- iOS逆向之Method Swizzle
- iOS逆向之fishHook原理探究
- iOS逆向之fishHook怎么通過符號找字符串
學習完上面的文章后,深感fishhook之強大,既然fishhook能hook系統的函數。那么猜想:
如果在我們的項目中hook了Method Swizzle,那么別人還能hook我們的項目嗎??
一、寫上基本的防護,內部使用hook,外部沒有hook
1、新建工程:基本防護,寫個簡單的頁面
代碼如下:
2、需求:在外部hook btnClick2,在內部hook btnClick1,需要保證的是在外部hook btnClick2無效,在內部hook btnClick1生效。
3、拖入fishhook代碼,新建hookMgr類
//專門HOOK
+(void)load{
//內部用到的交換代碼
Method old = class_getInstanceMethod(objc_getClass("ViewController"), @selector(btnClick1:));
Method new = class_getInstanceMethod(self, @selector(click1Hook:));
method_exchangeImplementations(old, new);
//在交換代碼之前,把所有的runtime代碼寫完
//基本防護
struct rebinding bd;
bd.name = "method_exchangeImplementations";
bd.replacement=myExchang;
bd.replaced=(void *)&exchangeP;
struct rebinding rebindings[]={bd};
rebind_symbols(rebindings, 1);
}
//保留原來的交換函數
void (* exchangeP)(Method _Nonnull m1, Method _Nonnull m2);
//新的函數
void myExchang(Method _Nonnull m1, Method _Nonnull m2){
NSLog(@"檢測到了hook");
}
-(void)click1Hook:(id)sender{
NSLog(@"原來APP的hook保留");
}
說明:
- 在做防護之前,先把自己內部需要runtime交換的代碼寫完,比如開放btnClick1給自己內部去hook,其他的hook則禁止
- 使用fishhook hook method_exchangeImplementations方法,這樣當外部使用method_exchangeImplementations方法時,讓它失效
4、運行,分別點擊按鈕1和按鈕2,此時內部hook了btnClick1方法,外部暫時沒有hook任何方法
二、准備ipa
1. 打包ipa
- 將基本防護.app拷貝出來
- 新建文件夾Payload,將基本防護.app拷貝到Payload文件夾中
- cd到Payload的上級目錄,使用命令壓縮,生成ipa
zip -ry Hook.ipa Payload
三、外部hook,注入代碼
1.新建工程:Hook基本防護
代碼注入參考:iOS逆向之代碼注入(framework)
前面在hookMgr中已經做了防護,不能交換btnClick2方法,那么我們寫下hook btnClick2的代碼來測試一下:
+(void)load
{
Method old = class_getInstanceMethod(objc_getClass("ViewController"), @selector(btnClick2:));
Method new = class_getInstanceMethod(self, @selector(click2Hook:));
method_exchangeImplementations(old, new);
}
-(void)click2Hook:(id)sender{
NSLog(@"btnClick2交換成功");
}
運行,分別點擊按鈕1,按鈕2,發現btnClick2交換成功,防護失敗了
2.思考防護失敗的原因
- 1.在基本防護工程里,hookMgr的load方法里加上
NSLog(@"hookMgr--Load");
- 2.在ViewController的load方法里加上
NSLog(@"ViewController--Load");
- 3.在AppDelegate的load方法里加上
+(void)load{
NSLog(@"AppDelegate--Load");
}
- 4.編譯基本防護工程重新運行,生成基本防護.app,重新打包
zip -ry Hook.ipa Payload
- 5.將Hook.ipa拷貝到Hook基本防護工程的APP文件夾里,打開Hook基本防護工程,在WJHook的load方法里加上,
NSLog(@"WJHook---load");
然后運行
發現WJHook(攻擊方)是最早調用的,hookMgr(防護方)是最晚調用的,那么攻擊方方法都交換成功了,你防護方才來防護,明顯是沒用。因此,上面的btnClick2方法仍然被外部交換了,hookMgr沒起到防護的作用。
3.解決辦法
1.修改Complie Sources的順序
-
修改前
-
修改后
2.既然外部的動態庫最先加載,那么防護方自己建立一個動態庫
- 在基本防護工程里新建動態庫antiHook
- 編譯運行
- 生成基本防護.app,重新打包
zip -ry Hook.ipa Payload
- 將Hook.ipa拷貝到Hook基本防護工程的APP文件夾里
3.打開Hook基本防護工程,運行
- 發現我們的防護hookMgr先執行,並且 檢測到了hook
- 至此外部就不能通過hook “Method Swizzle”來交換btnClick2方法
4、弊端
-
如果hookMgr內部要交換方法,需要提前在hookMgr的內部寫好交換代碼,然后再做防護。
-
因為在內部是沒有辦法再進行hook了,所以有些三方庫如果用了Method Swizzle,那么你要做的修改就比較多,需要將工程里用到的全部method_exchangeImplementations換成exchangeP
-
如果用Cydia Substrate或者MonkeyDev來hook,依然能hook成功
5、下面用MonkeyDev來舉例:
1、新建MonkeyDev工程MonkeyDemo,此過程需要先安裝好MonkeyDev
2、將防護的Hook.ipa拷貝到MonkeyDemo->TargetApp文件夾下
-
%hook ViewController 表示hook ViewController這個類
-
-(void)btnClick2:(id) org 表示hook btnClick2這個方法
-
hookMgr是最先加載的,但是MonkeyDev還是能hook成功
6、為什么MonkeyDev和Cydia Substrate能hook成功?
1.首先了解Cydia Substrate的組成部分(MonkeyDev也是集成了Cydia Substrate):
Cydia Substrate主要由3部分組成:
-
1.MobileHooker
MobileHooker顧名思義用於HOOK。它定義一系列的宏和函數,底層調用objc的runtime和fishhook來替換系統或者目標應用的函數.
其中有兩個函數:- MSHookMessageEx 主要作用於Objective-C方法
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
- MSHookFunction 主要作用於C和C++函數
void MSHookFunction(voidfunction,void* replacement,void** p_original)
- MSHookMessageEx 主要作用於Objective-C方法
-
2.MobileLoader
MobileLoader用於加載第三方dylib在運行的應用程序中。啟動時MobileLoader會根據規則把指定目錄的第三方的動態庫加載進去,第三方的動態庫也就是我們寫的破解程序. -
3.safe mode
因為APP程序質量參差不齊崩潰再所難免,破解程序本質是dylib,寄生在別人進程里。 系統進程一旦出錯,可能導致整個進程崩潰,崩潰后就會造成iOS癱瘓。所以CydiaSubstrate引入了安全模式,在安全模 式下所有基於CydiaSubstratede 的三方dylib都會被禁用,便於查錯與修復。
2. MSHookMessageEx底層調用objc的runtime和fishhook來替換系統或者目標應用的函數
在我們的防護代碼中,只防護了method_exchangeImplementations方法,然而method_setImplementation和method_getImplementation並沒有做防護,因此猜想Cydia Substrate就是通過這兩個方法來hook的。
3.實驗
-
在基本防護2的工程中,增加對method_setImplementation和method_getImplementation的防護
-
編譯生成基本防護.app,再次打包成Hook.ipa
-
將Hook.ipa拷貝到MonkeyDemo->TargetApp文件夾下
-
運行MonkeyDemo工程
如圖,做到了防護MonkeyDev的hook,在檢測到hook,強制退出APP
- 那么,上面的防護真的就無法破解了嗎?
答案當然是否定的,提供一個思路:
通過修改MachO文件,在防護動態庫之前調用hook的動態庫,就能實現hook,因為你是在我hook成功之后才做的防護。- 不過新手一般就破解不了上面的防護了。進攻和防護還需要不斷學習!