一、HOOK概述
1.HOOK定义
HOOK
翻译成中文为“挂钩”、“钩子”,在iOS逆向畛域中指的是扭转程序运行流程的一种技术,通过HOOK
能够让他人的程序执行本人所写的代码
下列示意图就是对HOOK性能的形象诠释:
- 注入恶意代码让用户误以为打卡胜利,理论并没有实现打卡(只批改两头流程)
- 注入恶意代码让用户误以为网络出问题(开拓新的流程分支)
2.HOOK形式
在iOS中HOOK技术有以下几种:
- Method Swizzling:利用OC的Runtime个性,动静扭转
SEL(办法编号)
和IMP(办法实现)
的对应关系,达到OC办法调用流程扭转的目标 - fishhook:这是FaceBook提供的一个动静批改链接machO文件的工具,利用machO文件加载原理,通过批改懒加载和非懒加载两个表的指针达到C函数HOOK的目标
- Cydia Substrate:原名为
Mobile Substrate
,它的次要作用是针对OC办法、C函数以及函数地址进行HOOK操作,且安卓也能应用
之前曾经介绍过Method Swizzling
了,OC的Runtime个性让它有了“黑魔法”之称,同时也是局限性所在
三者的区别如下:
Method Swizzling
只实用于动静的OC办法(运行时确定函数实现地址)fishhook
实用于动态的C办法(编译时确定函数实现地址)Cydia Substrate
是一种弱小的框架,只须要通过Logos语言(相似于正向开发)就能够进行Hook,实用于OC办法、C函数以及函数地址
二、fishhook
1.fishhook的应用
整个fishhook就凋谢了一个构造体rebinding
和两个函数
rebind_symbols
hook我的项目中的所有函数名称rebind_symbols_image
只hook某一个资源库的函数名称
应用fishhook的步骤:
- 导入头文件
#import "fishhook.h"
- 指定替换函数——
rebinding
构造体对象
struct rebinding nslog;nslog.name = "NSLog";nslog.replacement = fxNSlog;nslog.replaced = (void *)&sys_nslog;
- 调用
rebind_symbols
从新绑定符号
struct rebinding rebs[] = {nslog};rebind_symbols(rebs, 1);
残缺代码如下:
#import "fishhook.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; struct rebinding nslog; nslog.name = "NSLog"; nslog.replacement = fxNSlog; nslog.replaced = (void *)&sys_nslog; struct rebinding rebs[] = {nslog}; rebind_symbols(rebs, 1);}static void(*sys_nslog)(NSString *format, ...);void fxNSlog(NSString *format, ...) { format = [format stringByAppendingFormat:@"已hook"]; sys_nslog(format);}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"点击屏幕");}@end
定义
rebinding
来指定替换的函数name
中指定Hook的函数名称(C字符串)replacement
中指定新的函数地址- c函数的名称就是函数指针——动态语言编译时就已确定
replaced
中寄存原始函数地址的指针- 因为
NSLog
在Foundation库中,在每个手机的内存地址都不一样,不能通过CMD+B
就能确定其内存地址 - 这里fishhook在运行的时刻会动静获取到
NSLog
的地址,所以这里定义新的函数指针保留函数实现 - 应用
&
批改变量外部的值 - 应用
(void *)
进行类型转换
- 因为
rebind_symbols
中须要两个参数- 参数一是
rebinding
数组 - 参数二是
rebinding
数组的长度
- 参数一是
作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这有个iOS交换群:642363427,不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术,iOS开发者一起交流学习成长!
2.fishhook的局限性
后面介绍了fishhook
是用来hook C函数的,但在此前提下还是有它的局限性——无奈替换自定义函数
C函数
是动态的,在编译时就曾经确定了函数地址(函数实现地址在MachO本地文件中)零碎C函数
则是存在着动静的局部
那么为什么零碎级别的C函数就能够呢?这就要说到PIC技术了
3.PIC技术
PIC技术
(Position-independent code),又叫做地位独立代码
,是为了零碎C函数
在编译期间可能确认一个地址的一种技术手段
- 编译时在MachO文件中预留出一段空间——符号表(DATA段中)
- dyld把利用加载到内存中时(此时在
Load Commands
中会依赖Foundation
),在符号表中找到了NSLog
函数,就会进行链接绑定——将Foundation
中NSLog
的实在地址赋值到DATA段
的NSLog
符号上
而自定义的C函数不会生成符号表,间接就是一个函数地址,所以fishhook的局限性就在于只有符号表内的符号能够hook(从新绑定符号)
4.LLDB调试
因为NSLog
是个懒加载的符号,所以加了行代言代码
- 通过
image list
打印所有镜像资源——第一个就是过程的内存首地址 - 获取到MachO中NSLog的内存偏移量
应用计算器,内存首地址+内存偏移量=符号地址
- 通过
memory read 内存地址
读出符号地址
因为iOS是小端模式,内存地址8位倒着读
- 通过
dis -s 内存地址
查看汇编
此时的符号并没有绑定,因为还没有应用
- 过掉断点(应用NSLog)再进行查看
此时的NSLog符号曾经被绑定
- 再跳到下一步(重绑定符号)进行查看
此时的NSLog符号曾经被重绑定了
5.fishhook原理摸索
接下来剖析下rebind_symbols
:
prepend_rebindings
将rebindings
数组一直增加到_rebindings_head
链表的头部成为新的头节点判断链表
_rebindings_head->next
是否为空来判断是否是第一次调用- 若首次调用则应用
_dyld_register_func_for_add_image
进行回调监听 - 若不是则遍历调用
_rebind_symbols_for_image
- 若首次调用则应用
这个函数有个Int返回值
- 如果重定向胜利则返回 0
- 如果失败则返回 -1
接下来是_rebind_symbols_for_image
对MachO文件的操作:依照规定计算各种表的地址和指针在表中的偏移量
最初一步,perform_rebinding_with_section
依据算好的符号表地址和偏移量,找到在符号表中用于指向共享库指标函数的指针,将该指针的值(即指标函数的地址)赋值给rebinding
的*replaced
,最初批改该指针的值为replacement
(新的函数地址)
6.fishhook原理的实际——在MachO中查找函数实现
接下来就依据字符串对应在符号表中的指针,找到其在共享库的函数实现的
- NSLog在
Lazy Symbol Pointers
中位列第一个,下标为0 Dynamic System Table->Indirect Symbols
中的value与Lazy Symbol Pointers
一一对应,此表中的Data(0xA9=169)即为另一个表的下标- 拿着这个下标在
Symbol Table->Symbols
中找到NSLog,此时的Data对应String Table Index
中的偏移值(0x0000009B) - 最初在
String Table
中计算表头(0x000061EC)+偏移量(0x0000009B),找到NSLog的函数地址
7.fishhook利用场景
既然fishhook
能够替换C函数,那么就能够替换method_exchangeImplementations
等函数来避免HOOK,我的项目自身如果须要应用method_exchangeImplementations
则能够应用新的函数地址来进行操作
- 攻:能够插入新的动静库提前进行HOOK办法,此时fishhook的防护就不起作用了
- 防:也能够提前插入动静库进行fishhook替换(逆向注入的动静库个别排在原我的项目的动静库之后),此时fishhook代码先于hook代码,所以还是fishhook还是失效的
- 攻:釜底抽薪——间接找到fishhook的函数地址进行批改,再次运行
- ...
写在前面
在平安攻防畛域中,hook原理起到至关重要的作用,而应用fishhook做防护尽管意义不大,然而理解fishhook原理对后续的学习还是挺有帮忙的,想理解更多逆向相干常识无妨动动小手,增加一下咱们的交换群642363427来为你的技术多添一份荣耀。