使用EasyHook挂钩CreateWindowExW时调用原函数的相关疑问
问题分析
- 你当前的写法会触发无限递归,最终导致栈溢出程序崩溃:你挂钩的目标就是user32.dll导出的
CreateWindowExW函数,当你在挂钩回调CreateWindowExW_Hook中直接调用CreateWindowExW时,调用的还是被Hook修改过入口的函数,会再次跳转到你的CreateWindowExW_Hook函数,永远不会执行原函数的逻辑。
正确实现方案
EasyHook提供了规范的原函数调用方式,你需要提前定义原函数的签名指针,存储未被Hook的原函数地址后调用即可,修改后的完整代码如下:
// 首先定义CreateWindowExW的函数指针签名 typedef HWND (__stdcall *PFN_CreateWindowExW)( DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ); // 全局变量存储原函数的可调用地址 PFN_CreateWindowExW g_pOriginalCreateWindowExW = nullptr; HWND __stdcall CreateWindowExW_Hook( DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ) { // 修改参数 X = 50; Y = 50; nWidth = 400; nHeight = 300; // 调用存储的原函数地址,不会触发Hook return g_pOriginalCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } extern "C" void __declspec(dllexport) __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* inRemoteInfo); void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* inRemoteInfo) { HOOK_TRACE_INFO hHook = { NULL }; // 先获取原函数地址 PVOID pCreateWindowExWAddr = GetProcAddress(GetModuleHandle(TEXT("User32")), "CreateWindowExW"); NTSTATUS result = LhInstallHook( pCreateWindowExWAddr, CreateWindowExW_Hook, NULL, &hHook); if (SUCCEEDED(result)) { // 获取可直接调用的原函数地址,存入全局变量 LhGetOriginalFunction(&hHook, (PVOID*)&g_pOriginalCreateWindowExW); ULONG ACLEntries[1] = { 0 }; LhSetExclusiveACL(ACLEntries, 1, &hHook); } }
补充说明
- 不需要额外定义同名的
CreateWindowExW函数,你只需要通过EasyHook提供的LhGetOriginalFunction接口获取绕过Hook的原函数地址调用即可,不会触发二次Hook。 - 如果你提前在安装Hook之前就备份原函数的入口机器码手动跳转也可以实现,但直接用EasyHook提供的接口兼容性更好,不需要处理不同系统下函数入口的差异。
内容的提问来源于stack exchange,提问作者user16872085
相关产品推荐
相关产品推荐

