
當(dāng)我們要逆向第三方應(yīng)用時,首先就是要將應(yīng)用安裝在我們的手機上,然后進行hook分析,找到對應(yīng)的方法調(diào)用,進行代碼注入,破解其正常流程,從而達到逆向目的。接下來將詳細講解分析該過程具體實現(xiàn)。
一、shell腳本實現(xiàn)重簽名
1. 我們以最常見的應(yīng)用微信為例,其他應(yīng)用原理一樣!首先我們?nèi)P助手下載越獄版本的微信應(yīng)用,如下圖:

-
1.1 越獄版本的應(yīng)用是沒有加密的,正式版本的應(yīng)用是加過密的,我們用MachOView來查看應(yīng)用的可執(zhí)行文件信息,演示如下:
02 - 1.2 從上圖中我們可以看到LC_ENCRYPTION_INFO_64加密信息這一欄中的Crypt ID為0,代表沒有加密,而微信的正式版本此處為1,代表用到了某一種加密方式,加密的我們是很難去進行代碼注入的。
2.我們先來看一下重簽微信app的效果,演示如下:

2.1 接下來我們將詳細講解重簽過程,這里的重簽可以手動也可以使用腳本,手動比較繁瑣,這里就不演示了。下面我們基于shell腳本來完成代碼的重新簽名,總計不超過20條命令,在進行shell腳本講解之前,如果你不熟悉shell腳本,請先花點時間看下入門教程。
-
2.2 我們新建立一個WeChat的同名工程,方便后續(xù)文件的替換,其他應(yīng)用類似。然后在工程目錄下新建一個APP文件,這里用于放置我們剛下載的ipa包,演示如下:04
-
2.3 我們?yōu)楣こ虅?chuàng)建一個腳本文件,然后添加證書管理,接下來運行即可,三步就解決了重簽名問題,演示如下:
05 2.4 關(guān)鍵就在于shell腳本的實現(xiàn)過程,這里給出shell簽名腳本,腳本中每一行都做了詳細注釋,完整腳本地址。
#獲取手動創(chuàng)建的APP文件夾,用來放置越獄版本的Ipa包,${SRCROOT} 代表工程文件所在的目錄
crackPath="${SRCROOT}/APP"
#獲取越獄版本Ipa路徑
oldIpaPath="${crackPath}/*.ipa"
# 創(chuàng)建一個臨時文件夾,用來放置解壓的Ipa文件
tempPath="${SRCROOT}/Temp"
#首先先清空Temp文件夾
rm -rf "$tempPath"
#創(chuàng)建臨時文件夾目錄
mkdir -p "$tempPath"
# 1. 解壓IPA到temp下
unzip -oqq "$oldIpaPath" -d "$tempPath"
# 拿到解壓的臨時的APP的路徑
oldIPaPath=$(set -- "$tempPath/Payload/"*.app;echo "$1")
# 2. 將解壓出來的.app拷貝進入工程下
# BUILT_PRODUCTS_DIR 工程生成的APP包的路徑(系統(tǒng)創(chuàng)建的)
# TARGET_NAME target名稱(系統(tǒng)創(chuàng)建的)
targetAppPath="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
# 打印app編譯后的路徑
echo "app路徑:$targetAppPath"
#先刪除app所在路徑文件
rm -rf "$targetAppPath"
#重新創(chuàng)建該文件路徑
mkdir -p "$targetAppPath"
#將解壓的app文件拷貝到Xcode編譯的app文件目錄,讓Xcode認(rèn)為這是它編譯出來的,Xcode就會幫我們完成簽名工作
cp -rf "$oldIPaPath/" "$targetAppPath"
# 3. 刪除extension和WatchAPP.個人證書沒法簽名Extention
rm -rf "$targetAppPath/PlugIns"
rm -rf "$targetAppPath/Watch"
# 4. 更新info.plist文件 CFBundleIdentifier,PlistBuddy是更改plist文件的可執(zhí)行文件
# 設(shè)置:"Set : KEY Value" "目標(biāo)文件路徑"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$targetAppPath/Info.plist"
# 5. 重簽名第三方 FrameWorks
tagetAppFramworkPath="$targetAppPath/Frameworks"
if [ -d "$tagetAppFramworkPath" ];
then
for frameWork in "$tagetAppFramworkPath/"*
do
#簽名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$frameWork"
done
fi
二、framework代碼注入
1. 首先我們在代碼簽名的工程的基礎(chǔ)上,創(chuàng)建一個framework庫,并添加一個load方法,里面寫入我們需要注入的代碼,演示如下:

- 1.1 然后我們在腳本后面增加注入代碼
# 拿到MachO文件的路徑
APP_BINARY=`plutil -convert xml1 -o - $targetAppPath/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#注入
yololib "$targetAppPath/$APP_BINARY" "Frameworks/Inject.framework/Inject"
-
1.2 運行工程,可以看到我們注入的代碼成功了,演示如下:
07 1.3 上面工程有306個報錯,這個是我電腦權(quán)限的問題,可以忽略,你的電腦運行應(yīng)該不會有問題。我們可以看到代碼已經(jīng)注入成功,至于為什么是在load方法中添加,詳細了解請查看我的另一篇文章《dyld加載應(yīng)用啟動原理詳解》,里面有分析代碼的注入時機!
-
1.4 接下來我們來分析yololib這句腳本到底干了什么?首先我們將自己創(chuàng)建的framework可執(zhí)行文件和wechat的可執(zhí)行文件拿出來,然后執(zhí)行yololib命令演示如下圖:
08 -
1.5 yololib下載地址。使用yololib將自己的framework注入到WeChat可執(zhí)行文件中,演示如下圖:
09 -
1.6 接著用machOView來查看WeChat可執(zhí)行文件中是否存在自己創(chuàng)建的庫問題,如下圖:
10
2. 截獲微信注冊方法
-
2.1 我們使用調(diào)試工具查看注冊按鈕的調(diào)用方法,演示如下圖:
11 2.2 我們可以看到調(diào)用的Target是"WCAccountLoginControlLogic",點擊注冊按鈕執(zhí)行的方法為"onFirstViewRegester",有了這個,接下來就是簡單的方法交換了。
2.3 我們在自己的framwork中寫入方法交換方法,如下:
+(void)load
{
Method oldMethod = class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), @selector(onFirstViewRegester));
Method newMethod = class_getInstanceMethod(self, @selector(test));
method_exchangeImplementations(oldMethod, newMethod);
}
-(void)test{
NSLog(@"----截獲到微信注冊按鈕點擊------");
}
-
2.4 接下來我們運行程序,點擊按鈕,演示如下:
12
到此,shell腳本的自動簽名和framework代碼注入到此完成,還有一種dylib的注入,是用macOS的庫來完成的,相對來說這個比較簡單,如果有需要我會更新dylib的相關(guān)文章,主要熟悉掌握framwork的注入即可。附上腳本下載,幫助到你請給一個Star。
我是Qinz,希望我的文章對你有幫助。








