Я пытаюсь перехватить события клавиатуры и мыши целевого приложения.
Я следовал за вопросом SO Как перехватить внешний процесс с помощью SetWindowsHookEx и WH_KEYBOARD , и перехватчики правильно устанавливаются и удаляются с первого раза. Однако после того, как я удаляю ловушку один раз, а затем устанавливаю ее снова, попытка удалить ловушку во второй раз приводит к сбою целевого приложения. Цель ловушки - отслеживать время простоя приложения, чтобы я мог выполнять некоторые задачи во время простоя приложения.
Я прошу прощения за длину вопроса, но я попытался указать все детали, которые могут помочь
Спасибо
Мне нужно иметь возможность устанавливать и удалять хуки, основываясь на командах меню из иконки в системном трее. У меня есть консольное приложение [HookApp], которое вызывает методы установки и удаления в DLL [HookDLL]. Консольное приложение также создает окно для обработки событий меню. Я использую поток окна, чтобы фактически установить и удалить хуки, потому что тот же поток, который установил хук, должен удалить его. Консоль и окно должны быть невидимыми. Должен быть виден только значок на панели задач и соответствующее меню.
Я запускаю приложение для перехвата из командной строки с параметрами
я. ProcessId целевого процесса
II. Имя процесса
III. Простой [в секундах] - Простой перед запуском действия в DLL
Мне интересно, если таймер, который я запускаю в HookProcs, отвечает за сбой.
Журналы просмотра событий
Неверное имя приложения: notepad.exe, версия: 10.0.17134.1, отметка времени: 0x9d4727c2
Неверное имя модуля: HookDLL_x64.dll_unloaded, версия: 0.0.0.0, отметка времени: 0x5c31aabd
Код исключения: 0xc0000005
Смещение ошибки: 0x00000000000ba505
Идентификатор ошибочного процесса: 0x2bac
Кажется, что код исключения предполагает нарушение доступа к памяти.
Я пробовал следующее
Я.
а. Вызовите API SendMessageTimeout с HWND_BROADCAST из HookApp
б. Вызовите API SendMessageTimeout с HWND_BROADCAST из HookDLL
на основе Выгрузка DLL из всех процессов после отсоединения глобальной ловушки CBT
II.
а. Вызовите FreeLibraryAndExitThread API в методе DLLMain для DLL_PROCESS_DETACH AND DLL_THREAD_DETACH - вместе и поодиночке
на основании http://www.rohitab.com/discuss/topic/42505-unloading-dll-crashes-exe/
III. Сделали консоль HookApp и окно видимыми и скрытыми, чтобы понять, имеет ли это какое-то значение
IV. Не удалось попробовать следующее из-за 64-битной архитектуры
https://www.unknowncheats.me/forum/programming-for-beginners/73377-unload-injected-dll-thread-process.html
Другие ссылки, на которые я ссылался
а. Сбой нескольких программ при отсоединении от UnhookWindowsHookEx ()
б. Как правильно использовать SetWindowsHookEx & CallNextHookEx
с. Выгрузка внедренной DLL
д. 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();
}
- SendMessageTimeout в методе DLL [HookDLL] Удаление приводит к немедленному завершению работы приложения
- SendMessageTimeout в приложении [HookApp], похоже, не делает ничего полезного.
- FreeLibraryAndExitThread, похоже, не делает ничего полезного.
Тем не менее, с 2 и 3, я думаю, что я могу установить крюк во второй раз. Без них первый unhook вылетает приложение.
- Мне не удалось попробовать предложение с использованием встроенного языка ассемблера из-за 64-битной архитектуры.
Пожалуйста, помогите.