Отключение набора хуков с помощью SetWindowsHookEx несколько раз приводит к сбою перехваченного процесса

Я пытаюсь подключить события клавиатуры и мыши целевого приложения.
Я следил за таким вопросом Как подключить внешний процесс с помощью 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 и окно видимыми и скрытыми, чтобы увидеть, имеет ли это какое-то значение

Внутривенно Не удалось попробовать следующее из-за 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();
}
  1. SendMessageTimeout в методе DLL [HookDLL] При удалении немедленно происходит сбой приложения
  2. SendMessageTimeout в приложении [HookApp], похоже, не делает ничего полезного.
  3. FreeLibraryAndExitThread, похоже, не делает ничего полезного.
    Тем не менее, с 2 и 3, я думаю, что я могу установить крюк во второй раз. Без них первое отцепление вылетает из приложения.
  4. Я не смог попробовать предложение с использованием встроенного языка ассемблера из-за 64-битной архитектуры.

Пожалуйста помоги.

-3

Решение

для деинсталляции хука и выгрузки своей dll все что нужно — звоните UnhookWindowsHookEx для каждого дескриптора крюка, полученного предыдущим вызовом SetWindowsHookEx, все. тебе не нужно звонить FreeLibrary[AndExitThread] сам. система автоматического вызова FreeLibrary на крючке длл после UnhookWindowsHookEx callend, когда первое (любое) сообщение будет получено целевым потоком приложения и вызовом этого потока GetMessage или же PeekMessage, так что просто выгрузите свою DLL после нескольких UnhookWindowsHookEx — вам нужно опубликовать сообщение в ветке, для которой вы устанавливаете хук. если вы делаете это для конкретной нити (dwThreadId) — тебе нужно PostThreadMessageW(dwThreadId, WM_NULL, 0, 0); — система сама позвони FreeLibrary (вызывается из user32!__ClientFreeLibrary который звонил из ntdll!KiUserCallbackDispatcher — называется внутри GetMessage или же PeekMessage когда поток (или это окно) получил какое-либо сообщение)

вызов FreeLibrary от dll для себя — всегда ошибка — если предположить, что dll будет выгружен этим вызовом — куда мы вернемся после вызова? в незагруженное место. вызов FreeLibraryAndExitThread Существуют смысл в некоторых случаях, но только из потока, который вы создаете сами. вызов FreeLibraryAndExitThread из точки входа dll вообще фатальная ошибка — вы убиваете не сам поток, а поток, который вы убиваете — удерживаете критическую секцию (блокировку загрузчика) внутри которой называется точка входа dll — настолько фатальная ошибка. и вообще абсолютно бессмысленный звонок сюда — если вы говорите, получите DLL_PROCESS_DETACH это означает, что dll уже в процессе выгрузки. DLL_THREAD_DETACH — произвольный момент, почему и сколько раз вы пытаетесь вызвать unload для себя здесь? выходите из резьбы, удерживая широкий критический участок процесса без его освобождения. фатальная ошибка.

также потому что тот же поток, который установил хук, должен удалить его. — это неправда. другой поток от также может сделать это.

также StartTimer(); в вашем коде выглядят как подозрительные что делает этот код? есть и где вы отменяете таймер?

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]