fishhook 利用了 MachO 的动态绑定机制,苹果的共享缓存库不会被编译进我们的 MachO 文件,而是在动态链接(依靠动态连接器 dyld)时才去重新绑定。苹果采用了 PIC(Position-independent code)技术成功让 C 的底层也能有动态的表现:
编译时在 Mach-O 文件 _DATA 段的符号表中为每一个被引用的系统 C 函数建立一个指针(8 字节的数据,放的全是 0),这个指针用于动态绑定时重定位到共享库中的函数实现。
在运行时当系统 C 函数被第一次调用时会动态绑定一次,然后将 Mach-O 中的 _DATA 段符号表中对应的指针,指向外部函数(其在共享库中的实际内存地址)。
fishhook 正是利用了 PIC 技术做了这么两个操作:
将指向系统方法(外部函数)的指针重新进行绑定指向内部函数/自定义 C 函数。
将内部函数的指针在动态链接时指向系统方法的地址。