Сбой нескольких программ при отсоединении от UnhookWindowsHookEx()

Я делаю глобальный хук, чтобы добавить мою DLL в цепочку хуков:

HHOOK handle = SetWindowsHookEx(WH_CALLWNDPROC, addr, dll, 0);

Внутри моей DLL я использую Detours для перехвата нескольких вызовов функций WINAPI. Все работает отлично, за исключением вызовов WaitForSingleObject. Всякий раз, когда я добавляю WaitForSingleObject к удаленным функциям, некоторые программы завершают работу, когда я отсоединяю свою DLL (Chrome, Skype, ...). Вот как выглядит DLL:

DWORD (WINAPI* Real_WaitForSingleObject)( HANDLE hHandle, DWORD dwMilliseconds) = WaitForSingleObject;
DWORD WINAPI Mine_WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {

    switch(Reason) {
        case DLL_PROCESS_ATTACH: 
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourAttach(&(PVOID&)Real_WaitForSingleObject, Mine_WaitForSingleObject);
            DetourTransactionCommit();
            break;
        case DLL_PROCESS_DETACH: 
            DetourTransactionBegin(); 
            DetourUpdateThread(GetCurrentThread());
            DetourDetach(&(PVOID&)Real_WaitForSingleObject, Mine_WaitForSingleObject);
            DetourTransactionCommit();
            break;
        case DLL_THREAD_ATTACH:

            break;
        case DLL_THREAD_DETACH:

            break;
    }
    return TRUE;
}
DWORD WINAPI Mine_WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) {

    return Real_WaitForSingleObject(hHandle, dwMilliseconds);
}

extern "C" __declspec(dllexport) int meconnect(int code, WPARAM wParam, LPARAM lParam) {

    return CallNextHookEx(NULL, code, wParam, lParam);
}

Может ли кто-нибудь помочь мне понять, почему это происходит и как я могу обойти эту проблему? Спасибо!

2 ответа

Вы обходите функцию, которую использует практически любой процесс. И это особенно опасно, поскольку весьма вероятно, что такой процесс вызовет активную функцию. Блокирующий вызов практически в любом случае. Как только он разблокируется, код возобновит ваш обходной путь, которого больше нет.

Kaboom.

Реально, единственный способ разгрузить ваш обходной путь - это выйти из системы, чтобы все процессы, которые могли быть отклонены, больше не выполнялись.

Я думаю, что это происходит потому, что многие программы (Chrome, Skype, ...) имеют пул потоков, где фоновые потоки ожидают в WaitForSingleObject() чего-то интересного для них, и когда это происходит, этот поток проснись и сделай что-нибудь.

Итак, ваш поток A вызывает DetourDetach, в то время как другой поток B того же процесса в данный момент находится внутри Mine_WaitForSingleObject(). Затем DLL выгружается, и все вылетает. Вы можете проверить с помощью отладчика, присоединиться к этому проблемному процессу, установить точку останова в DLL_PROCESS_DETACH, и когда точка останова достигнет, просмотрите стеки других потоков для Mine_WaitForSingleObject.

Я не уверен, как это исправить. Но есть один способ, который вы можете попробовать - перечислить потоки и вызвать DetourUpdateThread() для каждого потока процесса. Таким образом, возможно, Detours сделает что-то с этим.

Другие вопросы по тегам