Функция SetWindowsHookEx, возвращающая NULL

Я работаю над DLL Injection, но получаю сообщение об ошибке
не удалось подключить процесс: 87 Параметр неверен.

Целевой процесс, а также DLL являются 64-битными.

Код впрыска:

BOOL HookInjection(TCHAR target[], TCHAR *dll_name)
{
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
    // SetWindowsHookEx can be used to inject a DLL into another process. A 32 - bit DLL cannot be injected into a 64 - bit process, 
    // and a 64 - bit DLL cannot be injected into a 32 - bit process.If an application requires the use of hooks in other processes, 
    // it is required that a 32 - bit application call SetWindowsHookEx to inject a 32 - bit DLL into 32 - bit processes, 
    // and a 64 - bit application call SetWindowsHookEx to inject a 64 - bit DLL into 64 - bit processes.The 32 - bit and 64 - bit DLLs must have different names.

    DbgPrint((char*)"[ ] loading module in local process");
    auto hdll = LoadLibrary(dll_name);
    //Load module ->Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded.

    DbgPrint((char*)"[+] loaded dll\n");

    typedef LRESULT(WINAPI * MyProc)(int code, WPARAM wp, LPARAM lp); // export from calc_dll.dll

    //GetProcAdress -> // GetPROCEDUREAdress Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).
    HOOKPROC addr = (HOOKPROC)(GetProcAddress(hdll, "print_successful_injection"));
    //auto mp = MyProc(GetProcAddress(hdll, "StartW"));
    //If you know who uses StartW, hush, its a secret ;)
    DbgPrint((char*)"[] It worked");
    auto pStartupInfo = new STARTUPINFO();
    auto pProcessInfo = new PROCESS_INFORMATION();


    DbgPrint((char*)"[ ] creating process to hook");
    CreateProcess(target,
        nullptr,
        nullptr,
        nullptr,
        FALSE,
        NORMAL_PRIORITY_CLASS,
        nullptr,
        nullptr,
        pStartupInfo,
        pProcessInfo);
    if (!pProcessInfo)
    {
        DbgPrint((char*)"[-] pprocessInfo fucked up");
    }

    if (!pProcessInfo->hProcess)
    {
        DbgPrint((char*)"[-] failed to create process");
        return FALSE;
    }
    DbgPrint((char*)"[+] Created hook process\n");

    DbgPrint((char*)"[ ] creating process hook");
    auto hProc = SetWindowsHookEx(WH_CBT,   // Installs a hook procedure that receives notifications useful to a CBT application
        addr,                                   // my proc symbol taken from the dll
        hdll,                               // dll containing my proc
        pProcessInfo->dwThreadId);          // dword to the thread (something something windows store) RTFM
    if (!hProc)
    {
        DbgPrint((char*)"[-] failed to hook process");
        //This is where the code fails ie hproc is NULL
        return FALSE;
    }
    DbgPrint((char*)"[+] hook injected");
    UnhookWindowsHookEx(hProc);

    return TRUE;
}

DLL, которая будет введена, выглядит следующим образом:

#include "stdafx.h"
#include<Windows.h>

LRESULT __stdcall print_successful_injection(int code, WPARAM w, LPARAM l)
{
    MessageBox(0, L"Successfully Injected!", L"Hello", MB_ICONINFORMATION);
    return (CallNextHookEx(NULL, code, w, l));
}

Файл def выглядит следующим образом:

LIBRARY "dll_to_inject"
EXPORTS
print_successful_injection

DbgFunction работает следующим образом:

VOID DbgPrint(char *msg)
{

#ifdef DEBUG
DWORD eMsgLen, errNum = GetLastError();//dword is unsigned int
LPTSTR lpvSysMsg; // __Out__ LPTSTR lpBuffer , A pointer to a buffer that receives the null-terminated string that specifies the formatted message

if (msg)
    printf("%s: ", msg);

//FORMAT_MESSAGE_ALLOCATE_BUFFER -> The function allocates a buffer large enough to hold the formatted message, and places a pointer to the allocated buffer at the address specified by lpBuffer.The lpBuffer parameter is a pointer to an LPTSTR
//FORMAT_MESSAGE_FROM_SYSTEM -> The function should search the system message-table resource(s) for the requested message
eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM,
    NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR)&lpvSysMsg, 0, NULL);

//If the function succeeds, the return value is the number of TCHARs stored in the output buffer, excluding the terminating null character.
//If the function fails, the return value is zero.

if (eMsgLen > 0)
    _ftprintf(stderr, _T("%d %s\n"), errNum, lpvSysMsg);
else
    _ftprintf(stderr, _T("Error %d\n"), errNum);
if (lpvSysMsg != NULL)
    LocalFree(lpvSysMsg);
#endif
}

Я довольно новичок в stackru, поэтому надеюсь, что попытался предоставить столько информации, сколько необходимо.

1 ответ

SetWindowsHookEx сбой, если он вызван не для потока графического интерфейса. точнее если Win32Thread поле KTHREAD 0. Вы звоните SetWindowsHookEx слишком рано - поток еще не поток GUI (не инициализирована подсистема GUI). так что нужно подождать до звонка SetWindowsHookEx, не уверен, возможен ли уловить ровно момент (после вызова потока NtGdiInit), когда уже можно позвонить SetWindowsHookEx, но самый простой способ позвонить WaitForInputIdle(pi.hProcess, INFINITE) с дескриптором нового созданного процесса и только после его возврата WAIT_OBJECT_0 вызов SetWindowsHookExW

также, как отдельное примечание - для чего вы выделяете STARTUPINFO а также STARTUPINFO из кучи? (и не бесплатно это поздно). просто объявите это как локальные переменные в функции. также STARTUPINFO должно быть инициализировано, как минимум, какSTARTUPINFO si = { sizeof(si) }; также вы не закрываете процесс и нити обрабатываете

Другие вопросы по тегам