FishHook
- (void)viewDidLoad {
[super viewDidLoad];
//hook NSLog
struct rebinding nslog;
nslog.name = "NSLog";
nslog.replaced = (void *)&sys_nslog;
nslog.replacement = my_NSLog;
struct rebinding bds[] = {nslog};
rebind_symbols(bds, 1);
}
//原来函数指针
static void (*sys_nslog)(NSString *format, ...);
//新函数
void my_NSLog(NSString *format, ...) {
format = [format stringByAppendingString:@"\nhook到了"];
//再调用到系统的NSLog中
sys_nslog(format);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"nslog");
}
//rebinding结构体
struct rebinding {
const char *name;//需要HOOK的函数名称,C字符串
void *replacement;//新函数的地址
void **replaced;//原始函数地址的指针!
};
复制代码
能hook到的是系统的函数,hook不到的是自定义的函数,自定义的是在本MachO中的并且在编译的时候就已经绑定好了符号和确定好了地址,但是NSLog是Foundation框架里,在编译时期确定不了so就可以hook到。
系统函数和本地函数的区别&符号绑定
FishHook的调用过程
NSLog在编译时期不知道函数地址的,NSLog在Foundation框架里,DYLD在加载MachO进内存的时候首先会加载共享缓存,
因为有些函数在编译的时候未确定函数地址,所以先用一个占位符进行占位,等到执行到这些函数时算出函数地址,再通过符号绑定,来调用函数
外部的C函数的调用是通过符号表找地址,C语言是静态语言,但外部函数调用通过动态的调用方式,通过符号找地址,可以绑定也可以重绑定
符号的绑定过程
首先程序执行先把非懒加载符号表中的符号绑定好保存,当调用NSLog时先找桩,找到桩后去执行桩对应的二进制指令,也就是去懒加载符号表中的值去执行,然后再去找非懒加载符号表中的dyld_stub_binder函数来进行符号绑定
FishHook的反向查找
符号
外部符号:本MachO以外的符号?NSLog的符号
内部符号:本MachO以内的? 自定义的一些方法或者类型
符号还分为全局符号和本地符号
全局符号:外部也可以使用,暴漏给外界使用的,?做一些动态库
本地:自己使用的
去符号
恢复符号
用FishHook来做防护
FishHook源码解析
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END