iOS 逆向開發(fā)16:HOOK原理上(HOOK 系統(tǒng)C函數(shù))

iOS 逆向開發(fā) 文章匯總

目錄


一墓怀、 HOOK概述

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

HOOK示意圖

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文件加載原理,通過(guò)修改懶加載和非懶加載兩個(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/

Method Swizzle
Cydia Substrate-MobileHooker
Cydia Substrate-MobileLoader


二压汪、fishHook的簡(jiǎn)單使用

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

獲取代碼:git clone https:github.com/facebook/fishhook.git

關(guān)鍵函數(shù):

// 用來(lái)重 新綁定符號(hào)表的函數(shù)腺阳。使用它來(lái)交換
FISHHOOK_VISIBILITY
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);
參數(shù)一  存放rebinding結(jié)構(gòu)體的數(shù)組(可以同時(shí)交換多個(gè)函數(shù))
參數(shù)二  rebindings數(shù)組的長(zhǎng)度
struct rebinding {
  const char *name;  // 需要HOOK的函數(shù)名稱,字符串
  void *replacement; // 替換到哪個(gè)新的函數(shù)上(函數(shù)指針,也就是函數(shù)名稱)
  void **replaced;   // 保存原始函數(shù)指針變量的指針(它是一個(gè)二級(jí)指針)
};

2.1 HOOK NSLog

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

- (void)viewDidLoad {
    [super viewDidLoad];
//------------HOOK NSLog------------

    //創(chuàng)建rebinding 結(jié)構(gòu)體
    struct rebinding nslog;
    nslog.name = "NSLog";
    nslog.replacement = my_NSLog;
    //保存NSLog系統(tǒng)函數(shù)地址的指針!
    nslog.replaced = (void *)&sys_nslog;
    
    //需求:HOOK NSLog
    struct rebinding bds[] = {nslog};
    
    rebind_symbols(bds, 1);
}

//函數(shù)指針!
static void (*sys_nslog)(NSString *format, ...);

//新函數(shù)!
void my_NSLog(NSString *format, ...) {
    format = [format stringByAppendingString:@"\n我HOOK到了!"];
    //走到系統(tǒng)的NSLog里面去!
    sys_nslog(format);
}

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

點(diǎn)擊屏幕輸出:hello
????????? 我HOOK到了!

2.2 HOOK Func

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

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

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //----------HOOK  Func -------
    //創(chuàng)建rebinding 結(jié)構(gòu)體
    struct rebinding func;
    func.name = "func";
    func.replacement = my_func;
    //保存NSLog系統(tǒng)函數(shù)地址的指針!
    func.replaced = (void *)&func_p;
    
    //需求:HOOK NSLog
    struct rebinding bds[] = {func};
    
    rebind_symbols(bds, 1);
}

static void (*func_p)(const char * str);

void my_func(const char * str) {
    NSLog(@"HOOK了!!");
    func_p(str);
}

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

點(diǎn)擊屏幕輸出:hello

從2.1和2.2可以看到fishHook只能HOOK系統(tǒng)的函數(shù)不能HOOK自定義的函數(shù)

因?yàn)镹SLog不是本Mach-O文件中的,func是本Mach-O文件中的滴须。編譯的時(shí)候舌狗,并不知道NSLog 的真實(shí)地址!因此可以HOOK NSLog函數(shù)叽奥。


三扔水、fishHook原理探究

How it works

dyld binds lazy and non-lazy symbols by updating pointers in particular sections of the __DATAsegment of a Mach-O binary. fishhook re-binds these symbols by determining the locations to update for each of the symbol names passed to rebind_symbols and then writing out the corresponding replacements.
For a given image, the __DATA segment may contain two sections that are relevant for dynamic symbol bindings: __nl_symbol_ptr and __la_symbol_ptr. __nl_symbol_ptr is an array of pointers to non-lazily bound data (these are bound at the time a library is loaded) and __la_symbol_ptr is an array of pointers to imported functions that is generally filled by a routine called dyld_stub_binder during the first call to that symbol (it's also possible to tell dyld to bind these at launch). In order to find the name of the symbol that corresponds to a particular location in one of these sections, we have to jump through several layers of indirection. For the two relevant sections, the section headers (struct sections from <mach-o/loader.h>) provide an offset (in the reserved1 field) into what is known as the indirect symbol table. The indirect symbol table, which is located in the __LINKEDIT segment of the binary, is just an array of indexes into the symbol table (also in __LINKEDIT) whose order is identical to that of the pointers in the non-lazy and lazy symbol sections. So, given struct section nl_symbol_ptr, the corresponding index in the symbol table of the first address in that section is indirect_symbol_table[nl_symbol_ptr->reserved1]. The symbol table itself is an array of struct nlists (see <mach-o/nlist.h>), and each nlist contains an index into the string table in __LINKEDIT which where the actual symbol names are stored. So, for each pointer __nl_symbol_ptrand __la_symbol_ptr, we are able to find the corresponding symbol and then the corresponding string to compare against the requested symbol names, and if there is a match, we replace the pointer in the section with the replacement.

3.1設(shè)置并進(jìn)入第一個(gè)斷點(diǎn):

編譯查看Mach-O文件

拿到ASLR的值:

ASLR + MachO中的 NSLog Data中的值就是當(dāng)前NSLog的實(shí)際地址:
0x0000000100de0000+0x22a4 = 0x100de22a4

通過(guò)ASLR + MachO中的 NSLog Offset中的值也能看到NSLog的實(shí)際地址:

由于還未進(jìn)行NSLog的符號(hào)綁定,因此此時(shí)NSLog的實(shí)際地址并不是NSLog真實(shí)函數(shù)的地址:

3.2進(jìn)入第二個(gè)斷點(diǎn)

由于是懶加載符號(hào)朝氓,所有在調(diào)用NSLog時(shí)才進(jìn)行了符號(hào)綁定魔市。

3.3進(jìn)入第三個(gè)斷點(diǎn)

經(jīng)過(guò)fishhook將NSLog符號(hào)重新綁定了

C語(yǔ)言是靜態(tài)語(yǔ)言,但不是所有的C函數(shù)調(diào)用都是靜態(tài)的赵哲。外部的C函數(shù)調(diào)用是動(dòng)態(tài)的待德。


四、NSLog間接符號(hào)綁定的流程

什么是符號(hào)表?
對(duì)于函數(shù)名枫夺、變量名将宪、方法名等編譯完都會(huì)生成一張符號(hào)表,符號(hào)分為內(nèi)部符號(hào)外部符號(hào)橡庞。外部符號(hào)(本Mach-O以外的符號(hào))也稱為間接符號(hào)较坛。

符號(hào)也分為本地符號(hào)全局符號(hào)
本地符號(hào):自己內(nèi)部使用的
全局符號(hào):外部也可以使用

// 全局符號(hào) -- 暴露給外界使用
void test() {
}

// 本地符號(hào) -- 作用域?yàn)楸镜胤?hào)
static void test1() {
    NSLog(@"test1");
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    test1();
}

編譯進(jìn)入可執(zhí)行文件目錄:
objdump --macho -t 文件名

可以看到test1是本地符號(hào),test和main是全局符號(hào)

間接符號(hào)表


4.1 NSLog調(diào)用前進(jìn)行符號(hào)綁定

添加如下代碼:

運(yùn)行查看匯編代碼:

0x1047562d0-ASLR(0x0000000104754000)=0x22D0(NSLog的樁

因此調(diào)用NSLog時(shí)是bl到NSLog的樁(一塊代碼)扒最。
樁的值為:1F2003D570E9025800021FD6 -- 即如下代碼:

因此NSLog的執(zhí)行流程為:bl-->樁代碼(去符號(hào)表里面的綁定地址執(zhí)行)-->符號(hào)表



0x0000000104756384(x16)-0x0000000104754000(ALSR)=0x2384

這里可以看到樁執(zhí)行符號(hào)表中初始的地址(此時(shí)NSLog的真實(shí)地址還未綁定)

匯編繼續(xù)執(zhí)行236c的代碼(重新運(yùn)行了一次丑勤,ASLR和上面的不一樣了):

經(jīng)過(guò)執(zhí)行dyld_stub_binder,就將NSLog的符號(hào)綁定了吧趣。

在非懶加載符號(hào)表中可以看到dyld_stub_binder的符號(hào)位置法竞,非懶加載符號(hào)剛開始運(yùn)行就綁定了(上篇文章可以看到非懶加載符號(hào)綁定的時(shí)機(jī))耙厚。


4.2 NSLog符號(hào)綁定后的調(diào)用流程

0x0000000102890000(ALSR)+0x8000(offset) = 0x0102898000

已綁定符號(hào)

現(xiàn)在樁執(zhí)行的就是0x0102898000指向的NSLog的真實(shí)地址了。

間接符號(hào)表的綁定流程:


NSLog間接符號(hào)表的綁定流程


總結(jié)

  • 符號(hào)綁定的過(guò)程
    • 外部函數(shù)調(diào)用是執(zhí)行樁里面的代碼! TEXT, stubs
      • 通過(guò)懶加載符號(hào)表里面的地址去執(zhí)行!
    • 懶加載符號(hào)表里面默認(rèn)保存的是尋找binder的代碼
      • binder函數(shù)在非 懶加載符號(hào)表里面(程序運(yùn)行就綁定好了! )
  • HOOK: 改變程序原有執(zhí)行流程
    • iOS中的HOOK技術(shù)
      • OC方法: MethodSwizzle
      • 系統(tǒng)函數(shù): fishhook
  • fishhook:
    • 重新綁定符號(hào)達(dá)到HOOK的目的
      • 外部符號(hào)岔霸,會(huì)在懶加載和非懶加載表中保存函數(shù)地址
      • fishhook就是找到這兩張表薛躬,并且修改里面的地址做到HOOK!


參考

符號(hào)表Symbol Table
iOS-開發(fā)進(jìn)階02:鏈接與Symbol(上)
iOS-開發(fā)進(jìn)階03:鏈接與Symbol(下)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市呆细,隨后出現(xiàn)的幾起案子泛豪,更是在濱河造成了極大的恐慌,老刑警劉巖侦鹏,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诡曙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡略水,警方通過(guò)查閱死者的電腦和手機(jī)价卤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)渊涝,“玉大人慎璧,你說(shuō)我怎么就攤上這事】缡停” “怎么了胸私?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鳖谈。 經(jīng)常有香客問(wèn)我岁疼,道長(zhǎng),這世上最難降的妖魔是什么缆娃? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任捷绒,我火速辦了婚禮,結(jié)果婚禮上贯要,老公的妹妹穿的比我還像新娘暖侨。我一直安慰自己,他們只是感情好崇渗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布字逗。 她就那樣靜靜地躺著,像睡著了一般宅广。 火紅的嫁衣襯著肌膚如雪葫掉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天乘碑,我揣著相機(jī)與錄音挖息,去河邊找鬼。 笑死兽肤,一個(gè)胖子當(dāng)著我的面吹牛套腹,可吹牛的內(nèi)容都是我干的绪抛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼电禀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼幢码!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尖飞,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤症副,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后政基,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贞铣,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年沮明,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辕坝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荐健,死狀恐怖酱畅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情江场,我是刑警寧澤纺酸,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站址否,受9級(jí)特大地震影響餐蔬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜在张,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一用含、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帮匾,春花似錦、人聲如沸痴鳄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)痪寻。三九已至螺句,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橡类,已是汗流浹背蛇尚。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顾画,地道東北人取劫。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓匆笤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親谱邪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炮捧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 《iOS底層原理文章匯總》[http://www.reibang.com/p/15af435341ce]上一篇文...
    一畝三分甜閱讀 1,397評(píng)論 2 2
  • 1.什么是HOOK ??HOOK,中文譯為“掛鉤”或“鉤子”惦银。在iOS逆向開發(fā)中是指改變程序運(yùn)行流程的一種技術(shù)咆课。通...
    _從今以后_閱讀 664評(píng)論 0 1
  • Hook概述 HOOK,中文譯為“掛鉤”或“鉤子”扯俱。在iOS逆向中是指改變程序運(yùn)行流程的一種技術(shù)书蚪。通過(guò)hook可以...
    恍然如夢(mèng)_b700閱讀 1,050評(píng)論 0 1
  • HOOK,中文譯為“掛鉤”或“鉤子”迅栅。在iOS逆向中是指改變程序運(yùn)行流程的一種技術(shù)善炫。通過(guò)hook可以讓別人的程序執(zhí)...
    鼬殿閱讀 1,434評(píng)論 0 2
  • fishhook是Facebook提供的一個(gè)動(dòng)態(tài)修改鏈接mach-O文件的工具。利用MachO文件加載原理库继,通過(guò)修...
    異想天不開_9950閱讀 19,441評(píng)論 17 108