HOOK原理及介绍

注入小结

通过之前的学习,我们知道了利用动态库注入的两种方式:

- Framework
- Dylib
  • 注入 App 后,使得 项目和动态库产生关联关系。
  • 修改 Mach-o 文件的 Load Commands 段。

然后开始在注入的动态库中,开发你想实现的逻辑功能!

一、HOOK概述

HOOK(钩子) 其实就是改变程序执行流程的一种技术的统称!

15245516017168.jpg

iOS中HOOK技术的几种方式

1、Method Swizzle

利用OC的Runtime特性,动态改变SEL(方法编号)和IMP(方法实现)的对应关系,达到OC方法调用流程改变的目的。主要用于OC方法

2、fishhook

它是Facebook提供的一个动态修改链接mach-O文件的工具。利用MachO文件加载原理,通过修改懒加载和非懒加载两个表的指针达到C函数HOOK的目的。

OC 是动态语言,C 则是静态语言,一经编译,所有的都可以获取到,那 Fishhook 是怎么做到的呢????

3、Cydia Substrate

Cydia Substrate 原名为 Mobile Substrate ,它的主要作用是针对OC方法、C函数以及函数地址进行HOOK操作。当然它并不是仅仅针对iOS而设计的,安卓一样可以用。官方地址:http://www.cydiasubstrate.com/

Cydia Substrate主要由3部分组成:

  • MobileHooker

    MobileHooker顾名思义用于HOOK。它定义一系列的宏和函数,底层调用objc的runtimefishhook来替换系统或者目标应用的函数.
    其中有两个函数:

    • MSHookMessageEx 主要作用于Objective-C方法
     void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
    
    
    • MSHookFunction 主要作用于C和C++函数
     void MSHookFunction(voidfunction,void* replacement,void** p_original)
    
    

    Logos语法的%hook 就是对此函数做了一层封装

  • MobileLoader

    MobileLoader用于加载第三方dylib在运行的应用程序中。启动时MobileLoader会根据规则把指定目录的第三方的动态库加载进去,第三方的动态库也就是我们写的破解程序.

  • safe mode

    因为APP程序质量参差不齐崩溃再所难免,破解程序本质是dylib,寄生在别人进程里。 系统进程一旦出错,可能导致整个进程崩溃,崩溃后就会造成iOS瘫痪。所以CydiaSubstrate引入了安全模式,在安全模 式下所有基于CydiaSubstratede 的三方dylib都会被禁用,便于查错与修复。

fishhook 的简单使用

Github 有相关的介绍,使用方法等;

https://github.com/facebook/fishhook

  • fishhook Demo 测试 1:系统方法交换

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // rebinding 结构体的定义
    //    struct rebinding {
    //        const char *name; // 需要 HOOK 的函数名称,字符串
    //        void *replacement; // 替换的新函数(函数指针,也就是函数名称)
    //        void **replaced; //  保存原始函数指针变量/地址的指针(它是一个二级指针!)
    //    };
    // C 语言传参是值/址传递的,把它的值/址穿过去,就可以在函数内部修改函数指针变量的值

    // 定义 rebinding 结构体
    struct rebinding nslogRebind;
    // 函数名称
    nslogRebind.name = "NSLog";
    // 新的函数指针
    nslogRebind.replacement = myLog;
    // 保存原始函数地址的变量的指针
    nslogRebind.replaced = (void *)&old_Nslog;// fishhook 将 old_Nslog 这个指针指向了 NSLog 这个函数,怎么做的呢???

    // 定义数组
    struct rebinding rebs[] = {nslogRebind};
    
    /*
     1. rebindings : 存放 rebinding 结构体的数组,可以交换 N 种方法
     2. size_t rebindings_nel : 数组的长度???
     */
    rebind_symbols(rebs, 1);
}

// 函数指针,用来保存原始的函数地址 (C 语言语法,函数指针类型变量)
static void (*old_Nslog)(NSString *format, ...);

// 自定义的 Log
void myLog (NSString *format, ...){
    format = [format stringByAppendingString:@"——> 勾上了!!!💖💖💖💖💖💖💖💖"];
    old_Nslog(format);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"点击了屏幕");
    
}

点击屏幕,可以看到控制台日志:

image.png
  • fishhook Demo 测试2:自定义方法交换 :
- (void)viewDidLoad {
    [super viewDidLoad];
    // 交换简写!
    // (struct rebinding [1]) 数组类型
    // {{"func",newFunc,(void *)&funcP}} 值为结构体,三个参数
    rebind_symbols((struct rebinding [1]){{"func",newFunc,(void *)&funcP}}, 1);
}

// 原始函数指针
static void (*funcP)(const char *);
// 新函数
void newFunc(const char *str){
    NSLog(@"———> 勾住了!!!💖💖💖💖💖💖");
    funcP(str);
}

// 原始函数
void func(const char * str){
    NSLog(@"%s",str);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    func("Hello world!!!");
}
image.png

首先代码是没有问题的,为什么呢?自定义方法交换不了呢???

fishhook 原理探究

  1. Mach-O 文件是怎么加载的?
    DYLD 工具动态加载,加载完 Mach-O 文件后,加载依赖的动态库,通过 image list 可以看到加载的相关类库。

  2. ASLR 地址空间随机布局,Mach-O 文件加载的时候是随机地址的。
    系统类库,每次启动,所有地址也是随机布局。

  3. PIC 位置代码独立

???

控制器(Programmable Interrupt Controller)”的简称。

???

可编程中断控制器(Programmable Interrupt Controller),也简称为PIC,是微处器与外设之间的中断处理的桥梁,由外设发出的中断请求需要中断控制器来进行处理。

如果 Mach-o 文件内部需要调用系统的函数时:

  • 现在 Mach-o _data 段 建立一个指针(就是符号,实现指向内部的函数调用,指向外部的函数地址),指向外部函数,(dyld 加载)
    可读可写,当 Mach-o 被加载进去的时候,它就会指向所指的函数。

  • DYLD会进行动态的绑定,将 Mach-o 文件Data 段中的指针指向外部的函数!!!所以 DYLD 叫动态加载。
    故 fishhook 中 的绑定方法叫做:rebind_symbols 重新绑定符号,就是绑定程序内部的函数。

这也就是为什么内部/自定义的函数修改不了,只能修改 Mach-O 文件外部的函数,如果是另一个动态库的或者是需要动态符号绑定的就可以,在符号表中能找到的才可以。

接下来,验证一下:

还是用 fishhook Demo 测试 1 来测试,运行,查看 Mach-o 符号表:

image.png
NSLog 函数

offset :8018, NSLog文件偏移地址,也就是说懒加载这个表也就在 Mach-O 文件偏移的地址 + 函数偏移地址

动态调试:

断点位置
Mach-O 在内存中的偏移地址

Mach-O 在内存中的偏移地址也就是 Mach-O 的真实地址。

Mach-o 文件Data 段中的函数指针

计算符号表的地址

通过符号表找方法的地址,通过 dis -s 反汇编命令查看函数详情。

接下来,过段点继续查看:

前后比较

通过上面可以看出,fishhook 之所以能够 Hook C 函数,是因为根据 Mach-O 文件 特点,PIC 位置代码独立 也就造就了所谓的静态语言 C 也有动态的部分,通过 DYLD 进行动态绑定的时候,我们做了手脚,替换为我们自定义的方法。

备注: 值得注意的是,调用之前先调用一下 NSLog 函数,(符号表中应该没有 NSLog 函数的地址,但其实是有,但是可能是不正确的/固定的地址??)否则则调用 rebind_symbols 方法前不能正确的获取 函数的符号表地址(fishHook 内部会调用吧??)

  • 懒加载表中 NSLog 函数什么时候给他赋值呢??

现在是存放在 Mach-o 文件偏移 8018 的位置 ,而它存放的一个 8 个字节的指针,保存的就是 动态缓存区 中保存 NSLog 函数的真实的地址,那这个地址是什么时候保存进去的呢???
并不是 Mach-O 文件加载的时候保存的,而是第一次调用 该函数时保存进去的,绑定一下,由 DYLD 绑定 NSLog 这个符号指向真实的 NSLog 的地址。

未调用方法的符号表
image.png

那 fishhook 根据方法字符串名字 "NSLog" 也就是 struct rebinding const char *name 是怎么找到的呢 ???

通过符号表查看函数名称字符串

再次查看 Mach-o 文件,上面查看的懒加载表中的 NSLog 函数:

懒加载表和动态符号表

懒加载表和动态符号表是一一对应 的关系,如下:

动态符号表

动态符号表中的 Data 其实就是 方法的 Symbol Table 中的下标,转换为 10 进制 (0x88 = 136),到 Symbol Table 中查看:

Symbol Table

_ 和 .
_ 是函数的开始,. 是分隔符,\0 的转义字符。

这里还不是最终的 NSLog 字符串,可以看到 _NSLog 在 String Table 中的 Index 偏移为 0x000000AC。接下来继续查看 String Table

NSLog 字符串存放的位置

String Table 首地址0xD0A4 + 偏移地址 0xAc = 0xD150

以上过程也就是 GitHub fishhook 的说明图,如下:

查找过程

小结:

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,881评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,052评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,598评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,407评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,823评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,872评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,037评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,778评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,505评论 1 247
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,745评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,233评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,231评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,141评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,939评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,954评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,784评论 2 275

推荐阅读更多精彩内容