fishhook 一、概述 HOOK:钩子、挂钩。让别人的程序执行自己的代码。
1、iOS中HOOK方式 Method Swizzle,利用Runtime,动态改变SEL和IMP的关系,主要用在OC方法中
2、fishhook fackbook提供的一个动态修改链接mach-o文件的工具,利用mach-o文件加载原理,通过修改懒加载和非懒加载表的指针来实现C函数HOOK的功能。
二、原理
1、C语言是静态函数,编译的时候已经确定了函数地址,怎么能HOOK呢?
C语言是静态函数,但是系统的C函数的调用是动态的
系统函数如NSLog,在编译的时候是无法确定地址,因为没有载入到内存,这里涉及到共享动态库的原理,(NSLog在Fundaction库里。动态库的共享缓存,在不同的系统,不同的手机,地址都是不一样的)。
如何调用系统库的呢? 苹果的共享缓存库不会被编译进我们的 MachO 文件,而是在动态链接时才去重新绑定。 苹果采用了PIC(Position-independent code)技术成功让 C 的底层也能有动态的表现
- 编译时,在mach-o文件_DATA段的符号表中为每一个被引用的系统C函数建立一个指针(8字节)。这个指针的作用是用于动态绑定时,绑定共享库中函数的实现。
- 运行时,当系统的C函数第一次调用时会进行符号绑定,然后将mach-o文件_DATA段的符号表对应的指针,指向外部函数(共享库中实际的内存地址)
1、在编译的时候,当调用NSLog的时,mach-o(本地)文件会生成一个NSLog符号指针,调用代码会指向这个指针。
2、在运行的时候,dyld链接器加载mach-o文件,载入到内存,载入到内存的时候会询问哪些符号需要绑定,把系统库的地址和函数的真实地址和符号绑定。
3、运行时,首次(懒加载表)NSLog函数的调用,会去找符号,一开始符号是没值的,符号绑定后才会有值。
符号:符号就是函数名称,以函数名称命名的指针
系统的C函数的调用是动态的,通过符号找到真实的地址,fishhook就是利用这个原理,对符号重新绑定,把符号指向的系统函数的真实地址改了,改成了自己定义的函数的地址。
自定义的C函数是无法通过fishhook工具HOOK的(可以通过innerHook内连HOOK,但是要考虑到堆栈平衡,要改动汇编代码),只能HOOK外部函数。