依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook很奇妙,有机会要学习到,正好近段日子找来了MiniHook,就一起分享一下。
本篇文章是在x64下测试与分析jmp+offset类型的Hook,并且逆推测出热补丁的简单用法,MinHook它的中心就是覆盖重写并且可以复原。知道大概的思路后后让我们先来具体的实现MinHook再去做测试。
首先是堆的申请(申请PAGE_SIZE大小自动生长的堆),以下是实现与卸载
第一幕CreateHook
CreateHook 第一步:判断内存是否申请好了,是否可执行,判断是否已经Hook过了,如果已经Hook过,当让他返回其所在位置,因为此时他的地址位置已经可以用来启动Hoook,如下代码详解
CreateHook 第二步:进行Hook,在这里用到TRAMPOLINE结构体,我称之为跳板结构体,作为数据的中间传输过渡,TRAMPOLINE中几个注意的成员是1.Relay:在x64下Fake函数到原函数的中转站(x86用不到),2.OldIPs:原函数地址的偏移字节的保存3.NewIPs: 已经写入FakeFunctionAddress函数的字节数 4.MemorySlot:32字节原函数地址的前7个字节和跳转指令后的字节 5.PachAbove:热补丁
CreateHook 第三步: 分配一块内存用来保存Trampoline里的MemorySlot数据 ,以下是MemorySlot结构体定义(MemorySlot内存构建放到最后的代码链接中):
CreateHook 第四步:CreateTrampoline
Hook的Target我们这里先使用MessageBoxW,作为一个详细的jmp跳转流程解释,然后我写了几个汇编程序去进行其他E8,Call等指令的跳转实现,不过它是怎么跳转的我会在下面跳转的时候贴出来,首先来玩X64下的MessageBoxW,
CreateTrampoline 第一步:前面讲过我们是通过跳转加指令形式跳转到我们需要到的地址处,上面代码注释中我们了解到OldPos与NewPos是在MemorySlot创建过程对原函数地址的偏移字节的保存和已经写入FakeFunctionAddress函数的字节数,如下
CreateTrampoline 第二步:构建
MemorySlot,他的构建do-While()循坏,x64下的MessageBoxW跳转在7字节处,所以为了之后的恢复,我们需要把7字节的内容做一个保存,这就是所谓的OriginalDataBackup数组的作用->用来恢复也就是解除Hook,后面会逐步解析他的作用和位置,我们这里先记住即可
MemorySlot开始申请32字节的长度,,我们利用反汇编引擎HDE计算出MessageBoxW函数基地址,从上面给出的MessageBoxW的地址内容中,我们可以看到到达7字节的加法是先加4个字节到下一地址,然后加3到跳转位置,记录在OldPos,NewPos中
到达7字节了,我们就可以去做跳回MessageBoxW基地址加偏移跳转指令了
做了这么多工作,无非是为了MemorySlot里有数据前7个字节和跳转回MessageBoxW的基地址+偏移,构造好后,我们的TRAPOLINE结构也就完成
CreateHook第五步:添加Hook信息了(TRAMPLIONE结构体过渡),我们需要再去创建一个HookEntry的结构体去完成接收信息
当有了这个结构体后就可以去CreateHook了,下面是构建过程:
到这里为止终于是创建了Hook
第二幕 EnableHook
顾名思义就是启动Hook,显而易见得知它的作用无非就是覆盖原函数我们记录的那7字节,如下:
当需要解除Hook时候我们就可以用到在前面说过的OriginalDataBackup去恢复原函数,或者直接调用MemorySlot中记录下的原始序幕
第三幕 MessageBoxW测试
编译运行后出结果,先是原先的MessageBoxW:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)