Several programs crash when unhooking with UnhookW

2019-04-17 08:27发布

问题:

I am doing a global hook to add my DLL to the hook chain:

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

Inside my DLL I am using Detours to intercept several WINAPI function calls. Everything works fine, except for WaitForSingleObject calls. Whenever I add WaitForSingleObject to the detoured functions, several programs crash when I unhook my DLL (Chrome, Skype, ...). Here is how the DLL looks:

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);
}

Could someone help me to understand why this is happening and how I can get around that Problem? Thanks!

回答1:

You are detouring a function that almost any process uses. And it is particularly dangerous since it is very likely that such a process has a call on that function active. A blocking call in almost any case. As soon as it unblocks, the code will resume into your detour that is no longer there.

Kaboom.

Realistically, the only way to unload your detour is by logging out so that every process that could have been detoured is no longer running.



回答2:

I think this is happening because many programs (Chrome, Skype, ...) have a thread pool, where background thread[s] are waiting on WaitForSingleObject() for something interesting for them to happen, and when it does happen, that thread[s] wake up and do something.

So, your thread A is calling DetourDetach while another thread B of the same process is currently inside Mine_WaitForSingleObject() Then DLL unloads, and everything crashes. You can verify by using debugger, attach to that problematic process, set breakpoint in DLL_PROCESS_DETACH, and when the breakpoint will hit, look through the stacks of another threads for Mine_WaitForSingleObject.

I’m not sure how to fix. But, one way that you might try — enumerate threads, and call DetourUpdateThread() for every thread of the process. This way, maybe the Detours will do something about that.