Hook专题1-inline hook
学一学 hook 专题,今天是 inline hook。
课堂笔记
hook概念
hook 就是钩子,是一种劫持技术,把原本执行的函数替换,替换为我自己的一个函数。当然在学 pwn 的时候,也有接触过 hook,就是 malloc_hook 和 free_hook。这些 hook 本意是为了开发者方便调试自己编写的 malloc 或者 free 函数去使用的,比如我自己写了一个 free 函数,我想测试一下性能,那我直接 __free_hook=myfree 就可以测试了,但是没想到就一直被打,直到 glibc 2.34 版本,这些 hook 被彻底删除。
inline hook的用法
inline hook(内联钩子),是指在函数的代码当中的一个地方(一般是代码开头),写上跳转指令,跳转到我们执行的函数,跳转完成之后,为了保持函数正常运行我们可能会释放钩子(unhook),把程序放回原来的位置,或者是直接执行完自己的代码就结束。
无条件跳转指令编码
一般,无条件跳转指令编码为 E9 + 32位小端序整型(根据 %rip 寄存器寻址),比如 E9 05 00 00 00 表示跳转自己后五个字节,但是需要注意的是,跳转后五个字节是指执行完这个指令之后的那个字节开始算的。
hook实战
在 VS 当中新建一个动态链接库(dll)项目。比如我们要 hook 一个 MessageBoxA 函数,我们就先获取这个函数的地址,然后找到前五个字节进行替换,跳转到我们自己写的函数当中。
全局变量申请两个字节数组,一个是原字节,一个是被 hook 之后的字节,再申请一个函数指针来指向我们要 hook 的函数。
先把原字节取出来,保存在缓冲区中,然后再计算我们函数地址到 hook 位置的一个偏移,构造好 jmp 语句。因为我们这里hook 只更改参数,需要用到下面的逻辑,所以在自己的函数中,我们调用 MessageBoxA 之前先把钩子取消掉,等待执行完毕之后,再把钩子挂会去就可以了。
dllmain:
1 |
|
先写一个待 hook 的程序。
demo:
1 |
|
把两个都编译好之后,运行 test.exe,用注入器进行 dll 注入,再次弹窗可以发现已经成功被 hook。
课外研究
这次除了上课听的内容以外,还有很多收获。第一个就是说,我在 hook 的时候,看 WriteProcessMemory 函数参数太多了,想着写字节嘛, memcpy 也是一样的,结果出现了一个问题,就是注入并没有成功。
仔细去查的时候发现了,权限不足,那么为什么 WriteProcessMemory 函数就可以注入成功呢,它内部有一个修改内存权限的操作导致了我们写入可以成功。
按照老师的说法,因为WriteProcessMemory函数是一个调试用的API函数,权限可能比较大,能突破这个限制,关于我们队师傅对于这个 WriteProcessMemory 的解释在这里。大概就是说,微软文档写的是一定要内存权限,但是实际上通过调试可以发现它内部会调用一个 函数去修改它的内存权限然后写入。
总之这里也是长一个心眼吧,最最关键的是,会用IDA去动调了,而且貌似操作不难,也算迈出了第一步hhh。