在使用 Detours 劫持之前必须得拥有这两个东西:detours.h 和 detours.lib。
为了这两个东西我真的是弄了大半天,本着自己动手丰衣足食的思想:
我去 GitHub 克隆了一份来自己编译,对着网上的教程弄,在编译的时候就是各种 bug。
试了一次又一次,算了还是找别人编译好了的用吧!目前最新版本是 Detours 4.01 版。
拿到编译好的头文件和库后,我放到 VC6.0 相应的文件中去,结果在编程时发现头文件出错!
这时我就懵逼了,最后发现是因为 VC6.0版本太低导致的。因此最后便放到 VS2017 中去了。
说到这里,如果你不想自己动手尝试的话,这里给你编译好的 Detours 库。 请点击下载!
关于 Detours 里的函数发现网上并没有比较详细的介绍:这里就借鉴一下别人的博客吧!
这里我们同样来拦截两个函数:通常情况下代码是这样的:
#include "stdafx.h" #include<detours.h> #include<Windows.h> #pragma comment(lib,"detours.lib") 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); }
这段代码是在 VS2017 上生成的,我一般都是在虚拟机里运行的,所以需要进行一些设置:
调试 ---> Dll 属性 ---> C/C++ ---> 代码生成 ---> 运行库---多线程/MT,这样设置完后就可以了。
我们将生成的 dll 文件注入到记事本后,会看到这样: