我有以下代码。
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook()
{
HMODULE hmod = GetModuleHandle(0);
if (!(_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hmod, 0)))
{
OutputDebugString(TEXT("Failed to Install hook"));
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
SetHook();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
ReleaseHook();
break;
}
return TRUE;
}
我想设置一个钩子来对窗口操作做出反应。我对c++没有经验,所以在调试应用程序和理解我做错了什么的时候非常困难。
在我的 SetHook()
方法的SetWindowHookEx方法总是以代码1428失败。所以Callback方法(这里没有显示)从未被调用。
我到底做错了什么?
PS: 我使用registry:Path将.dll注入到进程中。Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
名称。AppInit_DLLS
据我所知,这是有效果的,因为我得到了 "Failed to Install hook "和 "Exiting SETHOOK METHOD "的调试信息。
你将0(也就是NULL)传给了 GetModuleHandle()
,所以你要检索的是 HMODULE
你的DLL被加载到的EXE文件的进程中。
进程的EXE文件的名称:参数
lpModuleName
被加载的模块名称(可以是.dll或.exe文件)......
如果这个参数为NULL,GetModuleHandle将返回一个用于创建调用进程的文件(.exe文件)的句柄。
你不能使用这个 HMODULE
安装 SetWindowsHookEx()
钩子回调的DLL中。 你需要使用DLL中自己的 HMODULE
本身,即作为输入参数提供给您的 DllMain()
,例如
HHOOK _hook = NULL;
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook(HMODULE hModule) // <-- ADD THIS PARAM
{
if (!_hook)
{
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hModule, 0); // <-- USE IT HERE
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
SetHook(hModule); // <-- PASS IT HERE
break;
case DLL_PROCESS_DETACH:
ReleaseHook();
break;
}
return TRUE;
}
也就是说,你想在全局范围内安装一个钩子(hMod != NULL
和 dwThreadId == 0
),所以你只需要调用一次 SetWindowsHookEx()
,它没有意义的调用它在 每一 进程,将您的DLL加载到该进程中。 你应该创建你自己的EXE,将你的DLL加载到内存中并调用 SetWindowsHookEx()
1次,例如。
HMODULE _hmod = NULL;
HHOOK _hook = NULL;
// be sure to export your hook functions from the DLL..
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook()
{
if (!_hook)
{
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, _hmod, 0);
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
_hmod = hModule;
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
}
return TRUE;
}
typedef void (*LPFN_SH)();
typedef void (*LPFN_RH)();
HMODULE hMod = LoadLibrary("my.dll");
LPFN_SH SetHook = (LPFN_SH) GetProcAddress(hMod, "SetHook");
LPFN_RH ReleaseHook = (LPFN_RH) GetProcAddress(hMod, "ReleaseHook");
...
SetHook();
...
ReleaseHook();
FreeLibrary(hMod);
你的DLL将被自动注入到每一个与你的DLL位数相匹配的运行进程中(这意味着你需要单独的DLL来钩住32位和64位进程),在你的EXE进程的生命周期内。 不需要使用 AppInit_DLLS
注册表键根本。
否则,如果你真的想使用 AppInit_DLLS
将你的 DLL 注入到每一个比特度匹配进程中,那么最好让 DLL 调用 SetWindowsHookEx()
以每线程为单位 (hMod == NULL
和 dwThreadId != 0
)而不是在全局的基础上,例如。
__declspec(thread) HHOOK _hook = NULL;
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook()
{
if (!_hook)
{
DWORD dwThreadId = GetCurrentThreadId();
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, NULL, dwThreadId);
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
SetHook();
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_DETACH:
ReleaseHook();
break;
}
return TRUE;
}
那么就不需要使用单独的EXE加载器了。