抛出问题
OC语言时动态语言,比如runtime,很多东西时在运行时才确定的,比如方法调用,底层是在运行时调用objc_send,通过SEL去找对应的方法实现IMP.正式因为运行时特性我们可以通过交换两个方法的IMP来实现方法交换也就是iOS老生常谈的MethodSwzzing.
那么'c'语言属于静态语言,编译时刻就已经确定了函数地址.也就是说c函数调用时直接调用地址的
那么NSLog等外部代码在编译时,我们时根本不知道他的真实地址的,因为他存在Foundation框架中,是在系统中的共享缓存中的,所有APP都是可以使用的,所以编译时根本不知道其真实地址. 那么这不是前后矛盾么
PIC(位置无关代码/位置独立代码)
在iOS和macOS中MachO 中有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 Pointers 跟Indirect Table 的位置是有一一对应的关系
如图
Indirect Table 第一条也为NSlog 对应的data ,对应的data值000000EC 转换为10进制 为 236 代表的是NSLlog在总表也就是Symbols中位置的角标index`
可以看到 String Table Index ,data就代表NSLlog在String Table 中的位置000000E7
0000D7B0 + 000000E7 = 0000D897 就是NSlog 在String Table中的地址
贴上一张fishhook github上的一张图
系统流程:
Lazy Symbol Table中对应的indexIndirect Symbol Table对应的index找到data字段(代表Symbol中NSlog对应的index)Symbol Table对应的位置找到data字段(代表String Table中的位置offset偏移)string table (start address + offset)就是NSlog字符串的地址