大部分hook需要3个固定参数:
-
函数名称
-
要hook的函数旧地址
-
新的函数地址
编译阶段是不知道函数的真实地址的,但是知道自定义函数在当前可执行文件里的偏移地址。
个人理解的原理
:Mach-O中TEXT段只读的, DATA段可读可写的。内部自定义函数是不会生成符号表的
。系统函数也叫外部函数,编译时如果是外部函数,則会生成一个符号表
用来记录函数名称,保存在Mach-O的DATA段。运行时dyld会把外部函数的真正函数地址当做value赋值给符号表(符号绑定binding),函数名称也叫符号作为key,这个过程叫PIC(Position Independent Code)。fishhook目的就是把这个符号地址改了
。一个符号占8个字节。
-
runtime是Hook不了C函数的,因为C函数不会生成符号表,C函数的
偏移
地址在编译时期就已经确认了,所以才能快速、直接的跳转到这个地址,实现函数调用,走不到消息发送阶段
。 -
就像NSLog这种外部函数,只能在运行时才能确认其
执行地址
(偏移+ASLR),在编译时是不知道其地址的,因为其所在的框架Foundation是置于ios系统共享缓存库中的,是在dyld将可执行文件MachO加载到缓存中才能准确知道其执行地址,在此之前编译时会给一个临时的NSLog地址以让其在编译期不报错。 -
fishhook可以hook methodswillzing,防止被hook,可以将自己的和别人hook你的作区分,或objc_msgsend,需要写汇编,避免污染寄存器。fishhook只能hook系统函数。因为fishHook的原理是动态修改Mach-O文件里
修改符号表里的关联关系
。符号表
存在于__DATA_CONST, __got
和__DATA,__la_symbol_ptr
段中,分别为非懒加载
符号表和懒加载
符号表。这两种符号表的区别在于它们绑定的时机不一样,非懒加载符号表是在程序一启动就绑定了,懒加载符号表是在用到该符号时,才会进行绑定。 -
自定义的函数不会生成符号表,最新的
InlineHook框架Dobby
就可以Hook自定义C函数,其原理是直接修改了函数的前几条汇编指令,使其指向跳转变化。
网友评论