Detours学习1 - 开始使用Detours

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劫持等技术。也可以使用DetourCreateProcessWithDllExDetourCreateProcessWithDlls将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

posted @ 2020-12-19 16:21  非法关键字  阅读(1622)  评论(0编辑  收藏  举报