Detours是微软研究院的一个用于hook WinAPI的工具。
安装后安装目录的samples目录里面有很多项目。我们用到的是traceapi和withdll项目。
自定义traceapi
打开traceapi目录里面的_win32.cpp,可以看到已经默认hook了绝大部分的WinAPI。我们可以把大多数注释掉,只保留我们关心的几个函数,免得之后要分析的log过大。
以ReadProcessMemory为例,看看如何自定义trace的结果。在_win32.cpp,关于一个WinAPI函数会有四处地方:
第一处:
BOOL (__stdcall * Real_ReadProcessMemory)(HANDLE a0, LPCVOID a1, LPVOID a2, DWORD_PTR a3, PDWORD_PTR a4) = ReadProcessMemory;
第二处:
BOOL __stdcall Mine_ReadProcessMemory(HANDLE a0, LPCVOID a1, LPVOID a2, DWORD_PTR a3, PDWORD_PTR a4) { _PrintEnter("ReadProcessMemory(%p,%p,%p,%p,%p)n", a0, a1, a2, a3, a4); BOOL rv = 0; __try { rv = Real_ReadProcessMemory(a0, a1, a2, a3, a4); } __finally { _PrintExit("ReadProcessMemory(,,,,) -> %pn", rv); }; return rv; }
第三处
ATTACH(&(PVOID&)Real_ReadProcessMemory, Mine_ReadProcessMemory);
第四处
DETACH(&(PVOID&)Real_ReadProcessMemory, Mine_ReadProcessMemory);
如果不想trace某个函数,将第一、第二和第四处注释掉即可。
主要自定义的点在第二处,例如a2是buffer地址,a4是读取的字节数。当真正的ReadProcessMemory读取完毕后,我们就可以用这两个信息来看看究竟读了什么。因此在finally子句可以改成一下这样:
int size = (int) a4; char buf[MAXBUF]; PrintByte(buf, a2, size); _PrintExit("ReadProcessMemory(,,,,) -> %p,%p -> %sn", rv, a2, buf);
这里的PrintByte函数是将字节数组转为十六进制字符串。
使用
withdll的使用很简单,看看命令行说明即可。
下载安装打开DbgView。使用withdll启动目标程序并将自定义好的traceapi.dll注入进程,即可在DbgView的窗口里看到traceapi打印的信息了。