在一些逆向过程中常常通过代码注入的方式来hook,在OC里面我们常常通过runtime交换imp来hook,但是今天我们试试facebook开源的fishhook,来了解对系统C函数的hook
HOOK,俗称钩子,是iOS逆向中改变程序运行流程的一种技术,通过hook让别人的程序执行我们自己写代码.
今天我们主要来学习下fishhook,是Fachbook提供一个动态修改链接Mach-O文件的工具,利用MachO文件加载原理,通过懒加载/非懒加载两个表的指针达到C函数Hook的目的.
#import "ViewController.h"
#import "fishhook.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
struct rebinding nslog;
nslog.name = "NSLog";
nslog.replacement = myNslog;
nslog.replaced = (void *)&sys_nslog;
struct rebinding rebs[1] = {nslog};
rebind_symbols(rebs, 1);
}
static void (*sys_nslog)(NSString * format,...);
void myNslog(NSString * format,...){
format = [format stringByAppendingString:@"勾上了!\n"];
sys_nslog(format);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"点击屏幕了!!");
}
@end
打印结果
2020-07-21 14:15:04.092737+0800 FishhookTest[2340:179160] 点击屏幕了!!勾上了!
2020-07-21 14:15:04.977154+0800 FishhookTest[2340:179160] 点击屏幕了!!勾上了!
fishhook的使用就是需要我们定义一个指针,fishhook帮我们保存原系统函数实现地址,将需要替换的函数名称和自定义函数地址写成结构体调用rebind_symbols , 可以一次性往数组中写入多个结构体进行多个函数的hook
C函数是静态的,在编译的时候,编译器就知道它的实现地址,所以C函数只写函数声明调用时会报错.
fishhook怎么能改变C函数的调用
fishhook只能对带有符号表的系统函数进行重绑定,而对自己实现的C函数同样没办法
C是编译时确定函数地址 OC是运行时确定函数地址
系统的C函数有动态的部分,就是我们经常提到的符号表, 叫Position Independent Code (位置代码独立)
原理
由于iOS系统中UIkit/Foundation 库每个应用都会通过dyld加载到内存中,为了节约空间,苹果将这些系统库放在一个叫动态库共享缓存区,mac上也有
类似NSlog的函数实现地址,我们想要调用NSLog,就要找到其真实的实现地址
1.在工程编译中,所产生的Mach-O可执行文件会预留出一段空间,这个空间其实就是符号表,存放在_DATA数据段中,_DATA在运行时是可读可写的
2.编译时,工程中所有引用到共享缓存区的方法,其指向的地址设置为符号地址,如工程里面调用NSLog方法,在编译时会在Mach-O创建一个NSLog的符号,工程的NSLog就指向这个符号
3.运行时,当dyld加载到内存后,根据load commands 中列出的需要加载的哪些库文件,去做绑定的操作,如NSLog方法,dyld会找到Foundation里面的NSLog真实地址,将它写进_DATA段的符号表中NSLog上面
fishhook里面的rebind_symbols: 重绑定符号
就是将编译后系统库函数指向的符号绑定到用户自定义的函数地址上,将原系统函数的真实地址赋值到用户指定的指针上
fishhook无法hook自定义的C函数,是因为没有可以绑定的符号表
我的fishhookTest
参考: https://juejin.im/post/5dc3ba52f265da4d3962a833