iOS逆向-15:Hook原理

Hook概述

HOOK,中文譯為“掛鉤”或“鉤子”。在iOS逆向中是指改變程序運(yùn)行流程的一種技術(shù)。通過hook可以讓別人的程序執(zhí)行自己所寫的代碼。在逆向中經(jīng)常使用這種技術(shù)。所以在學(xué)習(xí)過程中,我們重點(diǎn)要了解其原理,這樣能夠?qū)阂獯a進(jìn)行有效的防護(hù)。

Hook示意

比如說我們收到紅包消息,我們進(jìn)行hook,執(zhí)行自定義的惡意代碼、看看搶紅包需要哪些參數(shù),準(zhǔn)備好參數(shù)調(diào)用搶紅包代碼。就不需要等待用戶點(diǎn)開紅包,點(diǎn)擊搶紅包等一一系列操作了

iOS中HOOK技術(shù)的幾種方式

  1. Method Swizzle
    ???
    利用OC的Runtime特性,動(dòng)態(tài)改變SEL(方法編號(hào))和IMP(方法實(shí)現(xiàn))的對(duì)應(yīng)關(guān)系,達(dá)到OC方法調(diào)用流程改變的目的。主要用于OC方法。

  2. fishhook
    ???
    它是Facebook提供的一個(gè)動(dòng)態(tài)修改鏈接mach-O文件的工具。利用MachO文件加載原理,通過修改懶加載和非懶加載兩個(gè)表的指針達(dá)到C函數(shù)HOOK的目的。

  3. Cydia Substrate

Cydia Substrate 原名為 Mobile Substrate ,它的主要作用是針對(duì)OC方法、C函數(shù)以及函數(shù)地址進(jìn)行HOOK操作。當(dāng)然它并不是僅僅針對(duì)iOS而設(shè)計(jì)的,安卓一樣可以用。官方地址:http://www.cydiasubstrate.com/

fishhook

接口函數(shù):

struct rebinding {
  const char *name;//需要HOOK的函數(shù)名稱,C字符串
  void *replacement;//新函數(shù)的地址
  void **replaced;//原始函數(shù)地址的指針!
};
FISHHOOK_VISIBILITY
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);

/*
 * Rebinds as above, but only in the specified image. The header should point
 * to the mach-o header, the slide should be the slide offset. Others as above.
 */
FISHHOOK_VISIBILITY
int rebind_symbols_image(void *header,
                         intptr_t slide,
                         struct rebinding rebindings[],
                         size_t rebindings_nel);

demo:

- (void)viewDidLoad {
    [super viewDidLoad];
    //創(chuàng)建rebinding 結(jié)構(gòu)體
    struct rebinding myNslog;
    myNslog.name = "NSLog";
    myNslog.replacement = my_NSLog;
    myNslog.replaced = (void *)&sysLog;
    struct rebinding bds[] = {myNslog};
    rebind_symbols(bds, 1);
    
}

//原函數(shù)
static void (*sysLog)(NSString *format, ...);
//新函數(shù)
void my_NSLog(NSString *format, ...) {
    format = [format stringByAppendingFormat:@"\nhook成功~?。。?];
    //回到系統(tǒng)的nslog里
    sysLog(format);
}


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

結(jié)果:


image.png

用法比較簡單,那么fishhook是如何hook函數(shù)的呢
我們知道:
OC動(dòng)態(tài)語言特性 方法通過sel找imp
而C語言是靜態(tài)語言 直接通過函數(shù)地址訪問

那么我們猜想一下,fishhook是不是先保存原函數(shù)的地址,然后bl到自己的函數(shù)地址呢?
其實(shí)這個(gè)過程并沒有那么簡單:
MachO Text段(只讀\可執(zhí)行!)
Data段(可讀\可寫) 所以這里面包含了符號(hào),及符號(hào)表
首先編譯時(shí)NSLog的地址我們不知道,NSLog在foundation共享緩存庫中
在訪問NSLog的時(shí)候,使用的其實(shí)是PIC技術(shù)(位置無關(guān)代碼),首先訪問占位符占位符就叫做符號(hào),占8個(gè)字節(jié),dlyd 進(jìn)行對(duì)符號(hào)里的數(shù)據(jù)修改就叫做符號(hào)綁定?。《械姆?hào)列表就叫做符號(hào)表,
因?yàn)橥獠糠?hào)地址不確定所以使用PIC技術(shù)

image.png

把符號(hào)里的地址修改了,做到修改符號(hào)對(duì)應(yīng)地址的關(guān)系
外部的c函數(shù)是動(dòng)態(tài)調(diào)用的,通過符號(hào)找地址,也可以重綁定
函數(shù)名變量名,方法名,編譯完就生成一張符號(hào)表

內(nèi)部符號(hào),本mach內(nèi)的符號(hào)
外部符號(hào),也叫間接符號(hào)表
可以通過 symbol table查看

本地符號(hào) 我自己內(nèi)部使用的,去符號(hào)去的是本地符號(hào)
全局符號(hào) 暴露給外界使用的,比如第三方庫,
objcdump --macho -t SymbolDemo 可以看到符號(hào)
l 本地
g 全局

indirect symbols間接符號(hào)表

外部符號(hào)的是在懶加載符號(hào),在第一次調(diào)用才綁定,我們通過匯編看一下流程
首先我們?cè)诘谝徽{(diào)用nslog的地方打一個(gè)斷點(diǎn),看匯編


image.png

通過image list 找到macho的偏移是 0x0000000104454000,也就是pagezero+ASLR
此次運(yùn)行時(shí)的ASLR是0x4454000,將0x10445a4a8 - 0x4454000 = 0x00000001000064a8 就是macho文件bl的位置:


image.png

發(fā)現(xiàn)是跳到外部符號(hào)的樁,樁里面有一段代碼,匯編CTRL + Stepinto點(diǎn)擊去看匯編:
image.png

br x16 0x000000010445a55c - 0x4454000 = 0x000000010000655c:
image.png

br去符號(hào)表里的地址執(zhí)行665c,找655c:


image.png

發(fā)現(xiàn)執(zhí)行的是上面紅框出來的代碼, 本地的一行代碼 ldr #1008000,即符號(hào)綁定
image.png

綁定之后,懶加載符號(hào)表里的data就修改了。

總結(jié)

外部符號(hào)綁定過程

  • 外部函數(shù)調(diào)用執(zhí)行樁里面的代碼 (Text stubs)
    通過懶加載符號(hào)表里面的地址去執(zhí)行
  • 懶加載符號(hào)表里面默認(rèn)存儲(chǔ)的是尋找binder的代碼
    binder函數(shù)在非懶加載符號(hào)表里(程序運(yùn)行就綁定好了)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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