我正在尝试挂钩目标应用程序的键盘和鼠标事件。我遵循了 SO question How to hook external process with SetWindowsHookEx 和 WH_KEYBOARD,并且第一次正确安装和卸载了这些钩子。但是,在我卸载钩子一次然后再次安装后,第二次尝试卸载钩子会使目标应用程序崩溃。钩子的目的是监控应用程序空闲时间,以便我可以在应用程序空闲时执行一些任务。对于问题的长度,我深表歉意,但我试图提供所有可能有帮助的细节谢谢
我需要能够根据系统托盘图标中的菜单命令安装和卸载挂钩。我有一个控制台应用程序 [HookApp],它调用 DLL [HookDLL] 中的安装和卸载方法。控制台应用程序还创建一个窗口来处理菜单事件。我使用窗口的线程来实际安装和卸载钩子,因为安装钩子的同一线程必须卸载它。控制台和窗口都必须是不可见的。只有系统托盘图标及其相关菜单必须可见。我从命令行使用参数 i 启动挂钩应用程序。目标进程的ProcessId ii。进程名称 iii. 空闲时间 [以秒为单位] - 在 DLL 中启动操作之前的空闲时间我想知道我在 HookProcs 中启动的计时器是否对崩溃负责。
事件查看器日志错误应用程序名称:notepad.exe,版本:10.0.17134.1,时间戳:0x9d4727c2 错误模块名称:HookDLL_x64.dll_unloaded,版本:0.0.0.0,时间戳:0x5c31aabd 异常代码:0xc0000005 错误偏移量:0x00000000000ba505 错误进程: 0x2bac
异常代码似乎表明内存访问冲突。
我尝试了以下 I.a. 从 HookApp b 调用带有 HWND_BROADCAST 的 SendMessageTimeout API。使用 HWND_BROADCAST 从 HookDLL 调用 SendMessageTimeout API,基于Unloading DLL from all processes after unhook global CBT hook
二、一个。在 DLL_PROCESS_DETACH 和 DLL_THREAD_DETACH 的 DLLMain 方法中调用 FreeLibraryAndExitThread API - 一起和单独基于http://www.rohitab.com/discuss/topic/42505-unloading-dll-crashes-exe/
三、使 HookApp 控制台和窗口可见和隐藏,看看它是否有任何区别
四。由于 64 位架构,无法尝试以下操作 https://www.unknowncheats.me/forum/programming-for-beginners/73377-unload-injected-dll-thread-process.html
我提到的其他链接 使用 UnhookWindowsHookEx() 解除挂钩时,多个程序崩溃 b. 如何正确使用 SetWindowsHookEx & CallNextHookEx c. 卸载注入的 DLL d. FreeLibraryAndExitThread 在卸载注入的 DLL 时使程序崩溃
//Code in the DLL
extern "C" __declspec(dllexport) void install(unsigned long threadID,int _nIdleTime) {
nIdleTime = _nIdleTime;
Log(L"install proc called from app: _nIdleTime", _nIdleTime);
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinst, threadID);
hhMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, hinst, threadID);
logger->Log("Install");
logger->Log("Keyboard", (LONG)hhKeyboard);
logger->Log("Mouse", (LONG)hhMouse);
}
//Uninstall the dll from the Target Process
DWORD WINAPI UnInjectDLLFromTarget() {
uninstall();
//DWORD_PTR dwResult = 0;
//SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
StartTimer();
Beep(1000, 20);
return CallNextHookEx(hhKeyboard, code, wParam, lParam);
}
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
// StartTimer();
//Beep(1000, 20);
return CallNextHookEx(hhMouse, code, wParam, lParam);
}
BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in DWORD fdwReason, __in LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_DETACH || fdwReason==DLL_THREAD_DETACH) {
FreeLibraryAndExitThread(hinstDLL, 0);
return 0;
}
}
//Code in the Application [HookApp]
Similar to [But not exactly the same - It is a bit more involved because of the need to create the message pump and the menu event handling window]
HINSTANCE hinst = LoadLibrary(_T("MyDLL.dll"));
if (hinst) {
typedef void (*Install)(unsigned long);
typedef void (*Uninstall)();
Install install = (Install) GetProcAddress(hinst, "install");
Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");
install(threadID);
Sleep(20000);
uninstall();
}
- DLL [HookDLL] 方法中的 SendMessageTimeout 卸载立即使应用程序崩溃
- 应用程序 [HookApp] 中的 SendMessageTimeout 似乎没有做任何有用的事情。
- FreeLibraryAndExitThread 似乎没有做任何有用的事情。但是,使用 2 和 3,我想我可以第二次安装挂钩。没有它们,第一次取消挂钩会使应用程序崩溃。
- 由于 64 位架构,我无法尝试使用内联汇编语言的建议。
请帮忙。