• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Гайд: Отключаем CRT и Оптимизируем программу

Пожалуйста, обратите внимание, что пользователь заблокирован
смотреть LastError-ы и тд
Решил посмотреть и нашел очень странное явление.
При запуске точки входа GetLastError() возвращает 14007 (ERROR_SXS_KEY_NOT_FOUND, "The requested lookup key was not found in any active activation context.")
А с CRT GetLastError() возвращает 0.
Вот теперь интересные вопрос багается мой софт из-за этой ошибки или нет. И как её фиксить, если она происходит еще до моего кода?)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Код написан на чистом WinAPI (без stl и прочего). Буквально две функции.
Выкладывай код .

Лично у меня не удалось подружить COM и non-crt
Аналогично.

Не может быть проблем , по крайней мере сколько пишу, не сталкивался. Да, студия любит совать свой crt везде, но все же, почти все можно вырезать и отключить.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
При запуске точки входа GetLastError() возвращает
Если код начинается на твоей точке входа, то ничего фиксить нельзя , да и нереально. Разве что какие-то особенности компилятора.. покажи код или хотя бы бинарь, чтоб не угадывать.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Выкладывай код .
C++:
#include <Windows.h>

void SendButtons() {
    INPUT inpt[24];

    for (int i = 0; i < 24; i++) {
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = 0x44; // D
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = 0x44; // D
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        inpt[i].ki.dwFlags = KEYEVENTF_KEYUP;
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = VK_TAB; // TAB
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = VK_TAB; // TAB
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        inpt[i].ki.dwFlags = KEYEVENTF_KEYUP;
    }
    for (int i = 0; i < 24; i++) // нужно именно так, а не через SendInput(24, inpt, sizeof(INPUT))
    {
        SendInput(1, &inpt[i], sizeof(INPUT)); 
        Sleep(3);
    }
}

int main() {
    DWORD ccc = GetLastError(); // тут уже есть ошибка (14007)
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    HWND hWnd = FindWindowA(NULL, "...");
    WriteFile(hStdOut, "Checking ... window", sizeof("Checking ... window") - 1, NULL, NULL);
    ccc = GetLastError(); // всё та же ошибка (14007)
    while (hWnd == NULL) {
        WriteFile(hStdOut, ".", 1, NULL, NULL);
        hWnd = FindWindowA(NULL, "...");
        Sleep(3000);
    }
    WriteFile(hStdOut, "\nReady\n", sizeof("\nReady\n") - 1, NULL, NULL);
    ccc = GetLastError();  // всё та же ошибка (14007)
    while (true) {
        if (GetAsyncKeyState(0x44) & 0x8000) { // Кнопка D
            SendButtons();
        }
        Sleep(1);
    }
    return 0;
}

Правильный вывод при нажатии на D:
dd d d d d d

Без CRT разный вывод бывает
 
Пожалуйста, обратите внимание, что пользователь заблокирован

c0d3r_0f_shr0d13ng3r

In ever cases, runtime library is needed and the standard library could be dependent on runtime library.
If you disable c runtime library (which is mostly platform dependent) your program will not run.

C Run-Time library is the correct term.

Microsoft has put the C Standard Library and C Runtime Library together and just calls it C Run-Time Library.​

 
Пожалуйста, обратите внимание, что пользователь заблокирован
GetLastError имеет смысл получать непосредственно после вызова функции, которая этот код устанавливает. Если ты собираешь свой код без CRT (да и с CRT тоже), то в начале точки входа уж точно не имеет смысла его вызывать.

Все тот же код ошибки остается потому, что ошибки не было.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Без CRT разный вывод бывает
Четвертый параметр WriteFile не должен быть NULL.
У меня эта прога вообще никак не выводит d d, что так что иначе.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Четвертый параметр WriteFile не должен быть NULL.
Починил.

У меня эта прога вообще никак не выводит d d, что так что иначе.
А вы кнопку d жмете? Оно при нажатии на d начнет отправлять клавиши.

Вот странно, у меня такой вывод бывает:

Код:
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd
dd    d        dd

dd    dd    d    d       
dd    dd    d    d       
dd    dd    d    d       
dd    dd    d    d       
dd    dd    d    d       
dd    dd    d    d       

dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d

dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d
dd    d    d            d


dd    d    d            d

dd    d    d    dd    d
dd    d    d    dd    d
dd    d    d    dd    d
dd    d    d    dd    d
dd    d    d    dd    d


dd    d    d    dd    d
dd    d    d    dd    ddd    d    d    dd    d
dd    d    d    dd    d



ddd    d           
ddd    d           
ddd    d           
ddd    d           
ddd    d
А программа одна и та же.

А вот с CRT всегда стабильно. На другом компе тестил с CRT, там тоже работает стабильно.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
У меня код зависает на поиске окна с "...".

По поводу CRT. может, там буферизация консоли просто включается?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
У меня код зависает на поиске окна с "...".

По поводу CRT. может, там буферизация консоли просто включается?
Окно любое поставьте.

По поводу CRT. может, там буферизация консоли просто включается?
Думаю дело совсем не в консоли.

Вот обновленный код с проблемой
C++:
#include <Windows.h>

void SendButtons() {
    INPUT inpt[24];

    for (int i = 0; i < 24; i++) {
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = 0x44; // D
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = 0x44; // D
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        inpt[i].ki.dwFlags = KEYEVENTF_KEYUP;
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = VK_TAB; // TAB
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        i++;
        inpt[i].type = INPUT_KEYBOARD;
        inpt[i].ki.wVk = VK_TAB; // TAB
        inpt[i].ki.wScan = MapVirtualKeyA(inpt[i].ki.wVk, MAPVK_VK_TO_VSC);
        inpt[i].ki.dwFlags = KEYEVENTF_KEYUP;
    }
    for (int i = 0; i < 24; i++) // нужно именно так, а не через SendInput(24, inpt, sizeof(INPUT))
    {
        SendInput(1, &inpt[i], sizeof(INPUT));
        Sleep(3);
    }
}

int main() {
    while (true) {
        if (GetAsyncKeyState(0x44) & 0x8000) { // Кнопка D
            SendButtons();
        }
        Sleep(1);
    }
    return 0;
}
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Можно вангануть. Ну ты понимаешь, что массив инпутов у тебя не инициализируется и там может любой мусор быть? При этом dwflags ты не заполняешь в случае keydown. Да и другие элементы тоже. Обнули ее перед циклом.
 
In ever cases, runtime library is needed and the standard library could be dependent on runtime library.
If you disable c runtime library (which is mostly platform dependent) your program will not run.

C Run-Time library is the correct term.

Microsoft has put the C Standard Library and C Runtime Library together and just calls it C Run-Time Library.​

Ты не совсем понял про что мы говорим.Не советую использовать переводчик влезая в русскоязычные обсуждения.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Можно вангануть. Ну ты понимаешь, что массив инпутов у тебя не инициализируется и там может любой мусор быть? При этом dwflags ты не заполняешь в случае keydown. Да и другие элементы тоже. Обнули ее перед циклом.
Мда. Что-то я не подумал об этом. Причем сам всегда видел этот мусор.
C++:
RtlSecureZeroMemory(inpt, sizeof(INPUT) * 24);

Вставив это перед циклом с кнопками, всё заработало.
Большое спасибо, такая глупая ошибка, а я уж и не мог понять никак.

А с чем связано, что с CRT нет бага в этом месте? Имею ввиду, почему в сборке с CRT мусор никак не влиял на код
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
А с чем связано, что с CRT нет бага в этом месте?
Я, если честно, не помню по стандарту Сишечки, должен ли CRT обнулять структуры на стеке. Мне кажется, что не должен. Если должен, то это реализуется кодом из CRT, это бы объяснило твою проблему. Но вполне возможно, что просто так совпадало, что на стеке оставались нули, ну или не были взведены биты во флагах (CRTшный код, который вызывался до твоей точки входа оставлял мусор на стеке в таком виде, что у все тебя работало).
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я, если честно, не помню по стандарту Сишечки, должен ли CRT обнулять структуры на стеке. Мне кажется, что не должен. Если должен, то это реализуется кодом из CRT, это бы объяснило твою проблему. Но вполне возможно, что просто так совпадало, что на стеке оставались нули, ну или не были взведены биты во флагах (CRTшный код, который вызывался до твоей точки входа оставлял мусор на стеке в таком виде, что у все тебя работало).
Понял. В любом случае большое спасибо
 
А у меня без CRT не работают функции CopyMemory, RtlCopyMemory, ZeroMemory, в общем все которые работают с массивами.
C:
FILE_RENAME_INFO fRename;
ZeroMemory(&fRename, sizeof(fRename));
LPWSTR lpwStream = DS_STREAM_RENAME;
fRename.FileNameLength = sizeof(lpwStream);
CopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));

Студия ругается следующим образом:
error LNK2019: ссылка на неразрешенный внешний символ _memcpy в функции
error LNK2019: ссылка на неразрешенный внешний символ _memset в функции


Жалко, придется crt тянуть.
 
А у меня без CRT не работают функции CopyMemory, RtlCopyMemory, ZeroMemory, в общем все которые работают с массивами.
C:
FILE_RENAME_INFO fRename;
ZeroMemory(&fRename, sizeof(fRename));
LPWSTR lpwStream = DS_STREAM_RENAME;
fRename.FileNameLength = sizeof(lpwStream);
CopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));

Студия ругается следующим образом:
error LNK2019: ссылка на неразрешенный внешний символ _memcpy в функции
error LNK2019: ссылка на неразрешенный внешний символ _memset в функции


Жалко, придется crt тянуть.
Почему же? Целых три варианта:
A) Включи подставляемые функции (самый простой вариант)
B) Импортируй memset/memcpy из msvcrt.dll(а еще лучше из ntdll.dll) при помощи LoadLibrary/GetProcAddress
C) Реализуй эти функции сам(самый правильный вариант)
P.S: Если что, отпиши в пм, с радостью помогу.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
ZeroMemory
RtlSecureZeroMemory.
ZeroMemory это макрос, который в конечном итоге запускает memset.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
RtlSecureZeroMemory
а тут не мемсет внутри?? просто ее компилятор не вырезает в целях оптимизации.
 
а тут не мемсет внутри?? просто ее компилятор не вырезает в целях оптимизации.
Короче я понял, то что обертка поверх crt, то собственно и выдает ошибки. У меня и из за функции PathFileExistsW студия ругается:
ссылка на неразрешенный внешний символ __imp__PathFileExistsW@4
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх