Fishhook 學習筆記

一、Fishhook 是什么?

簡單來說Fishhook就是hook函數(shù)的一種工具,當然它hook的原理和我們熟知的Method Swizzle 方式是不一樣的,它是Facebook提供的一個動態(tài)修改鏈接mach-O文件的工具。

  • Method Swizzle 是利用OC的Runtime特性,動態(tài)改變SEL(方法編號)和IMP(方法實現(xiàn))的對應關系,達到OC方法調(diào)用流程改變的目的。主要用于OC方法。
  • Fishhook 是利用MachO文件加載原理,通過修改懶加載和非懶加載兩個表的指針達到C函數(shù)HOOK的目的。

二、Fishhook的簡單使用

首先在github上下載fishhook庫:


image.png

解壓zip包后,將其中的.c和.h文件拖入你想hook的項目當中,我們所用到的就是這兩個文件,當然網(wǎng)上有大把的關于fishhook的源碼剖析資料,大家可以自行查閱,這里我就直接上代碼了,拖入步驟不作詳細介紹。

#import "ViewController.h"
#import "fishhook.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    //定義rebinding 結構體
    struct rebinding rebind = {};
    rebind.name = "NSLog";
    rebind.replacement = hookNSLog;
    rebind.replaced = (void *)&nslogMethod;
    
    //將上面的結構體 放入 reb結構體數(shù)組中
    struct rebinding red[]  = {rebind};
    
    /*
     * arg1 : 結構體數(shù)據(jù)組
     * arg2 : 數(shù)組的長度
     */
    
    rebind_symbols(red, 1);
    
}

//定義一個函數(shù)指針 用于指向原來的NSLog函數(shù)
static void (*nslogMethod)(NSString *format, ...);

void hookNSLog(NSString *format, ...){
    
    format = [format stringByAppendingString:@"被勾住了"];
    
    nslogMethod(format);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSLog(@"原有NSLog函數(shù)");
}

將文件導入項目后,在ViewController.m 文件中寫入代碼如上,代碼目的是:將點擊屏幕時執(zhí)行的NSLog函數(shù),替換成執(zhí)行hookNSLog函數(shù)。
點擊屏幕時執(zhí)行結果:


image.png

我們先不管原理是怎樣,大家是不是覺得,這執(zhí)行結果和以上代碼干的事,是不是很像runtime的方法交換。
但是從表面上看,runtime和fishhook的區(qū)別,大家都知道使用runtime交換的是OC的方法,而fishhook卻是交換C函數(shù),這里就會有個疑惑,C語言不是靜態(tài)語言嗎,為什么fishhook可以直接交換函數(shù)呢?
ok ! 在疑問之前,我們先將以上代碼稍作修改,在看一下結果。

#import "ViewController.h"
#import "fishhook.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    //定義rebinding 結構體
    struct rebinding rebind = {};
    rebind.name = "funcDlog";
    rebind.replacement = hookNSLog;
    rebind.replaced = (void *)&nslogMethod;
    
    //將上面的結構體 放入 reb結構體數(shù)組中
    struct rebinding red[]  = {rebind};
    
    /*
     * arg1 : 結構體數(shù)據(jù)組
     * arg2 : 數(shù)組的長度
     */
    
    rebind_symbols(red, 1);
    
}

//定義一個函數(shù)指針 用于指向原來的NSLog函數(shù)
static void (*nslogMethod)(NSString *format, ...);

void hookNSLog(NSString *format, ...){
    
    format = [format stringByAppendingString:@"被勾住了"];
    
    nslogMethod(format);
}

void funcDlog(NSString *format, ...){
    
    NSLog(@"%@", format);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    funcDlog(@"原有NSLog函數(shù)");
}


@end

來我們看下代碼的改動:
我們將原來hook的目標轉換了,自己定義了一個函數(shù)void funcDlog(NSString *format, ...),在函數(shù)調(diào)用NSLog函數(shù),而我們這次Hook的目標變成了 funcDlog函數(shù),按照之前的運行結果,猜測這次的運行結果應該還是“ 原有NSLog函數(shù)被勾住了”,但是實際運行結果卻是:

image.png

結果顯示我們的代碼并沒有hook成功,綜合以上兩次運行結果,我們發(fā)現(xiàn)了,fishhook可以實現(xiàn)runtime做不到的將C函數(shù)進行交換,但是我們自己定義的C函數(shù)卻不能交換,只能hook系統(tǒng)的函數(shù),這是為什么呢?我們來看下一個章節(jié)。

三、Fishhook的原理探究

首先在探究fishhook的原理之前,我要清楚幾個問題:

  • MachO是怎么加載的
    • 首先我們要知道,MachO文件是被dyld加載的,dyld是動態(tài)加載,也負責動態(tài)庫的加載。我們都知道動態(tài)庫加載時并不在我們自己的MachO文件內(nèi)部,是存在系統(tǒng)動態(tài)緩存區(qū),當我們MachO文件加載過后會動態(tài)加載我們所依賴的那些動態(tài)庫。
  • ASLR技術
    • 我們的MachO文件在內(nèi)存當中每次的運行地址是不一樣的,MachO文件加載的時地址是隨機的,這就是ASLR技術。蘋果每次加載MachO文件時會隨機分配一個地址,來降低緩沖區(qū)溢出。

那問題來了,每次MachO文件加載的地址不一樣,我們大家都知道,系統(tǒng)的動態(tài)庫緩存區(qū)的地址也是變化的,那每次dyld加載動態(tài)庫的時候是怎樣找到依賴動態(tài)庫進行加載的呢?

  • PIC 位置代碼獨立

    • 當MachO內(nèi)部需要調(diào)用系統(tǒng)的庫函數(shù)時,會現(xiàn)在MachO文件_DATA段中建立一個指針,指向外部函數(shù),dyld就會將指針與函數(shù)進行動態(tài)綁定,將MachO中的DATA段中的指針指向外部函數(shù),從而實現(xiàn)加載。

我們來看下第一份代碼的MachO文件,如圖:


image.png

當MachO內(nèi)部有兩個指針用來加載動態(tài)庫:

  • Non-Lazy Symbol Pointers :不懶加載指針
  • Lazy Symbol Pointers :懶加載指針

這兩個指針就是dyld用來在MachO內(nèi)部調(diào)用系統(tǒng)庫函數(shù)時來指向外部函數(shù)進行動態(tài)綁定加載。從上圖我們可以看出在Lazy Symbol Pointers指針表中NSLog的位置,以及偏移地址是0x8018。

那我們根據(jù)這個偏移地址在第一份代碼中進行LLDB調(diào)試看看結果如何:

  • 首先我們先在 fishhook的代碼執(zhí)行前設置斷點:


    image.png
  • 然后我們先拿到MachO文件在內(nèi)存中的首地址:0x0000000100154000


    image.png
  • 根據(jù)偏移地址拿到指針指向的地址值:


    image.png
  • 根據(jù)地址值中的地址進行反匯編,我看下結果:


    image.png

反匯編后結果清楚顯示地址指向的是Foundation下的 NSLog函數(shù)

ok! 這是還沒有進行fishhook前的NSLog ,那我們將斷點斷到fishhook代碼執(zhí)行后在看結果:


image.png

同樣的偏移地址,地址值卻發(fā)生了變化,反匯編后卻發(fā)現(xiàn),地址指向的是fishhookDemo1下的hookNSLog函數(shù)。

這就是Fishhook的原理:在dyld加載MachO文件所需要的系統(tǒng)函數(shù)時,通過改變MachO文件中的DATA段中指向外部函數(shù)的指針所指向的地址,來實現(xiàn)動態(tài)交換。

這里就可以解釋我們在兩次運行結果對比留下的兩個疑惑:

  • 為什么fishhook可以交換C函數(shù)
    • fishhook 是通過改變dyld加載動態(tài)庫所用的指針指向的函數(shù)地址,來實現(xiàn)的函數(shù)交換 ,所以C函數(shù)通過dyld動態(tài)加載動態(tài)庫也展現(xiàn)出C函數(shù)動態(tài)的一面。
  • 為什么我們自己寫的C函數(shù)fishhook交換不了
    • 我們自己寫的C函數(shù)不在系統(tǒng)動態(tài)庫緩存區(qū),而是存在我們自己的MachO文件當中,不經(jīng)過dyld加載,直接編譯成匯編語言,在MachO中的TEXT段中。所以fishhook的原理不能交換我們自己寫的C函數(shù)。

四、通過符號找到字符串

在上面我們知道了系統(tǒng)的動態(tài)庫與我們的MachO文件是通過dyld在加載時在MachO文件中的一個指針指向了外部函數(shù)來進行加載,但是這只是個地址,我們在代碼中調(diào)用函數(shù)時通過函數(shù)名稱來調(diào)用的,那這個地址和我們調(diào)用的函數(shù)名稱是如何建立起聯(lián)系的呢?我們先來看下剛才的MachO文件,如圖:

圖1:


image.png

圖2:


image.png

從圖1、圖2中我們可以看出Lazy Symbol Pointers 表 和 Dyamic Symbol Table 表中的關系是一一對應的,遍歷前一張表的index就可以對應到后一張表。注意圖2中的對應index行中的 Data 值為0x7F。

圖3:


image.png

在Symbol Table 表中先拿到第一條的偏移地址0xC500。

圖4:


image.png

在圖2中index中獲取的Data值為0x7F,這值是圖4中index的標號,由于圖4中index的偏移為0x10,所以偏移地址+Data對應的偏移地址為0xCCF0,找到當前index的Data值是0xA7。

圖5:


image.png

最后在String Table 表中 偏移首地址+0xA7 的值為0x0000D02B,在表中差得字符串以“_”開頭,以“.”結尾。所得的字符串就是外部函數(shù)地址所對應的函數(shù)名。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 13. Hook原理介紹 13.1 Objective-C消息傳遞(Messaging) 對于C/C++這類靜態(tài)語...
    Flonger閱讀 1,530評論 0 3
  • 13.1 Objective-C消息傳遞(Messaging) 對于C/C++這類靜態(tài)語言,調(diào)用一個方法其實就是跳...
    泰克2008閱讀 2,361評論 1 6
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關于...
    SeanCST閱讀 8,125評論 0 27
  • [TOC] 回顧 注入的相關要素: 注入的形式:利用動態(tài)庫的特性進行注入,包括Framework、Dylib。可以...
    _順_1896閱讀 1,003評論 0 0
  • 2016年的12月,很冷很冷。我從讀書的城市輾轉去到廣州南站,跨過1458.9km去見你。 那時候,我讀書的城市還...
    莫名墨閱讀 324評論 7 7

友情鏈接更多精彩內(nèi)容