1. 程式人生 > 實用技巧 >Detours學習1

Detours學習1

Using Detours

要繞過目標函式,必須具備兩個條件:一個是包含目標函式地址的目標指標,另一個是繞過函式。為了正確攔截目標函式、detour函式和目標指標必須具有完全相同的呼叫簽名,包括引數數和呼叫約定。使用相同的呼叫約定可以確保適當地保留暫存器,並確保堆疊在detour函式和目標函式之間正確對齊。

使用者程式碼必須包含detours.h標頭檔案並與detours連結detorus.lib庫。


// dllmain.cpp : 定義 DLL 應用程式的入口點。
#include "pch.h"
#pragma comment(lib, "detours.lib")

static VOID(WINAPI* TureSleep)(DWORD dwMilliseconds) = Sleep;

VOID WINAPI hkSleep(DWORD dwMilliseconds)
{
    ULONGLONG dwBeg = GetTickCount64();
    TureSleep(dwMilliseconds);
    ULONGLONG dwEnd = GetTickCount64();

    TCHAR buffer[512];
    _stprintf_s(buffer, sizeof(buffer) / sizeof(TCHAR), _T("Sleeped %llu milli sec"), dwEnd - dwBeg);
    MessageBox(NULL, buffer, _T(""), MB_OK);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    if (DetourIsHelperProcess())
    {
        return TRUE;
    }

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        DetourRestoreAfterWith();
        
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)TureSleep, hkSleep);
        DetourTransactionCommit();
        break;
    case DLL_PROCESS_DETACH:
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)TureSleep, hkSleep);
        DetourTransactionCommit();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    }
    return TRUE;
}

通過DetourAttach在Hook事務中呼叫可以攔截目標函式。通過對DetourTransactionBeginDetourTransactionCommit的呼叫來標記Hook事務。該DetourAttach帶有兩個引數:目標函式指標的地址和指向DetourFunction函式的指標。目標函式未作為引數提供,因為它必須已經儲存在目標指標中。

DetourUpdateThread提供在目標執行緒中宣告,以便在事務提交時更新指令指標。

DetourAttach分配和準備跳轉呼叫目標函式。Hook事務提交時,將重寫目標函式和跳轉函式Trampoline,並更新目標指標以指向跳轉函式

一旦Hook目標函式,對目標函式的任何呼叫都將通過DetourFunction函式重新路由。通過Trampoline呼叫目標函式時,DetourFunction函式負責複製引數。這很明確,因為目標函式是DetourFunction函式的內部呼叫函式。

通過DetourDetach在Hook事件中的呼叫,可以刪除對目標函式的攔截。與DetourAttach一樣,DetourDetach也有兩個引數:目標指標的地址和指向DetourFunction函式的指標。當Hook事務提交時,目標函式將被重寫並恢復為其原始程式碼,Trampline函式將被刪除,目標指標將恢復為指向原始目標函式。

如果需要將Hook的API注入到目標程式中,則Hook需要編譯成Dll。可以使用遠端執行緒注入、Dll劫持等技術。也可以使用DetourCreateProcessWithDllEx

DetourCreateProcessWithDlls將Dll注入到目標程序中。如果使用DetourCreateProcessWithDllExDetourCreateProcessWithDlls,則DllMain函式必須呼叫DetourRestoreAfterWith。如果Dll可以在x86和x64混合環境中使用,則DllMain函式必須呼叫DetourIsHelperProcess匯出為序號1,rundll32.exe以執行幫助任務來呼叫該API。


下面來注入一個剛剛到的Dll到一個程序中,測試一下效果

安裝Detours庫

VcPkg install detours:x86-windows
VcPkg install detours:x64-windows