SetWindowsHookEx functioning returning NULL

2020-06-23 06:40发布

I am working on DLL Injection but getting the error as
failed to hook process: 87 The parameter is incorrect.

The target process as well as the dll are both 64 bit.

The Injection code is:

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;
}

The dll that will be injected is as follows:

#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));
}

The def file is as follows:

LIBRARY "dll_to_inject"
EXPORTS
print_successful_injection

the DbgFunction works as follows:

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
}

I'm pretty new to stackoverflow so I hope I tried to provide as much as details necessary.

1条回答
劳资没心,怎么记你
2楼-- · 2020-06-23 07:03

SetWindowsHookEx fail if it called not for GUI thread. more exactly if Win32Thread field of KTHREAD is 0. you call SetWindowsHookEx too early - thread yet not GUI thread (not initialized gui subsystem). so you need wait for this, before call SetWindowsHookEx. not sure, are possible catch exactly moment (after thread call NtGdiInit), when already possible call SetWindowsHookEx, but simplest way call WaitForInputIdle(pi.hProcess, INFINITE) with handle of new created process and only after it return WAIT_OBJECT_0 call SetWindowsHookExW

also, as separate note - for what you allocate STARTUPINFO and STARTUPINFO from heap ? (and not free it late). simply declare it as local variables in function. also STARTUPINFO must be initialized, how minimum asSTARTUPINFO si = { sizeof(si) } ; also you not close process and thread handles

查看更多
登录 后发表回答