FishHook 原理探究

105 阅读2分钟

抛出问题

OC语言时动态语言,比如runtime,很多东西时在运行时才确定的,比如方法调用,底层是在运行时调用objc_send,通过SEL去找对应的方法实现IMP.正式因为运行时特性我们可以通过交换两个方法的IMP来实现方法交换也就是iOS老生常谈的MethodSwzzing. 那么'c'语言属于静态语言,编译时刻就已经确定了函数地址.也就是说c函数调用时直接调用地址的 那么NSLog等外部代码在编译时,我们时根本不知道他的真实地址的,因为他存在Foundation框架中,是在系统中的共享缓存中的,所有APP都是可以使用的,所以编译时根本不知道其真实地址. 那么这不是前后矛盾么

PIC(位置无关代码/位置独立代码)

iOSmacOSMachO 中有Text段也就是代码段 和Data段, 因为Text段时rx权限,所以apple就在Data段中放了一个占位符,让外部c函数先指向占位符,然后在运行的时候DYLD将占位符修改成真实地址. 这个过程叫做符号绑定. 这个过程跟OC中的方法sel -> imp是很像的,正是有这个过程的存在所以可以修改占位符达到一个方法的Hook,这也是fishhook的原理 编译时模型: bl -> 占位符(Symbol) 运行时模型: bl -> 桩地址(Symbol Stubs段代码进行符号绑定) -> 真实地址

符号绑定过程

FishHook 是如何通过字符串找到符号表位置的

Lazy Symbol Pointers 懒加载表 所有需要进行bind的函数都会在这个表中 Indirect Table 间接符号表,外部函数,也就本MachO以外的函数 Lazy Symbol PointersIndirect Table 的位置是有一一对应的关系 如图

2711707-afd0fbab7267e379.png

2711707-2d93a569aed26ede.png

Indirect Table 第一条也为NSlog 对应的data ,对应的data值000000EC 转换为10进制 为 236 代表的是NSLlog在总表也就是Symbols中位置的角标index`

2711707-d6f405d7088958c7.png

可以看到 String Table Index ,data就代表NSLlogString Table 中的位置000000E7

2711707-4f79b3e3c691f817.png 0000D7B0 + 000000E7 = 0000D897 就是NSlogString Table中的地址

贴上一张fishhook github上的一张图

2711707-b85416b10eaaa7f2.png

系统流程:

  1. Lazy Symbol Table 中对应的index
  2. Indirect Symbol Table对应的index 找到data字段(代表SymbolNSlog对应的index)
  3. Symbol Table 对应的位置找到data字段(代表 String Table中的位置offset偏移)
  4. string table (start address + offset) 就是NSlog字符串的地址