fishhook-動態(tài)修改MachO文件

fishhook.png

學(xué)習(xí)hook灾茁,不是要攻擊別人窜觉,破壞別人的應(yīng)用場景,而是為了更好的防護北专,讓自己的應(yīng)用更堅固更安全禀挫。

一、動態(tài)庫注入回顧

《動態(tài)庫注入》中使用了yololib對自定義動態(tài)庫在WX應(yīng)用中插入拓颓,既然能插入自定義庫语婴,我們就利用hook技術(shù)做了小小的改動,替換了登錄按鈕的方法,并攔截了微信步數(shù)上傳的方法砰左,修改了步數(shù)匿醒。hook是改變程序執(zhí)行流程的技術(shù),能夠修改其他應(yīng)用缠导,也能對自己應(yīng)用做防護廉羔。

通常替換方法有如下:

  1. 使用method_exchange交換selimp指針;
  2. 通過getImp獲取原有函數(shù)指針僻造,通過setImp設(shè)置原sel指向的指針為自定義函數(shù)指針憋他;
  3. 通過getImp獲取原有函數(shù)指針,通過replace替換原sel指向的指針為自定義函數(shù)指針髓削,通setImp一樣竹挡。

自己項目中使用:

通常在自己項目中使用,建立分類立膛,在分類load中來替換方法揪罕,以達到監(jiān)聽方法調(diào)用的目的。

hook視圖的出現(xiàn)消失:跟蹤頁面位置旧巾;
hook析構(gòu)函數(shù)deallocdeinit):跟蹤對象釋放狀況耸序;
hook消息轉(zhuǎn)發(fā)方法(forword):避免調(diào)用未實現(xiàn)方法而產(chǎn)生崩潰;
hook數(shù)組objectAtIndexedSubscript方法:避免數(shù)組越界崩潰鲁猩;
……

只要是OC的方法都可以根據(jù)業(yè)務(wù)需求進行監(jiān)聽修改或替換。

在其他應(yīng)用中使用:

通過動態(tài)庫注入的方式罢坝,來插入自己的load廓握,讓自己的代碼能和其他項目一起執(zhí)行,同樣使用我們常規(guī)的替換方法即可嘁酿。通過查看視圖頁面屬性確定要hook的目標(biāo)對象隙券。

hook微信步數(shù)獲取方法:實現(xiàn)微信步數(shù)修改;
hook微信搶紅包相關(guān)方法:實現(xiàn)自動搶紅包功能闹司;
hook微信消息撤回方法:實現(xiàn)拒絕消息撤回功能娱仔;
(ps:學(xué)習(xí)中,實戰(zhàn)不多游桩,有方法就有更多的可能)

在其他應(yīng)用中是通過動態(tài)庫來進行hook的牲迫,因此在目標(biāo)對象所在類的方法列表中并沒有要替換的方法,回歸原有方法調(diào)用會出現(xiàn)崩潰借卧,這里可以使用獲取原有方法的函數(shù)地址盹憎,直接調(diào)用函數(shù)即可實現(xiàn)原有方法的調(diào)用。

以上是針對OC的動態(tài)特性來hook的铐刘,我們能夠hook動態(tài)語言下的函數(shù)陪每,那么能不能直接hook系統(tǒng)的靜態(tài)函數(shù)呢,下面來看一下fishhook是如何hook的。

二檩禾、fishhook概述

fishhookFaceBook的開源庫挂签,能夠動態(tài)的修改MachO的符號表,來hook系統(tǒng)的C函數(shù)盼产。 C函數(shù)是在編譯時來確定函數(shù)地址在內(nèi)存中的偏移量饵婆,編譯后該偏移量是確定的,為什么說是偏移量是確定的呢辆飘?

在很多系統(tǒng)中都采用了 ASLR 技術(shù)啦辐,對堆、棧蜈项、共享庫等線性區(qū)布局進行隨機化芹关,來避免攻擊者直接獲取攻擊代碼位置。MachO的首地址是隨機變化的紧卒,找到首地址就能找到對應(yīng)的函數(shù)地址侥衬,即 Offset + MachO

靜態(tài)語言:編譯時確定函數(shù)地址
動態(tài)語言:運行時確定函數(shù)地址

三跑芳、fishhook簡單使用

使用步驟:

1轴总、直接將.c、.h加入到工程博个;
2怀樟、創(chuàng)建結(jié)構(gòu)體指明被替換的函數(shù)、替換的函數(shù)盆佣、接收原函數(shù)地址的指針往堡;
3、綁定符號表共耍。

使用庫函數(shù)交換系統(tǒng)NSLog函數(shù):

#pragma mark - 交換NSLog
-(void)exchangeLog {
     NSLog(@"我來了");
    //hook NSLog函數(shù)
    struct rebinding imp;
    imp.name = "NSLog";
    imp.replacement = my_NSLog;
    imp.replaced = &sys_nslog;
    
    //存放rebinding結(jié)構(gòu)體數(shù)組虑灰,一次可以交換多個函數(shù)
    struct rebinding rebs[1] = {imp};
    rebind_symbols(rebs, 1);
    NSLog(@"點擊了屏幕");
}
//實現(xiàn)一個函數(shù)來替換原有函數(shù)-函數(shù)名稱即是函數(shù)的指針
void my_NSLog(NSString *format, ...) {
    printf("攔截打印\n");
    sys_nslog(format);
}
//定義指針來接收原始函數(shù)的指針
static void (*sys_nslog)(NSString *format,...);

打印如下:

攔截打印
點擊了屏幕

運行輸出,方法被攔截痹兜,說明NSLog函數(shù)已被替換穆咐。

上面有提到,所有的函數(shù)地址在編譯后都是確定字旭,在OC中能夠交換方法是因為有selimp的連接過程对湃,函數(shù)與用戶之間有一個中間者,那么fishhook應(yīng)該也是如此谐算,修改了中間者的imp指向熟尉,否則直接調(diào)用函數(shù),就沒有交換的可能洲脂,在MachO中這個中間者叫符號斤儿。

動態(tài)替換:user -> sel -> imp
靜態(tài)替換:user -> symbol -> imp

hook自定義函數(shù)

-(void)exchangeFun{
    struct rebinding imp;
    imp.name = "old_func";
    imp.replacement = new_func;
    imp.replaced = &sys_func;
    struct rebinding rebs[1] = {imp};
    rebind_symbols(rebs, 1);
    old_func();
}
void (*sys_func);
void old_func(){
    printf("old_func\n");
}
void new_func(){
    printf("new_func\n");
}

打印如下:

old_func

打印還是原來的方法剧包,這里并沒有替換。這里可以猜想自定義函數(shù)調(diào)用沒有產(chǎn)生中間者往果,這里是直接調(diào)用的疆液,所以無法交換。

四陕贮、fishhook的實現(xiàn)原理

fishhook主要利用了共享緩存功能和PIC技術(shù)來實現(xiàn)hook功能堕油。

動態(tài)共享緩存

iOS系統(tǒng)為節(jié)省內(nèi)存資源,將系統(tǒng)的動態(tài)庫資源統(tǒng)一放在了系統(tǒng)的共享區(qū)域肮之,該區(qū)域其他應(yīng)用都可以訪問掉缺。

PIC技術(shù)

PIC技術(shù)叫位置代碼獨立,在MachO文件中會預(yù)留出一段空間戈擒,這一段空間叫做符號表眶明,在MachO文件的數(shù)據(jù)段中。dyld在加載MachO文件到內(nèi)存中后筐高,會將共享區(qū)的系統(tǒng)函數(shù)地址綁定到對應(yīng)的符號上搜囱,并插入到符號表中。這樣在項目中調(diào)用相關(guān)系統(tǒng)函數(shù)時柑土,實際上調(diào)用的是對應(yīng)的符號蜀肘,通過符號來找到具體的系統(tǒng)函數(shù)地址。

symbol.png

到這里思路應(yīng)該清晰很多稽屏,fishhook實現(xiàn)如下:

  1. 根據(jù)符號(字符)獲取系統(tǒng)函數(shù)地址扮宠;
  2. 替換符號指向的地址為用戶聲明的函數(shù)地址(符號綁定);
  3. 對外部聲明的指針進行系統(tǒng)函數(shù)地址賦值狐榔。

上面所提到的自定義函數(shù)無法hook也就了然了涵卵,自定義函數(shù)地址確定在代碼段中,缺少dyld的符號綁定階段荒叼,并且應(yīng)用中調(diào)用的是最原始的函數(shù)地址,因此無法交換典鸡。

data段:程序運行期間可讀可寫
代碼段:程序運行期間只讀

五被廓、fishhook符號綁定分析

這里使用 MachOView 工具,對以上給出的代碼生成的MachO文件進行分析萝玷。

*獲取符號表地址

1嫁乘、machO符號表中有懶加載表(_la_symbol_ptr)和非懶加載表(_nl_symbol_ptr)的_data段,在表中存放著與外部綁定的函數(shù)指針球碉,在懶加載端有offset地址蜓斧,如下:

lazy_symbol.png
  • 這里都是我們熟悉的名稱,這些函數(shù)的使用是需要進行懶加載綁定的
  • 提供了相對于MachO起始地址的偏移量offset睁冬,實際地址即是系統(tǒng)函數(shù)所在的內(nèi)存地址

這里觀察NSLog函數(shù)挎春,記住offset=0x4030這個偏移量看疙。

2、在打印函數(shù)調(diào)用前下斷點直奋,執(zhí)行image list獲取模塊列表能庆,如下:

image.png
  • 這里的image就是一個個模塊,一個個MachO文件

找到第一個模塊地址:0x00000001081f4000脚线,該地址為應(yīng)用程序的起始地址搁胆,在程序運行期間是固定,重新啟動該地址則會隨機變化邮绿,即上面所提到的 ASLR 技術(shù)渠旁。

3、起始地址與偏移量相加:0x00000001081f4000 + 4030 = 0x1081F8030(這里使用mac計算器的編程器)船逮,便是符號表的地址顾腊,記住這個值。

讀內(nèi)存

1傻唾、讀取符號表地址

memory read 0x1081F8030
offset.png

取第一行投慈,從右向左取8位數(shù)據(jù):0x01081f6984,改地址即是系統(tǒng)函數(shù)NSLog地址冠骄,使用命令:

dis -s 0x01081f6984

打印匯編伪煤,查看綁定情況。打印如下:

dis.png

由于是查看懶加載表的偏移量凛辣,此時函數(shù)還沒有調(diào)用抱既,并沒有綁定。

2扁誓、斷點到rebind_symbols(rebs, 1)處防泵,運行再打印符號表地址:

memory read 0x1081F8030

打印如下:

0x1081f8030: be e1 58 08 01 00 00 00 5d a5 57 08 01 00 00 00  ..X.....].W.....
0x1081f8040: 16 6b 29 0c 01 00 00 00 ca 69 1f 08 01 00 00 00  .k)......i......

同上從右向左取8位,再來查看匯編內(nèi)容:

dis -s 0x010858e1be

打印如下:

func.png

符號表有內(nèi)容了蝗敢,說明NSLog為懶加載捷泞,運行后,將Foundation中的NSLog加入到符號表中寿谴。因此只要該函數(shù)被加載過锁右,就可以找到綁定的符號地址。

3讶泰、繼續(xù)執(zhí)行咏瑟,使用fishhook進行hook,再查看符號表地址內(nèi)容:

memory read 0x1081F8030

打印如下:

hook_func.png

由于fishhook對系統(tǒng)NSLog函數(shù)的替換痪署,以上地址發(fā)生了變化码泞,取地址查看內(nèi)容:

dis -s 0x01081f5c60

打印如下:

replace.png

此時發(fā)現(xiàn)符號表綁定了fishhookDemomy_NSLog,說明此處的符號綁定被替換了狼犯。

通過以上實驗?zāi)軌蛑溃?code>dyld會對系統(tǒng)函數(shù)進行符號綁定余寥,符號表在數(shù)據(jù)段领铐,可讀可寫,dyld可以綁定劈狐,fishhook也可以通過系統(tǒng)函數(shù)進行綁定罐孝。

通過符號表查找系統(tǒng)函數(shù)

回到MachO文件,來看看Lazy Symbol肥缔、Dynamic Symbol Table莲兢、Symbol Table、String Table表關(guān)系:

1续膳、Lazy SymbolDynamic Symbol Tabel一一對應(yīng)(在數(shù)組的下標(biāo)一致)這兩個表包含了所有與動態(tài)庫相關(guān)的符號改艇;

2、Dynamic Symbol TabelSymbol Table關(guān)聯(lián)坟岔,Dynamic Symbol Table中的Data字段是Symbol Table數(shù)組的下標(biāo)谒兄;

3、Symbol Table中的data字段地址 + String Table表的起始地址社付,就是目標(biāo)函數(shù)對應(yīng)字符的位置承疲。

以NSLog為例驗證

lazy.png
indirect.png
  • 上面兩張圖的下標(biāo)與value一一對應(yīng)

找到indirect Symbols表中的_NSLog項:

indirect_data.png

NSLog函數(shù)為例,找到Data地址0x94鸥咖,等于十進制148燕鸽,即為Symbol Table表中NSLog對應(yīng)的下標(biāo),如下:

symbol.png

通過下標(biāo)找到了對應(yīng)的符號啼辣,主要上面的標(biāo)注0xBA為String Table中的偏移量啊研,表的起始地址加上偏移量即是函數(shù)名所在的位置。

string_table.png

通過首地址獲取最終函數(shù)名鸥拧,0xBA + 0x6180 = 0x623A党远,找到0x623A地址處,如下:

string.png

最終找到了系統(tǒng)的函數(shù)富弦。

小結(jié):

OC的運行時替換沟娱,和fishhook對系統(tǒng)函數(shù)的替換,都是由于有中間者的存在腕柜,才有hook的機會花沉。

六、fishhook源碼分析

……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末媳握,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子磷脯,更是在濱河造成了極大的恐慌蛾找,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赵誓,死亡現(xiàn)場離奇詭異打毛,居然都是意外死亡柿赊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門幻枉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碰声,“玉大人,你說我怎么就攤上這事熬甫∫忍簦” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵椿肩,是天一觀的道長瞻颂。 經(jīng)常有香客問我,道長郑象,這世上最難降的妖魔是什么贡这? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮厂榛,結(jié)果婚禮上盖矫,老公的妹妹穿的比我還像新娘。我一直安慰自己击奶,他們只是感情好辈双,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著正歼,像睡著了一般辐马。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上局义,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天喜爷,我揣著相機與錄音,去河邊找鬼萄唇。 笑死檩帐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的另萤。 我是一名探鬼主播湃密,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼四敞!你這毒婦竟也來了泛源?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤忿危,失蹤者是張志新(化名)和其女友劉穎达箍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铺厨,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡缎玫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年硬纤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赃磨。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡筝家,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邻辉,到底是詐尸還是另有隱情溪王,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布恩沛,位于F島的核電站在扰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏雷客。R本人自食惡果不足惜芒珠,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搅裙。 院中可真熱鬧皱卓,春花似錦、人聲如沸部逮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兄朋。三九已至掐禁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颅和,已是汗流浹背傅事。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留峡扩,地道東北人蹭越。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像教届,于是被迫代替她去往敵國和親响鹃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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