2607C++,使用微软detours勾挂工具

📅 2026/7/24 12:46:52
2607C++,使用微软detours勾挂工具
原文编译与使用微软DetoursHook库Detours是微软开发的一个监听和拦截调用函数的强大的窗口接口勾挂库.为了无需修改原代码时拦截和修改函数,它广泛应用在微软产品团队和众多独立软件开发中.Detours在调试,监听,记录日志和分析性能等方面表现出色,已变成程序员的重要工具.这里将指导读者编译并使用Detours库,实现简单弹窗替换功能,帮助读者熟悉该库的使用技巧.Detours是一个兼容多个窗口系列系统版本(包括窗口XP到窗口11)的工具库.它现在在MIT开源许可下发布,简化了你的使用许可进程,并允许社区使用开源工具和进程来支持其发展,当前该库的稳定版本为4.0. 1读者可如下官方链接自行下载到本地.Detours4.0.1:https://github.com/microsoft/Detours/releases,这里下载文件后打开目录,其中源目录下保存的是Detours库的源,而示例则是一些用例,当准备好后读者需要打开VS你命令提示符,可从开始菜单中找到VSTools工具菜单,并在其中找到VS20XXx86本地工具命令提示或DeveloperCommandPromptforVS20XX字样,此处以x86为例,在命令提示符中跳转到Detours源目录,运行nmake命令执行编译.如果一切顺利,这将会编译Detours库并生成要求的二进制文件,其中包含保存有头文件信息,而lib.X86则包含detours.lib库文件.接着打开VS工具,新建一个可执行控制台项并配置包含引用目录及库目录.接着来实现拦截并替换弹窗功能,在窗口中弹窗接口为MessageBoxW函数,首先需要定义OriginalMessageBoxW的指向原的MessageBoxW函数地址的函数指针.接着定义CustomMessageBoxW函数,在函数内首先按自定义内容替换弹窗提示,并用该参数调用OriginalMessageBoxW的原函数地址,以此来实现替代弹窗功能.#includeiostream#includeWindows.h#includedetours.h#pragmacomment(lib,detours.lib)//定义指向原MessageBoxW函数指针staticint(WINAPI*OriginalMessageBoxW)(_In_opt_ HWND hWnd,_In_opt_ LPCWSTR lpText,_In_opt_ LPCWSTR lpCaption,_In_ UINT uType)MessageBoxW;//自定义的MessageBoxW函数,用来替换原函数staticintWINAPICustomMessageBoxW(_In_opt_ HWND hWnd,_In_opt_ LPCWSTR lpText,_In_opt_ LPCWSTR lpCaption,_In_ UINT uType){//调用原的MessageBoxW函数,但修改了显示的文本returnOriginalMessageBoxW(hWnd,Lhello lyshark,LMsgBox,MB_OK);}接着就是封装勾挂与解挂的函数,分别定义这两个函数,其中InstallHook函数Detours事务的方式,按自定义的CustomMessageBoxW函数指针替换原的MessageBoxW函数指针,从而拦截并修改该函数的行为.相反,RemoveHook函数则类似事务机制,将自定义的CustomMessageBoxW函数指针替换回原的MessageBoxW函数指针,以恢复函数的原行为.//安装勾挂voidInstallHook(){//开始一个Detours事务if(DetourTransactionBegin()NO_ERROR){//更新当前线程以准备勾挂操作if(DetourUpdateThread(GetCurrentThread())NO_ERROR){//按自定义的函数指针替换原函数指针.if(DetourAttach((PVOID)OriginalMessageBoxW,CustomMessageBoxW)NO_ERROR){//提交事务,完成勾挂安装if(DetourTransactionCommit()NO_ERROR){printf(勾挂已成功安装.\n);return;}}}//如果任何步骤失败,则中止事务DetourTransactionAbort();}printf(安装勾挂失败.\n);}//移除勾挂voidRemoveHook(){//开始一个Detours事务if(DetourTransactionBegin()NO_ERROR){//更新当前线程以准备勾挂操作if(DetourUpdateThread(GetCurrentThread())NO_ERROR){//将自定义的函数指针替换回原函数指针if(DetourDetach((PVOID)OriginalMessageBoxW,CustomMessageBoxW)NO_ERROR){//提交事务,完成勾挂移除if(DetourTransactionCommit()NO_ERROR){printf(勾挂已成功移除.\n);return;}}}//如果任何步骤失败,则中止事务DetourTransactionAbort();}printf(移除勾挂失败.\n);}在程序入口处,分三次调用MessageBoxW函数,其中第一次及最后调用依次调用均在未勾挂状态下,第二次调用前InstallHook()安装勾挂,之后再调用MessageBoxW函数,并在调用结束后RemoveHook()移除勾挂,编译这段代码.intmain(intargc,char*argv[]){//显示原消息框MessageBoxW(NULL,Lhello world,LMsgBox,MB_OK);//安装勾挂并显示修改后的消息框InstallHook();MessageBoxW(NULL,Lhello world,LMsgBox,MB_OK);//移除勾挂并按原消息框恢复RemoveHook();MessageBoxW(NULL,Lhello world,LMsgBox,MB_OK);system(pause);return0;}使用x64dbg调试器加载运行代码,并查找到程序的入口处,因此处的入口处仅是一个main(intargc,char*argv[])所以,在汇编中可直接查找三个参数的关键变量位置,找到后即可定位到入口处,此时直接跟进去就可见主函数代码;当执行0x00321314处后则勾挂生效,当勾挂生效后则按自定义勾挂地址替换底部0x00321347处的地址,此时在其之上的入栈操作数将会失效;继续跟进0x00321347该地址,已按自定义的弹窗位置替换该地址中的入口处,此处是一个jmp无条件跳转,预示着将要转向.继续跟进该转向地址,则可见反汇编指令集,这里的代码重新入栈了新的串变量,并在入栈后调用了原MessageBoxW函数,并依次实现替换函数弹窗中的内容.此时,当继续调用原函数时,虽函数中的提示信息为你好世界但因为勾挂生效了则会按hellolyshark更改提示信息,以此来替换与更改函数功能.在实际应用中,一般DLL注入方式使用Detours库,这样更好地替换或修改第三方的功能,如改变弹窗提示.该方法可更高效地应用勾挂技术,实现对目标程序行为的控制和自定义.如如下的这段代码,当使用注入器把它注入到第三方进程中时,首先执行DLL_PROCESS_ATTACH即开始勾挂,在勾挂函数中DetourFindFunction查找到MessageBoxW函数的入口地址.并在OriginalMessageBoxW指针中保存它,并用DetourAttach勾挂它.#includewindows.h#includedetours.h#includedetver.h#pragmacomment(lib,detours.lib)//定义MessageBoxW函数指针类型staticint(WINAPI*OriginalMessageBoxW)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)NULL;//自定义的MessageBoxW函数intWINAPIMyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType){//可在此添加自定义逻辑returnOriginalMessageBoxW(hWnd,Lhello lyshark,lpCaption,uType);}//安装勾挂voidInstallHooks(){DetourRestoreAfterWith();//开始事务DetourTransactionBegin();//更新当前线程DetourUpdateThread(GetCurrentThread());//查找并拦截MessageBoxW函数OriginalMessageBoxW(int(WINAPI*)(HWND,LPCWSTR,LPCWSTR,UINT))DetourFindFunction(User32.dll,MessageBoxW);if(OriginalMessageBoxW!NULL){//开始勾挂DetourAttach((PVOID)OriginalMessageBoxW,MyMessageBoxW);}//提交事务DetourTransactionCommit();}//卸载勾挂voidUninstallHooks(){//开始事务DetourTransactionBegin();//更新当前线程DetourUpdateThread(GetCurrentThread());//撤销拦截MessageBoxW函数if(OriginalMessageBoxW!NULL){//解挂DetourDetach((PVOID)OriginalMessageBoxW,MyMessageBoxW);}//提交事务DetourTransactionCommit();}//DLL入口BOOL APIENTRYDllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){switch(ul_reason_for_call){caseDLL_PROCESS_ATTACH://禁止线程库调用DisableThreadLibraryCalls(hModule);//安装勾挂InstallHooks();break;caseDLL_THREAD_ATTACH:break;caseDLL_THREAD_DETACH:break;caseDLL_PROCESS_DETACH://卸载勾挂UninstallHooks();break;}returnTRUE;}当勾挂成功后则进程中,按hellolyshark提示替换任何调用弹窗的提示信息,而因未替换标题栏则依然会保持原状态.勾挂在安全领域的应用相当广泛,如可监听和拦截指定的API调用,检测解析器的行为,拦截网络通信函数,监听传输数据,拦截文件操作和注册表访问等等.