iOS Hook原理(二)-反hook& MonkeyDev

一情妖、 反 hook 初探

我們Hook別人的代碼一般使用OCMethodSwizzle抖部,如果我們用
fishhookMethodSwizzle hook了逞力,別人是不是就hook不了我們的代碼了弯淘?

1.1 創(chuàng)建主工程 AntiHookDemo

創(chuàng)建一個工程AntiHookDemo您觉,頁面中有兩個按鈕btn1btn2:

image.png

對應(yīng)兩個事件:

- (IBAction)btn1Click:(id)sender {
    NSLog(@"click btn1");
}

- (IBAction)btn2Click:(id)sender {
    NSLog(@"click btn2");
}

1.2 創(chuàng)建防護(hù) HookManager (FrameWork 動態(tài)庫)

這個時候要使用fishhook防護(hù),在FrameWork中寫防護(hù)代碼拖吼×凵希基于兩點(diǎn):

  1. Framework在主工程+ load執(zhí)行之前執(zhí)行+ load
  2. 別人注入的Framework也在防護(hù)代碼之后吊档。

創(chuàng)建一個HookManager Framework篙议,文件結(jié)構(gòu)下:

image.png

AntiHookManager.h

#import <Foundation/Foundation.h>
#import <objc/message.h>

//暴露給外界使用
CF_EXPORT void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);

@interface AntiHookManager : NSObject

@end

AntiHookManager.m:

#import "AntiHookManager.h"
#import "fishhook.h"

@implementation AntiHookManager

+ (void)load {
    //基本防護(hù)
    struct rebinding exchange;
    exchange.name = "method_exchangeImplementations";
    exchange.replacement = hp_exchange;
    exchange.replaced = (void *)&exchange_p;
    struct rebinding bds[] = {exchange};
    rebind_symbols(bds, 1);
}


//指回原方法
void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);

void hp_exchange(Method _Nonnull m1, Method _Nonnull m2) {
    //可以在這里進(jìn)行上報(bào)后端等操作
    NSLog(@"find  Hook");
}

@end

HookManager.h中導(dǎo)出頭文件:

#import <HookManager/AntiHookManager.h>

然后將AntiHookManager.h放入public Headers

image.png

修改主工程的ViewController.m如下:

#import <HookManager/HookManager.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    exchange_p(class_getInstanceMethod(self.class, @selector(btn2Click:)),class_getInstanceMethod(self.class, @selector(test)));
}

- (void)test {
    NSLog(@"self Hook Success");
}

- (IBAction)btn1Click:(id)sender {
    NSLog(@"click btn1");
}

- (IBAction)btn2Click:(id)sender {
    NSLog(@"click btn2");
}

@end

在工程中Hook自己的方法,這個時候運(yùn)行主工程:

AntiHookDemo[1432:149145] click btn1
AntiHookDemo[1432:149145] self Hook Success

btn2能夠被自己正常Hook怠硼。

1.3 創(chuàng)建注入工程 HookDemo

  1. 在根目錄創(chuàng)建APP文件夾以及Payload文件夾鬼贱,拷貝AntiHookDemo.appAPP/Payload目錄,壓縮zip -ry AntiHookDemo.ipa Payload/生成.ipa文件香璃。
  2. 拷貝appResign.sh重簽名腳本以及yololib注入工具到根目錄这难。
  3. 創(chuàng)建HPHook注入Framework

HPHook代碼如下:

#import "HPInject.h"
#import <objc/message.h>

@implementation HPInject

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(objc_getClass("ViewController"), @selector(btn1Click:)), class_getInstanceMethod(self, @selector(my_click)));
}

- (void)my_click {
    NSLog(@"inject Success");
}

@end

編譯運(yùn)行:

AntiHookDemo[1437:149999] find  Hook
AntiHookDemo[1437:149999] click btn1
AntiHookDemo[1437:149999] self Hook Success

首先是檢測到了Hook葡秒,其次自己內(nèi)部btn2 hook成功了姻乓,btn1 hook沒有注入成功。到這里暴露給自己用和防止別人Hook都已經(jīng)成功了眯牧。對于三方庫中正常使用到的Hook可以在防護(hù)代碼中做邏輯判斷可以加白名單等調(diào)用回原來的方法蹋岩。如果自己的庫在image list最后一個那么三方庫其實(shí)已經(jīng)Hook完了。

當(dāng)然只Hook method_exchangeImplementations不能完全防護(hù)学少,還需要Hook class_replaceMethod以及method_setImplementation剪个。

這種防護(hù)方式破解很容易,一般不這么處理:
1.在Hopper中可以找到method_exchangeImplementations版确,直接在MachO中修改這個字符串HookManager中就Hook不到了(這里會直接crash扣囊,因?yàn)?code>viewDidLoad中調(diào)用了exchange_p乎折,對于有保護(hù)邏輯的就可以繞過了,并且method_exchangeImplementations沒法做混淆)

image.png

2.可以很容易定位到防護(hù)代碼如暖,直接在防護(hù)代碼之前Hook笆檀,或者將fishhook中的一些系統(tǒng)函數(shù)Hook也能破解。本質(zhì)上是不執(zhí)行防護(hù)代碼盒至。

二酗洒、MonkeyDev

MonkeyDev是逆向開發(fā)中一個常用的工具 MonkeyDev。能夠幫助我們進(jìn)行重簽名和代碼注入枷遂。

2.1 安裝 MonkeyDev

theos安裝(Cydia Substrate就是 theos中的工具)

sudo git clone --recursive https://github.com/theos/theos.git /opt/theos

配置環(huán)境變量

#逆向相關(guān)配置
#export THEOS=/opt/theos

#寫入環(huán)境變量
#export PATH=$THEOS/bin:$PATH

運(yùn)行nic.pl查看theos信息樱衷。

image.png

[error] Cowardly refusing to make a project inside $THEOS (/opt/theos/)出現(xiàn)這個錯誤則是export配置有問題。

指定Xcode

sudo xcode-select -s /Applications/Xcode.app

安裝命令

sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-install)"

這里是安裝Xcode插件酒唉。安裝完成后重啟XcodeXcode中會出現(xiàn)MonkeyDev對應(yīng)的功能:

image.png

  • MonkeyApp:自動給第三方應(yīng)用集成Reveal矩桂、Cycript和注入dylib的模塊,支持調(diào)試dylib和第三方應(yīng)用痪伦,支持Pod給第三放應(yīng)用集成SDK侄榴,只需要準(zhǔn)備一個砸殼后的ipa或者app文件即可。
  • MonkeyPod:提供了創(chuàng)建Pod的項(xiàng)目网沾。
  • CaptainHook Tweak:使用CaptainHook提供的頭文件進(jìn)行OC函數(shù)的Hook以及屬性的獲取癞蚕。
  • Command-line Tool:可以直接創(chuàng)建運(yùn)行于越獄設(shè)備的命令行工具。
  • Logos Tweak:使用theos提供的logify.pl工具將.xm文件轉(zhuǎn)成.mm文件進(jìn)行編譯辉哥,集成了CydiaSubstrate桦山,可以使用MSHookMessageExMSHookFunctionHook OC函數(shù)和指定地址。

卸載命令

sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-uninstall)"

更新命令

sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-update)"

錯誤處理
1.MonkeyDev 安裝出現(xiàn):Types.xcspec not found
添加一個軟連接:

sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/PrivatePlugIns/IDEOSXSupportCore.ideplugin/Contents/Resources /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications

https://github.com/AloneMonkey/MonkeyDev/issues/266

2.2 重簽名

創(chuàng)建一個MonkeyDemo工程:

image.png

工程目錄如下:


image.png

在工程目錄下有一個TargetApp目錄醋旦,直接將微信8.0.2版本拖進(jìn)去:

image.png

編譯運(yùn)行工程:


image.png

這個時候就重簽名成功了恒水。相比用腳本自己跑方便很多,也能避免很多異常饲齐。

2.3 MonkeyDev 代碼注入

工程配置

MonkeyDemo注入一下AntiHookDemo钉凌,將AntiHookDemo編譯生成的App加入MonkeyDemoTargetApp中:

image.png

代碼注入

MonkeyDemo工程MonkeyDemoDylib->Logos目錄,.xm文件可以寫OC捂人、C++御雕、C

image.png

MonkeyDemoDylib.xmtype改為Objective-C++ Preprocessed Source

image.png

這里面的默認(rèn)代碼就是Logos語法:

image.png

.xm默認(rèn)打開方式修改為Xcode后重啟Xcode就能識別代碼了,否則就還是默認(rèn)文本文件先慷。將默認(rèn)的代碼刪除,寫Hook btn1Click的代碼:

#import <UIKit/UIKit.h>

//要hook的類
%hook ViewController

//要hook的方法
- (void)btn1Click:(id)sender {
    NSLog(@"Monkey Hook Success");
    //調(diào)用原來的方法
    %orig;
}

%end

直接運(yùn)行工程后點(diǎn)擊btn1

AntiHookDemo[9306:5972601] find  Hook
AntiHookDemo[9306:5972601] find  Hook
AntiHookDemo[9309:5973617] Monkey Hook Success
AntiHookDemo[9350:5987306] click btn1

image.png

這個時候就Hook成功了咨察,并且檢測到了Hook论熙。這里沒有防護(hù)住是因?yàn)?code>Monkey中用的是getImpsetImp
AntiHookManager做下改進(jìn):
AntiHookManager .h:

#import <Foundation/Foundation.h>
#import <objc/message.h>

//暴露給外界使用
CF_EXPORT void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);

CF_EXPORT IMP _Nonnull (*getImp_p)(Method _Nonnull m);

CF_EXPORT IMP _Nonnull(*setImp_p)(Method _Nonnull m, IMP _Nonnull imp);

@interface AntiHookManager : NSObject

@end

AntiHookManager .m:

#import "AntiHookManager.h"
#import "fishhook.h"

@implementation AntiHookManager

+ (void)load {
    //基本防護(hù)
    struct rebinding exchange;
    exchange.name = "method_exchangeImplementations";
    exchange.replacement = hp_exchange;
    exchange.replaced = (void *)&exchange_p;
    
    struct rebinding setIMP;
    setIMP.name = "method_setImplementation";
    setIMP.replacement = hp_setImp;
    setIMP.replaced = (void *)&setImp_p;
    
    
    struct rebinding getIMP;
    getIMP.name = "method_getImplementation";
    getIMP.replacement = hp_getImp;
    getIMP.replaced = (void *)&getImp_p;
        
    struct rebinding bds[] = {exchange,setIMP,getIMP};
    rebind_symbols(bds, 3);
}


//指回原方法
void (*exchange_p)(Method _Nonnull m1, Method _Nonnull m2);

IMP _Nonnull (*getImp_p)(Method _Nonnull m);

IMP _Nonnull(*setImp_p)(Method _Nonnull m, IMP _Nonnull imp);

void hp_exchange(Method _Nonnull m1, Method _Nonnull m2) {
    //可以在這里進(jìn)行上報(bào)后端等操作
    NSLog(@"find  Hook");
}

void (hp_getImp)(Method _Nonnull m) {
    NSLog(@"find  Hook getImp");
}

void (hp_setImp)(Method _Nonnull m, IMP _Nonnull imp) {
    NSLog(@"find  Hook setImp");
}

@end

這個時候控制臺輸出:

AntiHookDemo[1488:207119] find  Hook getImp
AntiHookDemo[1488:207119] find  Hook
AntiHookDemo[1488:207119] find  Hook getImp
AntiHookDemo[1488:207119] find  Hook
AntiHookDemo[1488:207119] click btn1

點(diǎn)擊btn1也沒有Hook到了摄狱。在這里運(yùn)行時有可能CrashJSEvaluateScript的時候脓诡,直接刪除App重新跑一次就可以了无午。
libsubstrate.dylib解析的,
其實(shí)這里.xm文件是被libsubstrate.dylib解析成MonkeyDemoDylib.mm中的內(nèi)容(.xm代碼是不參與編譯的):

image.png

MSHookMessageEx底層用的是setImpgetImpOC進(jìn)行Hook的祝谚。

錯誤問題
1.Signing for "MonkeyDemoDylib" requires a development team. Select a development team in the Signing & Capabilities editor.

直接在該targetbuild settings 中添加CODE_SIGNING_ALLOWED=NO

image.png

https://iosre.com/t/xcode11-monkeydev/17021

2.Failed to locate Logos Processor. Is Theos installed? If not, see https://github.com/theos/theos/wiki/Inst allation.
出現(xiàn)這個錯誤一般是theos沒有安裝好宪迟。或者路徑配置的有問題交惯。

3.library not found for -libstdc++
需要下載對應(yīng)的庫到XCode目錄中次泽。參考:https://github.com/longyoung/libstdc.6.0.9-if-help-you-give-a-star

4.The WatchKit app’s Info.plist must have a WKCompanionAppBundleIdentifier key set to the bundle identifier of the companion app.
刪除DerivedData重新運(yùn)行。

5.This application or a bundle it contains has the same bundle identifier as this application or another bundle that it contains. Bundle identifiers must be unique.
這種情況大概率是手機(jī)上之前安裝過相同bundleIdApp安裝不同版本導(dǎo)致席爽,需要刪除重新安裝意荤。還有問題的話刪除DerivedDatabundleId

6.This app contains a WatchKit app with one or more Siri Intents app extensions that declare IntentsSupported that are not declared in any of the companion app's Siri Intents app extensions. WatchKit Siri Intents extensions' IntentsSupported values must be a subset of the companion app's Siri Intents extensions' IntentsSupported values.
需要刪除com.apple.WatchPlaceholder(在/opt/MonkeyDev/Tools目錄中修改pack.sh):

rm -rf "${TARGET_APP_PATH}/com.apple.WatchPlaceholder" || true
image.png

然后刪除DerivedData重新運(yùn)行只锻。

  1. LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
    這個說明App內(nèi)部做了反調(diào)試防護(hù)玖像。直接在Monkey中開啟sysctl
rebind_symbols((struct rebinding[1]){{"sysctl", my_sysctl, (void*)&orig_sysctl}},1);
image.png

8.Attempted to load Reveal Library twice. Are you trying to load dynamic library with Reveal Framework already linked?
直接刪除dylibOther Linker Flags的設(shè)置即可(可能的原因是手機(jī)端已經(jīng)導(dǎo)入了這個庫):

image.png

??遇見莫名其妙的錯誤建議刪除DerivedData重啟Xcode重新運(yùn)行。

總結(jié)

  • Hook
    • 使用fishhook Hook method_exchangeImplementations齐饮、class_replaceMethod捐寥、method_setImplementation
    • 需要在動態(tài)庫中添加防護(hù)代碼。
    • 本地導(dǎo)出原函數(shù)IMP供自己項(xiàng)目使用祖驱,配合白名單握恳。
    • 這種防護(hù)很容易破解,一般不推薦這么使用羹膳。
  • MonkeyDev:逆向開發(fā)中一個常用的工具睡互。
    • 重簽名:很容易,直接拖進(jìn)去.ipa或者.app運(yùn)行工程就可以了陵像。
    • 代碼注入:Logos主要是編寫.xm文件就珠。底層依然是getImpsetImp的調(diào)用。

Demo
Lohos語法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醒颖,一起剝皮案震驚了整個濱河市妻怎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泞歉,老刑警劉巖逼侦,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腰耙,居然都是意外死亡榛丢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進(jìn)店門挺庞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晰赞,“玉大人,你說我怎么就攤上這事∫从悖” “怎么了然走?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長戏挡。 經(jīng)常有香客問我芍瑞,道長,這世上最難降的妖魔是什么褐墅? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任拆檬,我火速辦了婚禮,結(jié)果婚禮上掌栅,老公的妹妹穿的比我還像新娘秩仆。我一直安慰自己,他們只是感情好猾封,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布澄耍。 她就那樣靜靜地躺著,像睡著了一般晌缘。 火紅的嫁衣襯著肌膚如雪齐莲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天磷箕,我揣著相機(jī)與錄音选酗,去河邊找鬼。 笑死岳枷,一個胖子當(dāng)著我的面吹牛芒填,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播空繁,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼殿衰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盛泡?” 一聲冷哼從身側(cè)響起闷祥,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎傲诵,沒想到半個月后凯砍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拴竹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年悟衩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栓拜。...
    茶點(diǎn)故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡座泳,死狀恐怖斑响,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钳榨,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布纽门,位于F島的核電站薛耻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赏陵。R本人自食惡果不足惜饼齿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝙搔。 院中可真熱鬧缕溉,春花似錦、人聲如沸吃型。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勤晚。三九已至枉层,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赐写,已是汗流浹背鸟蜡。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挺邀,地道東北人揉忘。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像端铛,于是被迫代替她去往敵國和親泣矛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評論 2 348

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