iOS逆向之從砸殼到重簽名
一、概述
筆者做了多年的業務開發,以前對逆向知之甚少,好像我們做iOS的開發者對應用本身的安全問題總不是那么上心,總以為Apple自身的加密簽名機制足夠安全了,我們除了關心業務網絡安全,對自身App包的安全重視度總是不夠。然而一旦我們的包被有心人破解,那么無論是對自身業務還是用戶數據都是致命的。真正開始研究逆向,才發現我們App是如此的不堪一擊。所以研究逆向其實是研究Hacker
是如何攻破我們的應用,從而更好地保護自身應用安全。
研究逆向,首當其沖的就是重簽名,重簽名就是用自己的證書簽名別人的應用,從而進行分發。重簽名說白了就是套殼別人的應用,挺火的微信雙開,其實就是對微信進行了重簽名。而重簽名首先要做的就是對應用砸殼。
二、手機越獄與應用砸殼
我們從App store 下載的應用是經過蘋果加密簽名過的,是無法進行重簽名的。所以重簽名首先要做的就是對應用進行砸殼,而砸殼需要你有一臺越獄手機。
1. 手機越獄
目前主流的越獄平臺有PP助手、愛思助手做到比較好,提供一鍵越獄功能。我自己使用的愛思助手,下載愛思助手電腦版,選擇【工具箱】-【一鍵越獄】,此時會匹配你當前手機版本的越獄工具,選擇工具進行越獄。
我使用的是 iphone SE,系統版本是14.4,按照提示完成越獄就OK了。
需要注意,這種越獄方式是不完美的越獄,當你重啟手機后會重新變回非越獄狀態,需要重新走一遍越獄流程。不過對于我們研究逆向足夠了。
還沒完,越獄完成后需要安裝一個插件:Apple File Conduit"2"
,安裝這個插件的目的是,讓我們的電腦端能訪問設備的根文件目錄,安裝方式也很簡單,可以參考這篇文章Apple File Conduit"2"安裝,這里不再贅述。當我們安裝完成后,愛思助手連接手機,可以看到在【文件管理】中多了個欄目【文件系統(越獄)】,這就是越獄狀態下的系統根目錄。
2. ipa應用砸殼
首先了解什么是應用砸殼:我們提交到App Store發布的App都是經過Apple加密的,這樣可以確保安裝到我們手機的應用都是蘋果審核授權的,當然通過企業級證書或者開發者證書生成的App是不需要砸殼的。對于App Store加密的應用,我們無法通過Hopper等反編譯靜態分析,也無法class-dump,在逆向分析過程中,需要對加密的二進制文件進行解密才可以進行靜態分析,這一過程就是大家熟知的砸殼。
砸殼主要有兩種方式:
- 靜態砸殼
靜態砸殼就是在已經掌握和了解到了殼應用的加密算法和邏輯后,在不運行殼應用程序的前提下將殼應用程序進行解密處理。靜態脫殼的方法難度大,而且加密方發現應用被破解后,就可能會改用更加高級和復雜的加密技術。 - 動態砸殼
動態砸殼就是從運行在進程內存空間中的可執行程序映像(image)入手,來將內存中的內容進行轉儲(dump)處理來實現脫殼處理。這種方法實現起來相對簡單,且不必關心使用的是何種加密技術。所以目前市面上的砸殼工具都是基于動態砸殼進行的。動態砸殼有多種工具:Clutch
、dumpdecrypted
、CrackerXI App
,前兩種對系統要求較嚴格,而且年久失修很容易砸殼失敗,我們直接介紹最方便的第三種方式:利用CrackerXI App
進行砸殼。
(1) 在Cydia
中下載CrackerXI App
Cydia
類似于越獄前的App Store,越獄后我們所有的軟件都是通過Cydia
來進行安裝。打開Cydia
后,選擇【軟件源】-右上角【編輯】-點擊【添加】,輸入http://apt.wxhbts.com/
,【添加源】等待添加完成。添加軟件源完成后,搜索CrackerXI App
,點擊安裝完成后【重啟springboard】,回到桌面,可以看到桌面上安裝完成了CrackerXI+
App.
(2) 砸殼
提前在App Store 下載好你要砸殼的App,打開CrackerXI+
,選擇【AppList】然后點擊你要砸殼的應用,在彈框中選擇【YES,Full IPA】,此時會打開我們要砸殼的應用進行砸殼,完成后會看到一個砸殼后的文件地址/var/mobile/Documents/CrackerXI/*****.ipa
,這個文件就是我們砸殼后的ipa包。
這個路徑怎么查找相信聰明的你已經知道了,去愛思助手-【文件管理】-【文件系統(越獄)】查找到這個ipa,導出到桌面目錄就完成了。
(3) 驗證
完成上面的操作后,我們需要驗證一下拿到的ipa是否是被砸殼的。把.ipa
包擴展名改為.zip
,解壓后得到Payload
文件夾,右鍵【顯示包內容】- 找到可執行文件.
終端輸入
otool -l 值執行文件名 | grep crypt
可以看到cryptid
的值為0,說明砸殼成功。
三、重新簽名
Apple 應用的分發一般有一下幾種方式:
- 最常用的是從App store下載應用。這種下發方式不受設備數的限制,只要上線App store 的應用,都會被Apple進行簽名加密.
- 第二種方式是申請企業賬號,把我們的應用通過企業賬號進行簽名,從而繞過App store惱人的審核機制,達到分發應用的目的。這種方法分發數目也不受限制.
- 第三種是通過
TestFlight
進行測試版本的分發,他分為內部測試人員與外部測試人員。通過分發外部測試人員,最多能給1萬名用戶進行分發安裝. - 第四種開發人員通過添加設備ID安裝應用,最多可以注冊100臺設備.
不同的開發者賬號對應著App不同的分發方式,我們申請完成開發者賬號后,創建應用Id,然后創建其對應證書,描述文件等一系列動作,實際已經決定了它的分發方式了??梢赃@樣理解:每一個應用Id后面對應一套證書,這套證書決定了你應用的分發方式。重簽名就是為當前的應用換一套應用Id與證書,從而達到分發應用的目的?,F實的需求是,如果你上線App Store的應用,想通過企業賬號的形式進行分發,而你又沒有源碼,或是想探究一下應用雙開,那么重簽名就派上用場了。我們介紹兩種重簽名的方式:
1.Xcode 重簽名
(1) 新建同名的工程文件
注意這里的同名并不是Bundle Identifier 相同,而是跟你砸殼解壓ipa文件,Payload里面的包相同的名稱
還需要注意,如果你重簽名的工程中是通過AppDelegate
來監聽App的生命周期的話,那么需要在新版的Xcode中移除SceneDelegate
這個類,重新使用AppDelegate
來監聽App的生命周期。重新配置完成工程后,真機運行,把描述文件安裝到手機里。
(2) 替換編譯的App包
找到我們砸殼過的Payload文件夾中包,對我們編譯的包進行替換
(3) 對二進制文件中的FrameWork進行重簽名
其實在這一步之前還需要對包內的
PlugIns
插件以及Watch
相關組件進行刪除,我們逆向包里面沒有這些組件,所以省略了。
進入Framework 文件夾,利用CodeSign
對Framework進行證書簽名,注意要對所有FrameWork進行重簽名。
codesign -fs "復制的你自己的證書名字" 要重簽的FrameWork名稱
證書的名字就是你真機測試的證書的名稱,如果不知道可以去鑰匙串中查看
iPhone Developer: *** ** (********)
就是證書名稱
(4) 重簽名后運行
這樣我們就在沒有源碼的情況下,完成了對應用的重簽名。
2. 使用腳本文件重簽名
利用shell
腳本進行重簽名的原理,跟上面的簽名原理相同,只不過把重簽步驟給腳本化了。
(1) 創建空工程(工程名隨便),并且進行真機運行
(2) 在工程根目錄下創建APP文件夾,在文件中放入我們砸殼后的ipa包
(3) 在工程中添加腳本
在工程Build Phases
中新建腳本文件
在Run Script
中添加腳本
# Type a script or drag a script file from your workspace to insert its path.
# Type a script or drag a script file from your workspace to insert its path.
# ${SRCROOT} 為工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾,放三方APP的
ASSETS_PATH="${SRCROOT}/APP"
#ipa包路徑
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
#新建Temp文件夾
rm -rf "$TEMP_PATH"
mkdir -p "$TEMP_PATH"
# --------------------------------------
# 1. 解壓IPA 到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解壓的臨時APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# 這里顯示打印一下 TEMP_APP_PATH變量
echo "TEMP_APP_PATH: $TEMP_APP_PATH"
# -------------------------------------
# 2. 把解壓出來的.app拷貝進去
#BUILT_PRODUCTS_DIR 工程生成的APP包路徑
#TARGET_NAME target名稱
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "TARGET_APP_PATH: $TARGET_APP_PATH"
rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH/"
# -------------------------------------
# 3. 為了是重簽過程簡化,移走extension和watchAPP. 此外個人免費的證書沒辦法簽extension
echo "Removing AppExtensions"
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"
# -------------------------------------
# 4. 更新 Info.plist 里的BundleId
# 設置 "Set :KEY Value" "目標文件路徑.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
# 5.給可執行文件上權限
#添加ipa二進制的執行權限,否則xcode會告知無法運行
#這個操作是要找到第三方app包里的可執行文件名稱,因為info.plist的 'Executable file' key對應的是可執行文件的名稱
#我們grep 一下,然后取最后一行, 然后以cut 命令分割,取出想要的關鍵信息。存到APP_BINARY變量里
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#這個為二進制文件加上可執行權限 +X
chmod +x "$TARGET_APP_PATH/$APP_BINARY"
# -------------------------------------
# 6. 重簽第三方app Frameworks下已存在的動態庫
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
#遍歷出所有動態庫的路徑
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
echo "FRAMEWORK : $FRAMEWORK"
#簽名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi
運行后完成對其重簽名.
四、總結
對應用的砸殼和重簽名僅僅是逆向的入門,后面我們會繼續探討關于逆向的其他技術。再次聲明:研究逆向的目的是為了更好的保護我們的應用,而不是用在非法用途上。
參考文獻:
http://blog.cnbang.net/tech/3386/
https://www.i4.cn/news_3.html