代碼注入&HOOK了解

通常情況下,想去了解一個App,可以進(jìn)行重簽名后,在進(jìn)行view hierarchy debug調(diào)試了解。
對App破解時,一般是修改原始的程序,主要是利用代碼注入的方式,注入代碼就會選擇Framework或者Dylib等第三方庫等方式注入。

Framework注入

  • 重簽名App
  • Xcode新建Framework,編譯,將庫安裝進(jìn)App包中
  • 通過yololib注入Framwork庫路徑。修改Mach-O文件$yololib Mach-O文件路徑 Framework文件路徑
    • 所有的Framework加載都是有DYLD加載進(jìn)內(nèi)存被執(zhí)行的
    • 注入成功的庫路徑會寫入Mach-O文件的LC_LOAD_DYLIB字段中
  • 替換Mach-O文件,重新打包成.ipa文件

腳本注入方式:
重簽名腳本中追加注入腳本
yololib "目標(biāo)App的Mach-O路徑" "注入的framework文件路徑"

Dylib注入

  • 重簽名App
  • 通過Xcode新建Dylib庫(注意:Dylib屬于MacOS,所以需要修改屬性)
  • 添加Target依賴,讓Xcode將自定義Dylib文件打包進(jìn)App包中
  • 利用yololib指令進(jìn)行注入(同F(xiàn)ramework注入)

HOOK

HOOK,中文譯為“掛鉤”或者“鉤子”。
在iOS逆向開發(fā)中,是指改變程序運(yùn)行流程的一種技術(shù)。通過hook可以使別人的程序執(zhí)行自己所寫的代碼。

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

Method Swizzle

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

原理

在OC中,SEL和IMP之間的關(guān)系,就好像書的目錄一樣。
SEL是方法編號,就像“標(biāo)題”一樣
IMP是方法實(shí)現(xiàn)的真實(shí)地址,就像“頁碼”一樣。
Runtime提供了交換兩個SELIMP對應(yīng)關(guān)系的函數(shù)。

Method Swizzle的實(shí)現(xiàn)方式

// 添加方法的方式進(jìn)行交換
Method oldMethod = class_getInstanceMethod(objc_getClass("class"), @selector(oldSelector));
BOOL didAddMethod = class_addMethod(objc_getClass("class"), @selector(newSelector), my_selector, "v@:");
Method newMethod = class_getInstanceMethod(objc_getClass("class"), @selector(newSelector));
method_exchangeImplementations(oldMethod, newMethod);

// 新增的IMP
void newSelector(id self, SEL _cmd) {
    // hook實(shí)現(xiàn)
    [self performSelector:@selector(newSelector)];  //繼續(xù)執(zhí)行原始方法
}
// 替換
Method oldSel = class_getInstanceMethod(objc_getClass("class"), @selector(oldSel));
oldSelector = method_getImplementation(oldSel);  //舊的IMP保存
class_replaceMethod(objc_getClass("class"), @selector(oldSel), newSelector, "v@:");

// 用于保存舊的IMP
IMP (*oldSelector)(id self, SEL _cmd);
// 新的IMP實(shí)現(xiàn)
void newSelector(id self, SEL _cmd) {
    // hook實(shí)現(xiàn)
    oldSelector(self, _cmd);
}
// getIMP 和 setIMP 進(jìn)行方法修改
Method oldSel = class_getInstanceMethod(objc_getClass("class"), @selector(oldSel));
oldSelector = method_getImplementation(oldSel);
method_setImplementation(oldSel, newSelector);

IMP (*oldSelector)(id self, SEL _cmd);

void newSelector(id self, SEL _cmd) {
    // hook實(shí)現(xiàn)
    oldSelector(self, _cmd);
}

fishHook

fishhook 源碼地址:https://github.com/facebook/fishhook
Facebook提供的一個動態(tài)修改鏈接Mach-O文件的工具。
利用Mach-O文件加載原理,通過修改懶加載非懶加載兩個表的指針,達(dá)到C函數(shù)Hook的目的。

fishhook.h

/*
 * 結(jié)構(gòu)體
 * 表示從符號名到替換名的特定重新綁定
 */
struct rebinding {
  const char *name;   //需要HOOK的函數(shù)名稱,C字符串
  void *replacement;  //新函數(shù)的地址
  void **replaced;    //原始函數(shù)地址的指針!
};

/*
 * 重新綁定符號
 * rebindings:要重新綁定的結(jié)構(gòu)體數(shù)組
 * rebindings_nel:重新綁定的數(shù)量
 * 如果rebind_functions被多次調(diào)用,
 * 則要重新綁定的符號將被添加到現(xiàn)有的重新綁定列表中,
 * 如果給定的符號被多次重新綁定,則優(yōu)先執(zhí)行后面的重新綁定。
 */
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);

/*
 * 如上所述重新綁定,但僅在指定的image中。
 * header:指iamge的頭
 * slide:是相對偏移量(ASLR)
 */
int rebind_symbols_image(void *header,
                         intptr_t slide,
                         struct rebinding rebindings[],
                         size_t rebindings_nel);

fishhook使用例子

- (void)hookFunction {
    
    struct rebinding nslog;
    nslog.name = "NSLog";
    nslog.replacement = myNSLog;
    //fishhook在運(yùn)行時刻,動態(tài)獲取相應(yīng)函數(shù)的地址
    nslog.replaced = (void *)&sys_nslog;  
    
    struct rebinding rebs[1] = {nslog};
    
    rebind_symbols(rebs, 1);
}

// 函數(shù)指針,用于保存原始函數(shù)地址
static void(*sys_nslog)(NSString *format,...);

// 定義一個新的函數(shù)
void myNSLog(NSString *format,...) {
    // hook 內(nèi)容實(shí)現(xiàn)

    sys_nslog(format);  //調(diào)用原來的函數(shù)
}

只針對系統(tǒng)的函數(shù),對于自定義的函數(shù)無法進(jìn)行交換HOOK。

原理
  • 兩個前導(dǎo)知識

    • 蘋果為了節(jié)約內(nèi)存和提高加載速度,將系統(tǒng)的動態(tài)庫放在內(nèi)存的特殊位置,然后將這塊內(nèi)存共享給其他應(yīng)用。這塊區(qū)域就是動態(tài)庫共享緩存(dyld share cache)。
    • PIC技術(shù)(位置代碼獨(dú)立)
      • 由于使用共享緩存,使得所調(diào)用的系統(tǒng)函數(shù)在編譯時無法確定內(nèi)存地址
      • 所以蘋果采用了PIC技術(shù),在Mach-O文件的DATA段中建立兩張表,懶加載和非懶加載表,利用存放指向外部函數(shù)的指針
      • 在運(yùn)行,調(diào)用到對應(yīng)的函數(shù)時,DYLD則會相應(yīng)的函數(shù)進(jìn)行綁定。
  • 通過字符查找對應(yīng)的表

    • fishhook利用string Table、Symbols、indirect symbols、懶加載表之間的對應(yīng)關(guān)系查找到相應(yīng)的指針,再通過重新綁定的方式進(jìn)行指針修改。

fishhook就是利用綁定符號這一邏輯進(jìn)行方法的替換綁定,而自定義函數(shù)無需通過符號表,因此無法進(jìn)行重新綁定。

Cydia Substrate

Cydia Substrate 原名 Mobile Substrate,它主要作用是針對OC方法,C函數(shù)以及函數(shù)地址進(jìn)行HOOK操作。不僅僅只是針對iOS設(shè)計的,Android一樣可用。

MobileHooker

采用一系列的宏和函數(shù),底層調(diào)用objc的Runtimefishhook來替換系統(tǒng)或者目標(biāo)應(yīng)用的函數(shù)。

兩個函數(shù):
  • MSHookMessageEx
    主要作用于Objective-C方法
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
  • MSHookFunction
    主要作用于C和C++函數(shù)
void MSHookFunction(void function, void* replacement, void** p_original)

MobileLoader

MobileLoader用于加載第三方dylib到運(yùn)行的應(yīng)用程序中。
啟動時MobileLoader會根據(jù)規(guī)則把指定目錄的第三方的動態(tài)庫加載進(jìn)去,第三方的動態(tài)庫也就是我們所寫的Hook代碼。

Safe Mode

破解程序本質(zhì)是dylib,寄生在別人的進(jìn)程里。
系統(tǒng)進(jìn)程一旦出錯,可能導(dǎo)致整個進(jìn)程崩潰,崩潰后會造成iOS癱瘓。所以CydiaSubstrate引入了俺去模式,在安全模式下的所有基于CydiaSubstrate的第三方dylib都會被禁用,便于差錯和修復(fù)。

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

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

  • HOOK,中文譯為“掛鉤”或“鉤子”。在iOS逆向中是指改變程序運(yùn)行流程的一種技術(shù)。通過hook可以讓別人的程序執(zhí)...
    鼬殿閱讀 1,654評論 0 2
  • 簡述 在做逆向工程時, 我們可以使用HOOK技術(shù)修改工程. 這里有一個問題是如何將我們的代碼打包到原工程中? 這里...
    煙影很美閱讀 986評論 0 0
  • 注入小結(jié) 通過之前的學(xué)習(xí),我們知道了利用動態(tài)庫注入的兩種方式: 注入 App 后,使得 項(xiàng)目和動態(tài)庫產(chǎn)生關(guān)聯(lián)關(guān)系。...
    Superman168閱讀 14,434評論 4 5
  • Hook 1. 概述:Hook,中文譯為“掛鉤”或“鉤子”。在iOS逆向中是指改變程序運(yùn)行流程的一種技術(shù)。通過ho...
    Nice_cheo閱讀 1,578評論 0 0
  • 來自:https://www.cnblogs.com/dengzhuli/p/9952202.html 一、前言 ...
    介和閱讀 1,750評論 0 5

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