Detours是一个软件包,用于在应用程序下重新路由(拦截)Win32 API。
[Detours]
二、Detours使用
我们首先需要编译指定的库,如果我们需要拦截32位程序下的函数,就编译x86版本,如果用在64位下,则编译x64版本。这个编译就不说明了。
2.1、主要接口说明
主要使用到如下的接口:
1、DetourAttach&DetourDetach
LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer,
_In_ PVOID pDetour);
LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer,
_In_ PVOID pDetour);
前一个接口用于将拦截函数附加到目标函数,后一个接口用于取消目标函数的路由。
参数说明:
pp
Pointer :指向将附加到的目标指针的指针(地址)。
pDetour
:指向拦截函数的指针(地址)。
如果成功,则返回
NO_ERROR
;否则,返回错误代码。
在使用这两个接口前,需要调用下面的前置接口和提交接口
2、DetourTransactionBegin
3、 DetourUpdateThread
4、DetourTransactionCommit
2.2、代码示例
//附加拦截函数
void StartHook() {
//开始事务
DetourTransactionBegin();
//更新线程信息
DetourUpdateThread(GetCurrentThread());
//将拦截函数附加到原函数的地址上
DetourAttach(&(PVOID&)pfnOld, pfnNew);
//结束事务
DetourTransactionCommit();
//解除拦截函数
void EndHook() {
//开始事务
DetourTransactionBegin();
//更新线程信息
DetourUpdateThread(GetCurrentThread());
//将拦截函数从原函数的地址上解除
DetourDetach(&(PVOID&)pfnOld, pfnNew);
//结束事务
DetourTransactionCommit();
三、配合DLL注入使用Detours
Detours可以拦截我们想要拦截的函数,并获取或者修改函数调用信息,一般我们会编写一个dll,在dllmain中attach和detach我们的拦截函数,从而在目标进程加载我们dll时,拦截目标函数,在卸载dll时,恢复目标函数。那么远程进程注入,是一个不错的选择,可以在目标进程运行时,注入调试库,不影响目标进程的运行。DLL注入不是本章重点,所以,此处使用最简单的注入方式,也就是远程线程注入方式(仅学习使用,请勿用于非法用途,且这种方式也是最容易被发现的注入方式)。
我写了一个简单的dll注入+Detours拦截指定函数的源码(vs2022),有需要的可以下载参考下
GitHub - Prophecy2015/DLLInject
其中DLLInject是一个MFC编写的dll注入的工具,功能仅仅是向目标进程注入dll用的,需要使用管理员权限运行,不过,由于是注入工具,会被系统报病毒威胁。
TestAddDLL就是使用Detours编写的拦截Add方法的调试库
TestApp是持续调用Add方法的控制台程序,使用DLLInject向该程序注入TestAddDLL,即可打印拦截函数的内容。
3.1、找到拦截函数地址
要通过远程注入,拦截指定函数,首先就需要找到指定函数在指定进程加载后的虚拟内存空间地址,这样才能正确调用DetourAttach函数,毕竟该函数第一个参数就是待拦截的函数的地址。寻找函数地址的方法有很多,上述GitHub源码,使用了两种途径获取函数地址
3.1.1、通过导出表,查找导出函数
这种方式,适用于被导出的函数接口,这种函数接口,可以在PE文件的导出表中,找到对应的RVA,从而计算出VA地址,无需依赖dbghelp.dll接口就可以实现。
可以参考GetExportFunctionsVa函数的实现,这里涉及到对PE文件格式的解析,有兴趣的可以参考下我学习pe格式时,写的一个PETest工程(https://gitee.com/gaojunhuiwww/PETest.git),纯学习性质,大神勿喷
PVOID CMisc::GetExportFunctionsVa(const char* szModuleName, const char* szFuncName)
HMODULE hMod = ::GetModuleHandleA(szModuleName);
if (hMod == NULL)
DLL_TRACE(_T("Can not find %s!"), szModuleName);
return NULL;
DWORD dwFuncRva = GetExportFunctionsRva(hMod, szFuncName);
if (dwFuncRva == 0)
DLL_TRACE(_T("Can not find %s in %s!"), szFuncName, szModuleName);
return NULL;
DLL_TRACE(_T("%s!%s : %llX!"), szModuleName, szFuncName, (PVOID)((PBYTE)hMod + dwFuncRva));
return (PVOID)((PBYTE)hMod + dwFuncRva);
DWORD CMisc::GetExportFunctionsRva(HMODULE hModule, const char* strFuncName)
// 获取ExportsTableRva
DWORD dwExportTableRva = 0;
PBYTE pByte = (PBYTE)hModule;
PBYTE pTmp = pByte;
if (IMAGE_DOS_SIGNATURE == *(WORD*)pTmp)
//DOS头
IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pTmp;
pTmp += pDosHeader->e_lfanew;
if (IMAGE_NT_SIGNATURE != *(DWORD*)(PBYTE)pTmp)
return 0;
pTmp += sizeof(DWORD);
PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)pTmp;
pTmp += sizeof(IMAGE_FILE_HEADER);
// opt tou
if (IMAGE_NT_OPTIONAL_HDR32_MAGIC == *(WORD*)(PBYTE)pTmp)
// 32位头
dwExportTableRva = ((PIMAGE_OPTIONAL_HEADER32)pTmp)->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
else if (IMAGE_NT_OPTIONAL_HDR64_MAGIC == *(WORD*)(PBYTE)pTmp)
// 32位头
dwExportTableRva = ((PIMAGE_OPTIONAL_HEADER64)pTmp)->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pByte + dwExportTableRva);
for (int i = 0; i < pExportDir->NumberOfNames; i++)
std::string strName = (char*)((PBYTE)pByte + *(DWORD*)((PBYTE)pByte + pExportDir->AddressOfNames + i * sizeof(DWORD)));
if (strName == strFuncName)
WORD wOrdinal = *(WORD*)((PBYTE)pByte + pExportDir->AddressOfNameOrdinals + i * sizeof(WORD));
if (wOrdinal < pExportDir->NumberOfFunctions)
return *(DWORD*)((PBYTE)pByte + pExportDir->AddressOfFunctions + wOrdinal * sizeof(DWORD));
return 0;
3.1.2、通过dbghelp接口查询指定函数
这种方式,只要你有指定模块的pdb文件,你就可以找到该模块的大部分函数的地址,inline和被优化的函数除外,也包括了上诉的导出表函数。不过需要依赖dbghelp.dll。
可以参考GetFunctionsVaFromSymbols函数的实现
PVOID CMisc::GetFunctionsVaFromSymbols(PCTSTR szModuleName, PCTSTR szFunctionName, PCTSTR szSymPath/* = nullptr*/)
HMODULE hMod = 0;
HANDLE hProcess = 0;
DWORD64 BaseOfDll = 0;
PIMAGEHLP_SYMBOL pSymbol = NULL;
PVOID pRet = NULL;
DWORD Options = SymGetOptions();
Options = Options | SYMOPT_DEBUG;
SymSetOptions(Options);
if (szModuleName)
hMod = GetModuleHandle(szModuleName);
if (hMod == 0)
DLL_TRACE(_T("Cannot find module %s"), szModuleName);
return NULL;
hProcess = GetCurrentProcess();
BOOL bRet = SymInitialize(hProcess, 0, TRUE);
if (FALSE == bRet)
DLL_TRACE(_T("SymInitialize error ..."));
break;
TCHAR SymbolPath[256];
GetCurrentDirectory(sizeof(SymbolPath) / sizeof(TCHAR), SymbolPath);
if (nullptr != szSymPath)
_tcscat_s(SymbolPath, _T(";"));
_tcscat_s(SymbolPath, szSymPath);
_tcscat_s(SymbolPath, _T(";"));
_tcscat_s(SymbolPath, g_szPDBPath);
SymSetSearchPath(hProcess, SymbolPath);
TCHAR FileName[256];
GetCurrentDirectory(sizeof(FileName) / sizeof(TCHAR), FileName);
_tcscat_s(FileName, _T("\\"));
_tcscat_s(FileName, szModuleName);
BaseOfDll = SymLoadModuleEx(hProcess, NULL, FileName, NULL, (DWORD64)hMod, 0, NULL, 0);
if (BaseOfDll == 0)
DLL_TRACE(_T("SymLoadModule %s error code:%d"), FileName, GetLastError());
break;
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
MAX_SYM_NAME * sizeof(TCHAR) +
sizeof(ULONG64) - 1) /
sizeof(ULONG64)];
PSYMBOL_INFO pSym = (PSYMBOL_INFO)buffer;
pSym->SizeOfStruct = sizeof(SYMBOL_INFO);
pSym->MaxNameLen = MAX_SYM_NAME;
if (TRUE == SymFromName(hProcess, szFunctionName, pSym))
pRet = (PVOID)pSym->Address;
DLL_TRACE(_T("%s!%s: %llX"), szModuleName, szFunctionName, pRet);
DLL_TRACE(_T("Can not find symbol %s!%s"), szModuleName, szFunctionName);
} while (false);
if (BaseOfDll != 0)
BOOL bRet = SymUnloadModule(hProcess, BaseOfDll);
if (bRet == FALSE)
DLL_TRACE(_T("SymUnloadModule Failed! err:%d"), GetLastError());
BaseOfDll = 0;
SymCleanup(hProcess);
return pRet;
运行完成后可以看到Detours里面的src文件夹下面有detours.h与detours.cpp,在lib.x64文件夹下面有detours.lib,我们后续使用Detours就需要这几个文件。注意,这里使用这几个文件的需要将文件复制到项目下面来,打开你的项目文件,确保下面有这几个文件,因为vs添加文件的话是不会将文件复制过来的(踩坑之一)。这个时候需要先运行vs中的一个bat文件,我的路径如下,直接将这个文件拖入cmd命令窗口中。下载的时候记住你下载的位置,默认·下载的话一般在这里面。
Microsoft Research Detours是一款强大的Windows API监控与拦截工具包,被众多独立软件开发商和微软内部产品团队广泛采用。作为一款开源软件,Detours采用MIT许可证发布,为开发者提供了灵活的API调用监控、拦截与增强能力,是Windows平台下系统级编程的必备工具。
## 🚀 什么是Detours?它能做什么?
Detours本质上是一个用于监控和 ins
开发环境,WIN10 64bit, VS2022
首先在GITHUB下载源码。GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form.Detours is a software package for monitor...
Detours 是微软开发的一个强大的Windows API钩子库,用于监视和拦截函数调用。它广泛应用于微软产品团队和众多独立软件开发中,旨在无需修改原始代码的情况下实现函数拦截和修改。Detours 在调试、监控、日志记录和性能分析等方面表现出色,已成为开发者的重要工具。本章将指导读者编译并使用Detours库,通过实现一个简单的弹窗替换功能,帮助读者熟悉该库的使用技巧。
Detours 是Microsoft开发一个库,下载地址http://research.microsoft.com/en-us/projects/detours/,它具有两方面的功能:
1 拦截x86机器上的任意的win32 API函数。
2 插入任意的数据段到PE文件中,修改DDL文件的导入表。
Detours库可以拦截任意的API调用,拦截代码是在动态运行时加载的。Detours替换目标API最前面的几条指令,使其无条件的跳转到用户提供的拦截函数。被替换的API函数的前几条指令被保存到tram
Detours是微软开发的一个函数库,可用于捕获系统API。在用其进行程序开发之前,得做一些准备工作:一.下载Detours 在http://research.microsoft.com/sn/detours 可免费下载Detours,当前的最新版本是Detours Express 2.1 is available for immediate download under
1.5版本编译,用vs2003建一个win32工程,选lib项目。然后把所有的源文件加入进来,编译就可以了。2.1版本编译,同上,但可能出错,fatal error C1189: #error : Must define one of DETOURS_X86, DETOURS_X64, or DETOURS_IA64 在引用Detours的头文件之前补
在http://research.microsoft.com/sn/detours 可免费下载Detours,当前的最新版本是
Detours Express 2.1 is available for immediate download un
detours是微软提供的一套工具,主要用于win32 API的拦截。
准备工作(环境)
首先下载detours的资源,地址:https://github.com/microsoft/detours
下载到本地后解压至任意文件夹;
打开cmd终端进到这个文件夹下,键入nmake;
编译完成后:
新建一个工程,将include中的detours.h移动至工程文件下;
将lib.X64(X86也有对应目录)下的detours.lib移动至工程文件下;
示例代码:
#include &l
原文地址:http://www.codeproject.com/Articles/30140/API-Hooking-with-MS-Detours
在这篇文章里,我将要介绍API拦截技术的相关理论和实现方式。API拦截是一项强大的技术,他让你可以拦截某些函数,重定位到自定义的函数上。在将控制权交给原始API之前,你可以在这个自定义的函数里做任何想做的事。
本文中,我将讨论API拦
Detours 是一个用于在 ARM, ARM64, X86, X64 和 IA64 机器上拦截二进制函数的库。 Detours 最常用来拦截应用程序中的 win32 api 调用,比如添加调试工具。 拦截代码在运行时动态应用。
Detours 将目标函数的前几个指令替换为无条件跳转到用户提供的 detour 函数
它与WriteProcessMemory 有所不同
WritePro...
一般来说,使用Detours的代码都具有固定的模式。Detours 1.5和Detours 2.1的接口函数变了很多,这里按照2.1版本对基本的使用方法进行说明。常用的函数有下面几个:
DetourTransactionBegin():开始一次截获或者解除截获过程。
DetourUpdateThread():列入一个在DetourTransaction过程中要进行update的线程。这个函数的
Detours是微软开发的一个函数库,可用于捕获系统API。在用其进行程序开发之前,得做一些准备工作:一.下载Detours
在http://research.microsoft.com/sn/detours 可免费下载Detours
二.安装Detours
一路NEXT
三.生成Detours库
在安装后的文件夹下找不到直接可以拿来用的LIB文件
Microsoft Research Detours Package概述
Detours是一个用于在ARM, ARM64, X86, X64和IA64机器上拦截二进制函数的库。Detours最常用来拦截应用程序中的Win32 api调用,比如添加调试工具。拦截代码在运行时动态应用。Detours将目标函数的前几个指令替换为无条件跳转到用户提供的detour函数。来自目标函数的指令被放置在蹦床上。蹦床的地址放在目标指针中。detour函数可以替换目标函数,也可以通过目标指针作为子例程调用目标...