fishHook原理分析

463 阅读2分钟

MachO

首先我们要了解一个东西。我们写好的代码,生成的 iOS 程序其实是一个可执行文件。这个文件格式是 MachO 格式,所以一般我们称其为 MachO 文件。在刚才的 APP 包里面,它长这样:

MachO.jpeg

这个文件里面包含的就是数据和指令。比如你定义的类、方法、全局变量、方法实现等等。我们为什么要讨论 MachO?因为结合上面的疑问我们思考一个问题:自定义函数和系统函数,在文件位置上有什么区别?

  • 自定义函数在本 MachO 文件中,在运行时刻进入内存,自定义函数在本镜像文件中。
  • 系统函数在系统框架中,在运行时刻进入内存,系统函数在系统的动态库中,比如 NSLogFundation 这个镜像文件中。(需要借助 PIC技术 去符号寻址) 那既然如此我们就可以得到这样的结论:自定义的函数,在编译时刻,编译器就可以确定函数的实现地址(在 MachO 文件中的偏移地址)。但是系统函数是没办法知道的。那么在 CPU 执行我们的代码的时候,我们是如何告诉 CPU ,我们需要调用系统函数。以及如何知道系统函数的地址的呢?这里就要提到 PIC 技术了。

PIC(Position Independ code)技术

PIC翻译过来就是位置独立代码。

比如当你的程序要调用一个 MachO 外部函数的时候,编译器是没办法知道该函数的地址的。所以它在 MachO 文件里面生成一个列表,列表里面放指针。让当前的系统函数调用指向这个列表里面对应的指针。等到我们的 MachO 文件加载进入内存时,再将系统函数的真实地址,一个一个的赋值给列表中的指针。

  • 那么这个列表,我们称为符号表。
  • 这里面的指针,我们称为符号。
  • 给里面的指针赋值的过程,我们称为符号绑定。

那么说到这里,我想很多童鞋已经猜到了。fishhook 之所以 HOOK 不了自定义的函数,就是因为自定义的函数没有通过符号寻找地址这个过程。而系统函数是通过符号去绑定实现地址的。fishhook 就是利用这一点,去修改了系统函数的符号达到 HOOK 的目的。其实我们通过fishhook 的函数名称就不难看出来 rebind_symbols 符号重绑定。