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;
}
样例二:动态链接库
// 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生成设置为多线程:
相关链接
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