iOS逆向?qū)崙?zhàn)--022:InlineHook

所謂InlineHook(內(nèi)聯(lián)鉤?),就是直接修改?標(biāo)函數(shù)的頭部代碼铝耻。讓它跳轉(zhuǎn)到?定義函數(shù)中執(zhí)?代碼誊爹,從?達(dá)到Hook的?的。這種Hook技術(shù)?般用于靜態(tài)語?

Dobby框架

Dobby是一個(gè)全平臺(tái)的InlineHook框架瓢捉,詳情可查看 官方文檔

編譯Dobby

將代碼clone下來

git clone https://github.com/jmpews/Dobby.git --depth=1

由于Dobby是跨平臺(tái)框架频丘,所以項(xiàng)?并不是?個(gè)Xcode?程,需要使?cmake將?程編譯成為Xcode?程

進(jìn)?Dobby?錄泡态,創(chuàng)建?個(gè)?件夾椎镣,然后cmake編譯?程

cd Dobby && mkdir build_for_ios_arm64 && cd build_for_ios_arm64
cmake .. -G Xcode \
-DCMAKE_TOOLCHAIN_FILE=cmake/ios.toolchain.cmake \
-DPLATFORM=OS64 -DARCHS="arm64" -DCMAKE_SYSTEM_PROCESSOR=arm64 \
-DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=1 -DDEPLOYMENT_TARGET=9.3 \
-DDynamicBinaryInstrument=ON -DNearBranch=ON -DPlugin.SymbolResolver=ON -DPlugin.Darwin.HideLibrary=ON -DPlugin.Darwin.ObjectiveC=ON

編譯完成后,會(huì)?成?個(gè)Xcode?程

編譯Xcode?程兽赁,?成Framework

導(dǎo)?DobbyX.framework到?程状答,如果遇到Bitcode問題,兩種解決方式

  • 關(guān)閉當(dāng)前?程的Bitcode
  • 編譯DobbyX.framework時(shí)刀崖,開啟Bitcode

DobbyX.framework拷?問題

Framework庫?次拖??程惊科,Xcode不會(huì)?動(dòng)幫你拷?。運(yùn)?時(shí)會(huì)發(fā)現(xiàn)Framework沒有打包進(jìn)?App包亮钦,造成DYLD加載時(shí)找不到庫的錯(cuò)誤

來到Xcode中的Build Phases馆截,點(diǎn)擊+,選擇New Copy Files Phase

Copy Files中,將Destination選擇Frameworks

點(diǎn)擊+蜡娶,選擇DobbyX.framework混卵,點(diǎn)擊Add

Dobby的核心的函數(shù)

int DobbyHook(void *address, void *replace_call, void **origin_call);
  • address:需要HOOK的函數(shù)地址
  • replace_call:新函數(shù)地址
  • origin_call:保留原始函數(shù)的指針的地址

案例1

Dobby的使用

搭建InlineDemo項(xiàng)目,拖入DobbyX.framework窖张,解決拷?問題

打開ViewController.m文件幕随,寫入以下代碼:

定義將要被HOOK的靜態(tài)函數(shù)

int sum(int a,int b){
   return a + b;
}

定義函數(shù)指針,?于保存被替換函數(shù)的地址

static int (*sum_p)(int a,int b);

定義新函數(shù)宿接,?此函數(shù)替換將要HOOK的函數(shù)赘淮,該函數(shù)的返回值及參數(shù)必須?致

int mySum(int a,int b) {
   NSLog(@"Sum:%d,??????????",sum_p(a,b));
   return a - b;
}

viewDidLoad方法中睦霎,調(diào)用DobbyHook進(jìn)行函數(shù)的Hook

- (void)viewDidLoad {
   [super viewDidLoad];

   DobbyHook((void *)sum, mySum, (void *)&sum_p);    
}

touchesBegan中梢卸,調(diào)用sum函數(shù)

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   NSLog(@"Sum:%d",sum(10, 20));
}

真機(jī)運(yùn)行項(xiàng)目,點(diǎn)擊屏幕副女,輸入以下內(nèi)容:

InlineDemo[9140:1691629] Sum:30蛤高,??????????
InlineDemo[9140:1691629] Sum:-10

sum函數(shù)HOOK成功,先輸出原始函數(shù)的執(zhí)行結(jié)果碑幅,再輸出替換函數(shù)的執(zhí)行結(jié)果

HOOK原理

案例1:

通過匯編代碼襟齿,查看HOOK原理

上述案例中,在touchesBegan方法上設(shè)置斷點(diǎn)

真機(jī)運(yùn)行項(xiàng)目枕赵,點(diǎn)擊屏幕,進(jìn)入touchesBegan方法

單步調(diào)試位隶,向下執(zhí)行1步拷窜。進(jìn)入sum函數(shù)

  • 前三句代碼被替換
  • 拉伸棧空間的代碼沒有了

單步調(diào)試涧黄,向下執(zhí)行3步篮昧。通過br x17指令,跳轉(zhuǎn)到mySum函數(shù)

進(jìn)入mySum函數(shù)笋妥,通過blr x8指令懊昨,跳轉(zhuǎn)到指定地址上執(zhí)行代碼

該代碼中,通過br x17指令春宣,回到sum函數(shù)

  • 這里出現(xiàn)了拉伸椊桶洌空間的代碼

進(jìn)入sum函數(shù),執(zhí)行原始代碼邏輯

  • sum函數(shù)的結(jié)尾月帝,恢復(fù)棧平衡

當(dāng)sum函數(shù)執(zhí)行ret指令躏惋,返回mySum函數(shù),執(zhí)行后續(xù)代碼

靜態(tài)函數(shù)的HOOK嚷辅,并沒有在原始函數(shù)中增加代碼簿姨,而是將拉伸棧空間的三句代碼進(jìn)行了替換

當(dāng)調(diào)用原始函數(shù),才會(huì)拉伸棧平衡扁位。然后在原始函數(shù)的代碼中准潭,恢復(fù)棧平衡

案例2:

mySum函數(shù)中,不調(diào)用原始函數(shù)

mySum函數(shù)中域仇,注釋原始函數(shù)的調(diào)用

真機(jī)運(yùn)行項(xiàng)目刑然,進(jìn)入sum函數(shù)。代碼并沒有發(fā)生變化

進(jìn)入mySum函數(shù)殉簸,跳轉(zhuǎn)到指定地址的代碼沒有了

當(dāng)mySum函數(shù)執(zhí)行ret指令闰集,直接返回到touchesBegan

此時(shí)sum函數(shù)的原始代碼都不會(huì)被執(zhí)行

這種情況,不會(huì)拉伸棸惚埃空間武鲁,sum函數(shù)的原始代碼不會(huì)被執(zhí)行,所以也不會(huì)恢復(fù)棧平衡

HOOK函數(shù)地址

在逆向開發(fā)中蝠检,三方應(yīng)用會(huì)剝離符號(hào)表沐鼠,我們無法獲得符號(hào)名稱,所以HOOK的一定是地址

應(yīng)用每次啟動(dòng)時(shí)叹谁,ASLR偏移地址都不一樣饲梭,所以不能直接HOOK地址

正確的做法:先找到函數(shù)在MachO中的偏移地址,加上PAGEZERO0x100000000焰檩,再加上本次啟動(dòng)的ASLR偏移地址

案例1

延用上述案例憔涉,找到sum函數(shù)的實(shí)現(xiàn)地址

查看匯編代碼,找到sum函數(shù)的調(diào)用

  • 函數(shù)實(shí)現(xiàn)地址:0x1022edd48

使用image list函數(shù)析苫,找到主程序的基地址

  • 基地址:0x1022e8000

使用函數(shù)實(shí)現(xiàn)地址 - 主程序基地址兜叨,計(jì)算函數(shù)在MachO中的偏移地址

e -f x -- 0x1022edd48-0x1022e8000
-------------------------
$1 = 0x5d48
  • 偏移地址:0x5d48

MachO文件中,查看偏移地址

  • 對(duì)應(yīng)的正是sum函數(shù)的匯編代碼
  • 和斷點(diǎn)時(shí)看到的匯編代碼有些區(qū)別衩侥,因?yàn)?code>Dobby在運(yùn)行時(shí)国旷,Hook函數(shù)會(huì)替換匯編代碼

案例2:

對(duì)函數(shù)地址進(jìn)行HOOK

打開ViewController.m文件,寫入以下代碼:

#import "ViewController.h"
#import <DobbyX/dobby.h>
#import <mach-o/dyld.h>

@implementation ViewController

int sum(int a,int b){
   return a + b;
}

static uintptr_t sumP = 0x5d48 + 0x100000000;

- (void)viewDidLoad {
   [super viewDidLoad];
   
   sumP += _dyld_get_image_vmaddr_slide(0);
   DobbyHook((void *)sumP, mySum, (void *)&sum_p);
}

static int (*sum_p)(int a,int b);

int mySum(int a,int b) {
   NSLog(@"Sum:%d茫死,??????????",sum_p(a,b));
   return a - b;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   NSLog(@"Sum:%d",sum(10, 20));
}

@end

這里有一個(gè)小問題跪但,因?yàn)榘咐窃谧约旱捻?xiàng)目中HOOK地址,所以對(duì)項(xiàng)目的代碼進(jìn)行了修改峦萎,這樣會(huì)造成sum函數(shù)的實(shí)現(xiàn)地址發(fā)生改變

  • sum函數(shù)的偏移地址屡久,從之前的0x5d48變?yōu)?code>0x5d08

打開ViewController.m文件,修改代碼:

static uintptr_t sumP = 0x5d08 + 0x100000000;

真機(jī)運(yùn)行項(xiàng)目爱榔,點(diǎn)擊屏幕涂身,HOOK成功

InlineDemo[9883:1880364] Sum:30,??????????
InlineDemo[9883:1880364] Sum:-10

在代碼不修改的情況下搓蚪,地址不會(huì)改變蛤售。所以在逆向開發(fā)中,分析第三方應(yīng)用,不會(huì)出現(xiàn)這種問題

Dobby注入應(yīng)用

案例1:

搭建被HOOK的應(yīng)用

創(chuàng)建FuncDemo項(xiàng)目

打開ViewController.m文件悴能,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

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

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
   NSLog(@"Sum:%d",sum(10,15));
}

int sum(int a,int b){
   return  a + b;
}

@end

真機(jī)運(yùn)行項(xiàng)目揣钦,使用函數(shù)實(shí)現(xiàn)地址 - 主程序基地址,計(jì)算出sum函數(shù)在MachO中的偏移地址:0x5F04

為了HOOK的場景更加真實(shí)漠酿,剝離除了間接符號(hào)之外的全部符號(hào)

剝離符號(hào)后冯凹,驗(yàn)證sum函數(shù)的實(shí)現(xiàn)地址是否改變

真機(jī)運(yùn)行項(xiàng)目,使用image list獲得主程序基地址

通過暫停炒嘲,進(jìn)入lldb宇姚。通過主程序基地址 + 0x5F04,得到sum函數(shù)地址

對(duì)地址設(shè)置斷點(diǎn)夫凸,成功找到函數(shù)浑劳,說明sum函數(shù)的實(shí)現(xiàn)地址沒有改變

案例2:

修改重簽名腳本,改為支持.app格式

定義變量

# 工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
# 資源文件夾夭拌,我們提前在工程目錄下新建一個(gè)APP文件夾魔熏,里面放ipa包
ASSETS_PATH="${SRCROOT}/APP"
# 拿到臨時(shí)的APP的路徑
TEMP_APP_PATH=$(set -- "${ASSETS_PATH}/"*.app;echo "$1")

.app拷貝進(jìn)入工程

TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"

rm -rf $TARGET_APP_PATH
mkdir -p $TARGET_APP_PATH
cp -rf $TEMP_APP_PATH/ $TARGET_APP_PATH

刪除ExtentionWatch

rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"

更新info.plist文件中的CFBundleIdentifier

/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"

拿到MachO文件的路徑,給MachO文件上執(zhí)行權(quán)限

APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`

chmod +x "$TARGET_APP_PATH/$APP_BINARY"

重簽名第三方Frameworks

TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do

簽名

/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi

注入

./yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/Hook.framework/Hook"

案例3:

對(duì)FuncDemo.app進(jìn)行HOOK

搭建HookDemo項(xiàng)目

yololib鸽扁、appSign.sh蒜绽、DobbyX.framework,拷貝到項(xiàng)目根目錄

在項(xiàng)目根目錄桶现,創(chuàng)建App目錄

FuncDemo.app拷貝至App目錄

創(chuàng)建target躲雅,添加注入的動(dòng)態(tài)庫,命名HOOK

HOOK動(dòng)態(tài)庫中骡和,創(chuàng)建Inject

HookDemo主項(xiàng)目中相赁,拖入DobbyX.framework,勾選HookDemoHOOK

HookDemo中即横,找到Embed Framewords,添加DobbyX.framework

打開Inject.m文件裆赵,寫入以下代碼:

#import "Inject.h"
#import <DobbyX/dobby.h>
#import <mach-o/dyld.h>

@implementation Inject

static uintptr_t sumP = 0x5F04 + 0x100000000;

+(void)load{
   sumP += _dyld_get_image_vmaddr_slide(0);
   DobbyHook((void *)sumP, mySum, (void *)&sum_p);
}

static int (*sum_p)(int a,int b);

int mySum(int a,int b) {
   NSLog(@"Sum:%d东囚,??????????",sum_p(a,b));
   return a - b;
}

@end

真機(jī)運(yùn)行項(xiàng)目,點(diǎn)擊屏幕战授,HOOK成功

FuncDemo[11452:2162229] Sum:25页藻,??????????
FuncDemo[11452:2162229] Sum:-5
總結(jié)

Dobby

  • Dobby原理:運(yùn)行時(shí)對(duì)目標(biāo)函數(shù)的匯編代碼替換,修改的是內(nèi)存中MachO的代碼段
  • Dobby替換匯編代碼時(shí)植兰,對(duì)原始函數(shù)的調(diào)用份帐,會(huì)影響棧的拉伸和平衡
  • 在真實(shí)HOOK場景中,我們拿不到符號(hào)名稱楣导,只能對(duì)地址進(jìn)行HOOK
  • HOOK地址時(shí)废境,需要加上PAGEZEROASLR
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子噩凹,更是在濱河造成了極大的恐慌巴元,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驮宴,死亡現(xiàn)場離奇詭異逮刨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堵泽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門修己,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迎罗,你說我怎么就攤上這事睬愤。” “怎么了佳谦?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵戴涝,是天一觀的道長。 經(jīng)常有香客問我钻蔑,道長啥刻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任咪笑,我火速辦了婚禮可帽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘窗怒。我一直安慰自己映跟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布扬虚。 她就那樣靜靜地躺著努隙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辜昵。 梳的紋絲不亂的頭發(fā)上荸镊,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音堪置,去河邊找鬼躬存。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舀锨,可吹牛的內(nèi)容都是我干的岭洲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坎匿,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼盾剩!你這毒婦竟也來了雷激?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤彪腔,失蹤者是張志新(化名)和其女友劉穎侥锦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體德挣,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恭垦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了格嗅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片番挺。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖屯掖,靈堂內(nèi)的尸體忽然破棺而出玄柏,到底是詐尸還是另有隱情,我是刑警寧澤贴铜,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布粪摘,位于F島的核電站,受9級(jí)特大地震影響绍坝,放射性物質(zhì)發(fā)生泄漏徘意。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一轩褐、第九天 我趴在偏房一處隱蔽的房頂上張望椎咧。 院中可真熱鬧,春花似錦把介、人聲如沸勤讽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脚牍。三九已至,卻和暖如春巢墅,著一層夾襖步出監(jiān)牢的瞬間诸狭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工砂缩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留作谚,地道東北人三娩。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓庵芭,卻偏偏與公主長得像敬肚,于是被迫代替她去往敵國和親他爸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甫匹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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