SetWindowsHookEx函数返回NULL

我正在处理DLL注入,但得到错误
无法挂钩进程: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 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 } 

我是stackoverflow的新手,所以我希望我尽量提供必要的细节。

如果它不调用GUI线程, SetWindowsHookEx失败。 更确切地说,如果Win32Thread字段为0.你太早调用SetWindowsHookEx – 线程但不是GUI线程(未初始化的gui子系统)。 所以你需要等待这个,然后再调用SetWindowsHookEx 。 不确定,有可能捕捉到正确的时刻(在线程调用NtGdiInit ),当已经可能调用SetWindowsHookEx ,但最简单的方法是调用WaitForInputIdle(pi.hProcess, INFINITE)并使用新创建进程的句柄并且只有在它返回WAIT_OBJECT_0调用SetWindowsHookExW

另外,作为单独的注释 – 你从堆中分配STARTUPINFOSTARTUPINFO是什么? (而不是免费提供)。 简单地将它声明为函数中的局部变量。 还必须初始化STARTUPINFOSTARTUPINFO si = { sizeof(si) }最小值; 你也不要关闭进程和线程句柄