Detours是一个用于在Windows上监视和检测API调用的软件包。
Detours 是一个由 Microsoft Research 开发的库,它允许开发人员在运行时动态地拦截(或“钩子”)Windows API 函数调用。这对于诸如调试、日志记录、模拟、扩展或修改应用程序行为等任务特别有用。通过使用 Detours,开发者可以透明地替换任何已存在的函数,同时保持其原始功能(如果需要)的可用性。

Detours 的工作原理是通过修改目标函数的地址解析表(IAT, Import Address Table)或函数指针,将调用重定向到一个新的函数,这个函数被称为“trampoline”。这个新的函数会执行所需的自定义代码,然后可以选择性地调用原始函数,或者完全忽略它。

使用 Detours 时需要谨慎,因为它允许开发者在运行时修改正在运行的程序的行为。如果修改不当,可能会导致程序崩溃、数据损坏或其他不可预见的问题。因此,在使用 Detours 进行开发时,最好先在非生产环境中进行彻底的测试。

值得注意的是,由于 Detours 修改了 Windows API 的底层机制,因此它可能与某些安全软件(如防病毒程序)发生冲突。在部署使用 Detours 的应用程序时,可能需要与这些软件供应商进行协调。

另外,虽然 Detours 是一个强大的工具,但它并不是解决所有问题的最佳方法。在某些情况下,使用其他技术(如插件系统、代理服务器或虚拟化)可能更为合适。因此,在选择使用 Detours 之前,最好先评估其他可用的选项。

样例一

#include<Windows.h>
#include<stdio.h>
#include<detours/detours.h>

// 声明一个函数指针OldMessageBoxA,指向MessageBoxA。
static int(WINAPI* OldMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) = MessageBoxA;

// 自定义函数MyFunction0,当调用MessageBoxA时,会跳转到此处。
int WINAPI MyFunction0(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    // 执行特定的MessageBoxA函数
    return OldMessageBoxA(NULL, "Hook Success!", "Warning", MB_OKCANCEL);
}
int main()
{
    // 开始
    DetourTransactionBegin();
    // 更新到线程
    DetourUpdateThread(GetCurrentThread());
    // 附加HOOK
    DetourAttach(&(PVOID&)OldMessageBoxA, MyFunction0);
    
    // 提交
    DetourTransactionCommit();

    // 调用MessageBoxA,会转到MyFunction0
    MessageBoxA(0, 0, 0, 0);

    // 移除HOOK
    DetourDetach(&(PVOID&)OldMessageBoxA, MyFunction0);
    return 0;
}

基于detours的Windows Hook_github

样例二:动态链接库

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include<detours.h>
void HookOn();
void HookOff();

static int (WINAPI* OldMesssageBoxA)
(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType
    ) = MessageBoxA;

static int (WINAPI* OldMesssageBoxW)
(
    HWND hWnd,
    LPCWSTR lpText,
    LPCWSTR lpCaption,
    UINT uType
    ) = MessageBoxW;// 注意了,自定义函数得和被 HOOK 的函数一样,否则会发生异常。
int WINAPI MyFunction0
(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType
);

int WINAPI MyFunction1
(
    HWND hWnd,
    LPCWSTR lpText,
    LPCWSTR lpCaption,
    UINT uType
);

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        HookOn();
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        HookOff();
        break;
    }
    return TRUE;
}

void HookOn()
{
    //开始事务
    DetourTransactionBegin();
    //更新线程信息  
    DetourUpdateThread(GetCurrentThread());
    //将拦截的函数附加到原函数的地址上,这里可以拦截多个函数。
    DetourAttach(&(PVOID&)OldMesssageBoxA, MyFunction0);
    DetourAttach(&(PVOID&)OldMesssageBoxW, MyFunction1);
    //结束事务
    DetourTransactionCommit();
}

void HookOff()
{
    //开始事务
    DetourTransactionBegin();
    //更新线程信息 
    DetourUpdateThread(GetCurrentThread());
    //将拦截的函数从原函数的地址上解除,这里可以解除多个函数。
    DetourDetach(&(PVOID&)OldMesssageBoxA, MyFunction0);
    DetourDetach(&(PVOID&)OldMesssageBoxW, MyFunction1);
    //结束事务
    DetourTransactionCommit();
}
// 调用被 HOOK 的函数可以用被 HOOK 函数的指针,不能用原函数。
int WINAPI MyFunction0(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    return OldMesssageBoxA(NULL, "Hooking your MessageBoxA!", "Warming", MB_OKCANCEL);
}

int WINAPI MyFunction1(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
    return OldMesssageBoxW(NULL, L"Hooking your MessageBoxW!", L"Warming", MB_OKCANCEL);
}

DLL生成设置为多线程:

基于detours的Windows Hook_Windows_02

基于detours的Windows Hook_#include_03

相关链接

https://mp.weixin.qq.com/s/wbsjxv7Zt67pMi5ZYD0cfQ

https://github.com/microsoft/Detours

https://github.com/microsoft/Detours/wiki

https://idiotc4t.com/persistence/detous-inline-hook#inline-hook-jian-jie

https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md