在上一篇 fishHook原理----(1) 中,我们讲了fishHook
的HOOK
流程,当第一次调用NSLog
的时候,首先会到找桩去执行一段代码,这段代码就是去找到懒加载里面的值去执行,然后它默认会b
到另一段代码,就是去找non_Lazy Symbol
去找dyld_stub_binder
的真实函数的地址完成符号绑定,第一次绑定完成之后,完成了第一次调用;
3、当第二次调用NSLog
的时候,还是会找到桩去执行一段代码,代码会跳到懒加载里面的Data
的值去执行,但是这个时候,Data
里面的值指向了NSLog
的真实地址,不再是指向查找dyld_stub_binder
的真实函数的地址完成符号绑定;
使用fishHook
的核心代码就这几行,rebinding
结构体有一个name
成员变量,那它是如何通过name
找到NSLog
符号的呢?
struct rebinding psyLog;
psyLog.name = "NSLog";
psyLog.replacement = psy_Log;
// 原函数
psyLog.replaced = (void *)&sysLog;
struct rebinding psysh[] = {
psyLog
};
rebind_symbols(psysh, 1);
以下是官方给的在懒加载表或非懒加载表中查找给定name
的过程:

看着可能看不大懂,我们先撇开这个图,看一下MachO,从懒加载表开始,因为懒加载是外部函数,_NSLog
的下表是第0
位,对应的在间接符号表也是第0
位。


找到间接符号表的对应index
,得到Data
段数据0xB2
(对应的十进制是178),还有Description
是Symbol
符号表,意思就是在Symbol
表的178标号位置

然后对应的找到
Symbol
表的对应#178
,得到Data
段数据0xD7
,还有Description
是String Table Index
字符串表,意思就是在String Table Index
表的偏移0xD7
位置。

来到String Table
根据刚刚得到的偏移量0xD7
,通过初始位置+偏移量定位到对应的位置,0xD3D0 + 0xD7 = 0xD4A7
,终于查到我们需要的字符串ASCII
码5F 4E 53 4C 6F 67
,Value
是_NSLog
。 至此,再返回去看一下官方给的查找流程图,就很明了了。
网友评论