其实对于InlineHook来说,知识点仅仅只是是改写目标hook点的前几个字节改为jmp 目标例程。
Detours会在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数的调用引导到自己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+5作为Trampoline函数。
常用的函数有下面几个:
- DetourTransactionBegin() :开始一次Hook或者Unhook过程。
- DetourUpdateThread() :列入一个在DetourTransaction过程中要进行update的线程。这个函数的作用稍微有一些复杂。感兴趣的可以去了解一下。
- DetourAttach() :添加一个要Hook的函数。
- DetourDetach () :添加一个要Unhook的函数。
- DetourTransactionCommit() :执行当前的Transaction过程。在这个函数中才会真正进行Hook或者Unhook操作。前面三个函数都只是做一些记录工作。
案例: inline hook -- Hook MessageBox
原始函数情况如下:
Hook之后,继续执行:
强制性将这5个字节换成 jmp New_MessageBoxW (04010A0h)也就是强制跳转到拦截的新函数里面(这就是为什么会拦截的原因)
进入 New_MessageBoxW 内部:
内存:0x004100B0 6ec800d8 ?.?n 指向了一个全新的地址:保存着替换的函数头部几个字节的汇编代码
同时会将OLD_MessageBoxW 这个原本指向(MessageBoxW) 的函数指针 指向一个全新的地址,而这个地址的前5个字节就是从原本MessageBoxW处复制来的环境寄存器的数据,然后再jmp 76E0FED4 回到MessageBoxW中hook点之下的地方继续执行。
进入到原始函数的头几个字节的汇编指令,执行复原:
认真看这个 76C917B5 是不是就是A的首地址 再往后偏移5个字节,这样OldMesssageBoxW就能完成 原本messageBoxw的调用(所以在NewMessageBoxW不能再调用messageBoxw了,因为messageboxw的前5个字节已经修改成调用NewMessageBoxW,这样会造成死循环,应该调用OldMessageBoxw,因为这个OldMessageBoxw相当于未Hook前的Messageboxw)
指向完毕,跳转原Hook点jmp下方:
注意堆栈,再次回到 Hook函数中:
至此 InlineHook 完成;