您将 0(又名 NULL)传递给 GetModuleHandle(),因此您正在检索您的 DLL 加载到其进程中的 EXE 文件的 HMODULE:
参数
lpModuleName
已加载模块的名称(.dll 或 .exe 文件)...
如果此参数为 NULL,GetModuleHandle 返回用于创建调用进程的文件(.exe 文件)的句柄。
您不能使用 HMODULE 来安装 DLL 中的 SetWindowsHookEx() 挂钩回调。您需要使用 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(),在每个中调用它是没有意义的/em> 加载 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 将在 EXE 进程的整个生命周期内自动注入到与您的 DLL 位数相匹配的每个正在运行的进程中(这意味着您需要单独的 DLL 来挂钩 32 位和 64 位进程)。根本不需要使用AppInit_DLLS 注册表项。
否则,如果您真的想使用 AppInit_DLLS 将 DLL 注入每个位匹配进程,那么最好让 DLL 在每个线程的基础上调用 SetWindowsHookEx()(hMod == NULL 和 @ 987654339@) 而不是在全球范围内,例如:
__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 加载器了。