Facebook提供的一个动态修改链接mach-O文件的工具。利用Mach-O文件的加载原理,通过修改懒加载和非懒加载两个表的指针达到C函数HOOK的目的
注:fishhook只能修改系统的C函数,而从上面我们可以发现fishhook是动态的修改mach-O文件,但是C语言是静态语言它是如何动态修改的呢。其实它是利用了C函数在iOS中的动态特性,符号绑定特性。
代码实现hook-NSLog
#import "ViewController.h"
#import "fishhook.h"
@interface ViewController ()
@end
@implementation ViewController
static void(*system_nslog)(NSString *format, ...);
void myNSLog(NSString *format, ...){
format = [format stringByAppendingString:@"\n\n\n\n🐂🐂🐂🐂\n\n\n\n"];
system_nslog(format);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
struct rebinding nslog;
nslog.name = "NSLog";
nslog.replacement = myNSLog;
nslog.replaced = (void *)&system_nslog;
struct rebinding rebs[1] = {nslog};
//参数1: 存放rebinding结构体的数组
//参数2: 数组的长度
rebind_symbols(rebs, 1);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"\n\n\n\n🐮🐮🐮🐮\n\n\n\n");
}
@end
fishhook原理
通过mach-O文件分析
__DATA,__la_symbol_ptr,图中右边第一个就是NSLog,第一个值是offset,也就是我们如果拿到了mach-O文件的首地址,然后偏移0x00003028,就可以找到NSLog的函数地址

如何验证mach-O首地址偏移0x00003028就可以得到NSLog的函数地址呢
运行demo,然后在NSLog的处进行断点

通过mach-O工具查看NSLog的偏移地址,见上图懒加载符号得到0x00003028
通过image list,例举出mach-O文件所依赖的所有模块,然后找到mach-O文件首地址

然后使用x 0x0000000105deb000+0x00003028 读内存

因为iOS是小端模式,所以我们要读取:后面的八个字节,要从后往前度,在通过dis 命令得到

这样我们就得到了NSLog的函数地址
我们再看下通过fishhook后NSLog的函数地址


有趣,原来fish做的工作就是把符号绑定的地址函数给替换了
fishhook是如何做替换的
首先我们来看下官网的原理图

我们 在通过mach-O文件来看下这个图的流程
首先还是看懒加载表然后找到第一个数据是NSLog

再到Dynamic Symbol Table表中找第一个数据,这两张表的顺序是一样的

然后找到Data的值00000079,并转换为十进制121,得到Symbol Table中NSLog的编号

这个表中的Data-9B代表着_NSLog在String Table中的偏移

使用0x9B+0x4EEC得到0x4F87

这样就找到了NSLog
生活如此美好,今天就点到为止。。。