欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HOOK原理与fishhook初探防护

程序员文章站 2022-07-13 16:17:09
...

1.HOOK概述

1、Method Swizzle

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

2、fishhook

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

3 cydia Substrate

Cydia Substrte原名为mobile Substrte,它主要的作用是针对OC方法、C函数以及函数地址进行HOOK操作。当然它并不是仅仅针对ios而设计的,安卓也一样可以用。

下图是Method Swizzle和cydia substrte的简单原理图:
HOOK原理与fishhook初探防护
HOOK原理与fishhook初探防护
HOOK原理与fishhook初探防护

2.fishHook简单使用

1.获取facehook的源码

1.1 通过登录github 搜索fishhook 可以看到源码并且down下来。
1.2 可终端cd到想要下载的目标文件下,通过输入命令 下载,
HOOK原理与fishhook初探防护
下载后可以看到只有fishhook.h fishhook.c 2个文件,可以看到点h中·只有2个方法和一个结构体。
HOOK原理与fishhook初探防护
方法1:rebind_symbols 针对是c函数
方法2:rebind_symbols_image 主要用于image

2.fishHook简单使用

1.用自定的myNSlog 替换 系统方法NSlog

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    
    //rebinding结构体
    struct rebinding nslog;
    nslog.name = "NSLog";
    nslog.replacement = myNslog;
    nslog.replaced = (void *)&sys_nslog;
    //rebinding结构体数组
    struct rebinding rebs[1] = {nslog};
    /**
     * 存放rebinding结构体的数组
     * 数组的长度
     */
    rebind_symbols(rebs, 1);
}
//---------------------------------更改NSLog-----------
//函数指针
static void(*sys_nslog)(NSString * format,...);
//定义一个新的函数
void myNslog(NSString * format,...){
    format = [format stringByAppendingString:@"勾上了!\n"];
    //调用原始的
    sys_nslog(format);
}



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

2.如下代码,运行后可以发现点击屏幕,new_func并未替换func方法,原因是因为fishHook只能用于替换“系统函数”,并不能替换自定义的函数,具体原理下面继续探索。

void func(const char * str){
    NSLog(@"%s",str);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    //rebinding结构体
    struct rebinding nslog;
    nslog.name = "func";
    nslog.replacement = new_func;
    nslog.replaced = (void *)&old_func;
    //rebinding结构体数组
    struct rebinding rebs[1] = {nslog};
    /**
     * 存放rebinding结构体的数组
     * 数组的长度
     */
    rebind_symbols(rebs, 1);
}
//---------------------------------更改NSLog-----------
//函数指针
static void(*old_func)(const char * str);
//定义一个新的函数
void new_func(const char * str){
      NSLog(@"%s + 1",str);
}



-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    func("哈哈");
  //  NSLog(@"哈哈!");
}

3 无法交换自定义函数,符号绑定原理

1.c 静态:系统的c函数存在着动态的部分!!
编译时确定:函数的地址!

2.oc 动态
运行时确定:函数的地址!

3.自定义函数的函数实现地址在macho的本地文件中,
而系统函数编译时系统地址不能确定,苹果用PIC技术解决,在macho的数据段中生成符号表,运行时通过dyld链接共享缓存库将真实地址绑定到符号表上符号地址,

我们可以看到nslog在macho中的偏移位置是0x4030,
HOOK原理与fishhook初探防护
我们可以看到macho在内存的起始位置是HOOK原理与fishhook初探防护
然后我们打开电脑段的计算器,command + 3 打开科学计算器,
然后起始位置加 偏移量,得到的16进制的0x10e172030,NSlog内存中的位置,
我们将断点打到viewdidload,如图所示位置:
HOOK原理与fishhook初探防护
然后使用LLDB,读取内存的指令:memory read 0x10e172030.可以看到内存中value是 0xf7ff2081c3b5,然后使用汇编指令dis -s f7ff2081c3b5查看汇编代码,如下显示foundation模块的nslog,(我这里断点过到nslog之下了,上面走到viewdidload时候也同样使用memory read 0x10e172030,可以查看未绑定nslog符号之前,内存value是不同于此处的,同样使用dis -s 0x… 可以看到未绑定之前是我们不识别的汇编,)
HOOK原理与fishhook初探防护
同样我们过了rebing_sysbols后在断点到touch处,同样读内存,和value发现此处已经绑定为myNSlog方法了。
HOOK原理与fishhook初探防护
HOOK原理与fishhook初探防护

4 rebing_sysbols中的结构体如何通过name字符串,查找修改到nslog的交换方法的。

首先在lazy Syymbol表中可以看到NSLog,
HOOK原理与fishhook初探防护
与lazy symbol表对应的表如下,nslog都是在表中首位,看到此处data序号为0x83:
HOOK原理与fishhook初探防护
上面这张表又与下面表对应,0x83十进制是131,我们可以寻找下表中131位置,是nslog,然后data对应value是A1
HOOK原理与fishhook初探防护
HOOK原理与fishhook初探防护
与上表想对应去string表中,寻找起始位置:0x6020 + a1便找到nslog的位置了
HOOK原理与fishhook初探防护

5 初探防护

我们用fishhook交换了method_exchangeImplementations,之前使用method_exchangeImplementations进攻的代码就会可以被防护住了。

+(void)load
{
    //进攻的代码!
    // getIMP  setIMP
    Method old = class_getInstanceMethod(self, @selector(btnClick1:));
    Method newMethod = class_getInstanceMethod(self, @selector(click1Hook:));
    method_exchangeImplementations(old, newMethod);
    
    //防护代码!
    struct rebinding bd;
    bd.name = "method_exchangeImplementations";
    bd.replacement = myExchange;
    bd.replaced = (void *)&exchangeP;
    struct rebinding rebs[1] = {bd};
    rebind_symbols(rebs, 1);
    
   
}

//防护代码
//函数指针变量
void
(*exchangeP)(Method _Nonnull m1, Method _Nonnull m2);
void myExchange(Method _Nonnull m1, Method _Nonnull m2){
    NSLog(@"检测到HOOK!!");
}


-(void)click1Hook:(id)sender{
    NSLog(@"HOOK成功!!");
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (IBAction)btnClick1:(id)sender {
    NSLog(@"按钮1调用了!");
    
}


- (IBAction)btnClick2:(id)sender {
    NSLog(@"按钮2调用了!");
    
}
相关标签: HOOK

上一篇: OP-TEE 环境搭建

下一篇: git的安装