Hook principle - reverse development

Today we will continue to explain another important element --Hook principle of reverse engineering developed to explain. Hook, Chinese can be translated as "hook" or "hook", a technology development program that runs in reverse change. To explain the process according to the following

  1. Hook Overview
  2. Hook technical means
  3. fishhook Principles and Practice
  4. Symbol Table View function name
  5. to sum up

A, Hook Overview

In the reverse development is meant to change the running process technology that allows their code to run someone else's program by Hook. Hook need to understand its principles, so it can be an effective protection against malicious code attacks.

 

Two, Hook technical means

2.1 Method Swizzle way

Method Swizzle already talked about last time, is the use of the characteristics of OC Runtime, and to dynamically change the SEL (method number) and IMP (method implementation) corresponding relationship to achieve the purpose of the method call OC process changes. OC is the main method used.

2.2 Cydia Substrate way

Cydia Substrate formerly known as Mobile SubStrate, a major role to perform the operation for address Hook C functions, OC functions and function. And there is a great advantage, Cydia Substrate is not just designed for iOS, Andriod same can also be used.

2.2.1

Cydia Substrate defines a set of functions and macros, call objc the underlying runtime instead of the objective function and fishHook system or method.

There are two functions

  • MSHookMessageEx method is mainly used for OC
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
  • MSHookFunction mainly for C and C ++ functions
void MSHookFunction(voidfunction,void* replacement,void** p_original)

2.2.2 MobileLoader

MobileLoader mainly used to load third-party applications dylib running. When you start MobileLoader loaded into the specified third-party dynamic libraries, dynamic libraries are also third-party crackers we write.

2.2.3 safe mode

The nature of crackers that dylib, parasitic program to others in the process. But once the system process error, it may lead to the collapse of the entire process may also lead to iOS crash. Introduced in Cydia Substrate in safe mode, if the error once, the three parties will be disabled dylib easy troubleshooting and repair.

2.3 fishHook

fishHook Facebook is to provide a dynamic link Mach-O file modification tool. This file is loaded by using the principle of Mach-O, by modifying the non-lazy loading and lazy loading table pointer two purposes Hook C function.

Today, we mainly on the third way fishHook achieve the purpose of the program change.

 

Three, fishhook principles and examples

3.1 Overview

fishhook source address https://github.com/facebook/fishhook

There are two main methods fishhook and a structure

See the code structure, into the red portion of the circled tags, can be used to hook fishhook code.

 

 3.2 Examples

3.2.1 Demo1 Example 1

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

- (void)viewDidLoad {
    [super viewDidLoad];
     NSLog(@"123");
    //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-----------
//函数指针,用来保存原始的函数地址 (C 语言语法,函数指针类型变量)
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(@"点击了屏幕!!");
}

上面的代码运行结果如下:

3.2.2 Demo2实例2

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("哈哈");
}

运行结果如下:

从上面可以看出自定义的交换方法为什么交换不了呢?首先可以肯定的是代码是OK的,下面我们讲解原理,为什么自定义的方法不行呢?

 

 3.3 原理探究

Mach-O文件是如何加载的?

Dyld工具动态加载,加载MachO文件完成后,开始加载依赖的动态库,也就是通过上篇博客的image List 可看到相关的类库。

PIC(Promrammable Interrupt Controller)位置代码独立,由外设发出中断请求需要中断控制器来处理。

Mach-O文件内部调用系统函数时:

  • Mach-O _data段建立了一个指针(也就是符号,实现指向内部的函数调用,指向了外部的函数地址),指向了外部函数(dyld),可读可写,当Mach-O被加载进去,就会指向所指的函数。
  • Dyld会动态的绑定,将Mach-O中的data 段中指针指向了外部的函数,也是Dyld为什么叫做动态绑定的原因。

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

 

下面我们是真实查看内容,通过实例

利用第一个Demo来测试,运行起来,然后查看可执行文件,通过MachoView工具

 

从图2看出offset偏移地址为3028,也就是NSLog函数文件的偏移地址,懒加载此表时在Mach-O文件偏移地址+函数偏移的地址。

下面以Demo1查看,在Demo1打断点,查看Mach-O函数偏移地址,通过指令image list 第一个就是Mach-O内容和地址(本人上篇博客地址即可)

Mach-O在内存的偏移地址也就是Mach-O的真实地址,发现为 0x000000010a9c5000

通过上面红色加重算法,计算Mach-O文件Data段的函数指针

发现执行完只有就会被绑定。NSLog函数文件就会被绑定。

下面再看一下,对于屏幕点击的,hook如下

前提是我们去除ViewDidLoad方法里面的NSLog(@“123”)这句代码,运行代码,最后将断点断在touchesBegan里面,此时开始看地址和内容

截图的前两次打印是程序运行时,但是未曾点击touchesBegan,后两次是点击屏幕时断点进入到了里面,再看内容,打印的对象是NSLog还是myNslog,通过上面发现是myNslog,说明Hook成功。

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

fishhook是根据方法字符串的名字“NSLog”,它是怎么找到的呢?下面将讲解利用符号表查看函数名称字符串。

 

四、符号表查看函数名称

 再次查看Mach-O文件,查看懒加载表中的NSLog函数

懒加载表是和动态符号表是一一对应关系,通过上面发现NSLog函数时第一个,而对应的Dynamic Symbol table也是第一个,打开Dynamic Symbol table

查看Dynamic Symbol Table 第一个也是NSLog,查看Data值为7A,对应的十进制为122,然后到Symbols Table里面查看122,如下:

 

查看Symbols Table的data值为0000009B,然后在String Table Index去看函数偏移值为0000009B的内容,如下:

 

 为什么选择00004F94查看NSLog呢,我们从上面得知Symbols Table的data值为0000009B,然后加上String Table的函数第一个地址为00004F04,然后将0000009B + 00004F04 = 0X4F9F,最后看00004F94里面包含了0X4F9F,蓝色内容看出是NSLog内容,也就是找到啦。完美!!!

以上过程可以在fishhook中github上有说明图:

 

上面的说明图也就是通过符号表查看函数名称以及反过来也可以逆查的过程。配上说明图,方便大家熟悉流程。

 

五、总结

上面讲述了Hook的几种技术方式以及fishhook的原理探究,以及如何让别人的app实现自己的代码。下面我们对此总结一下,写了一个本篇博客的整个过程便于大家整理,希望对大家有所帮助加深理解。

Guess you like

Origin www.cnblogs.com/guohai-stronger/p/11921916.html