HOOK原理分析

2016-05-19  本文已影响2226人  我家有个小太阳

先把用来HOOK的函数贴出来,然后逐过程解释
LPVOID DetourFunc(BYTE *src, const BYTE *dst, int len, int TYPE, PMEMORYINFO lpMemInfo) { if (lpMemInfo) { lpMemInfo->dwAddr = (DWORD)src; lpMemInfo->len = len; lpMemInfo->lpOriginCode = (PBYTE)malloc(len + 0x5); memcpy_m(lpMemInfo->lpOriginCode, src, len); lpMemInfo->IsHook = TRUE; } DWORD lpOld; VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &lpOld); switch (TYPE) { case DETOUR_TYPE_JMP: src[0] = 0xE9; break; case DETOUR_TYPE_CALL: src[0] = 0xE8; break; } *(DWORD*)(src + 1) = (DWORD)(dst - src) - 5; BYTE* Addr = src + 5; BYTE* dstination = src + len; BYTE* pCode = lpMemInfo->lpOriginCode + len; *pCode = 0xE9; *(DWORD*)(pCode + 0x1) = (DWORD)(dstination - pCode) - 5; while (Addr != dstination) { *Addr = 0x90; Addr++; } VirtualProtect(src, len, lpOld, &lpOld); VirtualProtect((LPVOID)lpMemInfo->lpOriginCode, len + 0x5, PAGE_EXECUTE_READWRITE, &lpOld); return (src+len); }

lpMemInfo是一个结构体,用来存放HOOK的一些信息,它的各属性的含义是
  • dwAddr: HOOK的目标地址

接下来解释代码
结构体初始化.png

方框中的部分分配了一段大小为len+0x5大小的空间,并把原始数据存入

绘图_刚分配后.png
置入跳转方式.png

上面这段代码的意思就是置入跳转方式,把HOOK的地址的第一个字节改为JMP或者CALL,0xE9代表JMP,0xE8代表CALL


*(DWORD*)(src + 1) = (DWORD)(dst - src) - 5;

上面这行代码的意思是将接下来的四个字节写入要跳转的地址,因为是指向DWORD的指针,所以是4个字节。所以在CALL之前进行HOOK的话,必须保证HOOK地址与CALL之间的距离大于5个字节


BYTE* pCode = lpMemInfo->lpOriginCode + len; *pCode = 0xE9;

修改后.png

上面代码的作用就是把lpOriginCode指向的空间的后5个字节变成一个跳转到HOOK地址加Len的地方

汇编片段.png

在上图中,如果我们的HOOK地址是0x0351C853,那么JMP语句跳转到CALL地址,0x0351C858,len为5


while (Addr != dstination) { *Addr = 0x90; Addr++; }

如果len > 5的话,将JMP语句到CALL之间的语句置为空指令nop(代码字节为0x90)
VirtualProtect函数的作用是改变一段内存区域的访问权限


最后函数的返回值为CALL的地址


下面是HOOK函数的使用方法

我的HOOK函数.png

_Skin()函数作为HOOK函数的*BYTE dst参数传入,当被HOOK的地址被运行时会跳转到_Skin()函数,pushad用来保护寄存器,之后我们可以调用自己的函数(这里为_Skin_Data())作其它处理


使用popad、popfd恢复寄存器后,我们需要把上面HOOK过程中被覆盖的代码加上去之后再调用reCall(HOOK函数的返回值)


HOOK函数中被保存的原始代码和结构体的一些属性这里并没有用到,可以省略
整个HOOK过程到此结束,作者Q49909509,欢迎交流-_-.

上一篇 下一篇

猜你喜欢

热点阅读