轉(zhuǎn)載:原文地址
本文將從原理分析,到利用原理的漏洞,再到具體過程,最后利用腳本全自動(dòng)實(shí)現(xiàn)。
作為一名iOS開發(fā)者肯定知道iOS開發(fā)證書,那么證書具體是什么呢?為什么到我們本地的不是證書本身,而是一個(gè)稱之為描述文件的東西。而這「描述文件」又具體是什么呢?
在知道這「描述文件」后,我們是不是可以通過將「描述文件」替換為我們自己的「描述文件」進(jìn)行一些有意思的事情呢?比如這篇文章的主題,對(duì)一個(gè)APP進(jìn)行重簽名,讓他在我們的XCode中運(yùn)行起來,運(yùn)用我們強(qiáng)大的LLDB進(jìn)行調(diào)試,分析其UI和部分邏輯。當(dāng)然作為一個(gè)正直的開發(fā)者,我們?cè)谶@片文章肯定不會(huì)對(duì)她進(jìn)「代碼注入」這樣讓人不(興)齒(奮)的事情的(下一篇就會(huì) O(∩_∩)O哈哈~)。
片頭先給福利:點(diǎn)擊下載Demo:AppReSign,使用方法詳見demo的Readme
接下來我們會(huì)從以下幾點(diǎn)來玩一玩「APP重簽名」
- 分析Apple對(duì)App加密的需求
- 什么是雙層簽名
- 手動(dòng)對(duì)APP進(jìn)行重簽名
- 使用Shell腳本進(jìn)行重簽
1、分析Apple對(duì)App加密的需求
首先明確一點(diǎn),對(duì)App加密肯定是用要非對(duì)稱加密而不是對(duì)稱加密!這我默認(rèn)大家都懂了,應(yīng)該不用解釋。
Step 1 安裝App到手機(jī)的渠道分析
如果所有的APP都是從App Store下載的那么,這就簡(jiǎn)單了,只需要對(duì)APP進(jìn)行一層RSA加密就可以了,App Store持有私鑰,我們iPhone持有公鑰。那么問題就解決了。但事實(shí)上肯定不是這樣,我們已知的渠道除了App Store就包括XCode打包,ADHOC證書分發(fā),企業(yè)證書分發(fā)等等。為了解決這個(gè)問題,我們就得先了解Apple的具體需求是什么。
Step 2 分析需求
- App Store下載
- XCode直接安裝
- 限制ADHoc打包的APP安裝設(shè)備
- ...等等
2、什么是雙層簽名
針對(duì)以上三種(包括但不只)場(chǎng)景,蘋果給出「雙層簽名」的機(jī)制。
什么是「雙層簽名」,先上一張PPT。
看不懂?沒關(guān)系,下面會(huì)一步步,詳細(xì)的接受雙層簽名的始末。
1、向服務(wù)器申請(qǐng)證書
- 什么是CSR文件
申請(qǐng)過開發(fā)者證書的都知道,要申請(qǐng)證書,都有「Mac本地通過CSR文件向服務(wù)器」這樣的一步。那么這一步到底做了寫什么呢?
先看看什么是CSR
CSR是Certificate Signing Request的英文縮寫,即證書請(qǐng)求文件,也就是證書申請(qǐng)者在申請(qǐng)數(shù)字證書時(shí)由CSP(加密服務(wù)提供者)在生成私鑰的同時(shí)也生成證書請(qǐng)求文件,證書申請(qǐng)者只要把CSR文件提交給證書頒發(fā)機(jī)構(gòu)后,證書頒發(fā)機(jī)構(gòu)使用其根證書私鑰簽名就生成了證書公鑰文件,也就是頒發(fā)給用戶的證書。
通俗一點(diǎn),就是Mac本地有一對(duì)公鑰(公鑰M)和私鑰(私鑰M)(什么是公鑰私鑰?),在Mac上對(duì)公鑰M進(jìn)行了一層包裝,這包裝后的新東西就是CSR。
- 服務(wù)器通過CSR返回證書
本地有了CSR文件之后,將CSR上傳到Apple的服務(wù)器。
Apple服務(wù)器其實(shí)也是有一對(duì)公鑰(公鑰A)和私鑰(私鑰A),在收到Mac上傳過來的的CSR文件之后,取出其中的公鑰M,用Apple服務(wù)器的私鑰A對(duì)公鑰M進(jìn)行一次數(shù)字簽名(什么是數(shù)字簽名?)得到開發(fā)證書,然后將開發(fā)證書附入描述文件(描述文件還有哪些東西下文會(huì)有講到),最后將描述文件傳回給我們的Mac電腦。
2、描述文件
配置描述文件是 XML 文件,包含以下內(nèi)容:設(shè)備的安全策略和限制、VPN 配置信息、無線局域網(wǎng)設(shè)置、電子郵件帳戶和日歷帳戶以及可允許 iPhone、iPod touch 和 iPad 配合您的企業(yè)系統(tǒng)使用的鑒定憑證。配置描述文件能快速地將設(shè)置和授權(quán)信息載入到設(shè)備上。有些 VPN 和無線局域網(wǎng)設(shè)置只能使用配置描述文件來設(shè)定,而且如果您使用的不是 Microsoft Exchange,則將需要使用配置描述文件來設(shè)定設(shè)備密碼策略。
描述文件包括的東西,如:
- 開發(fā)證書
- APP的Bundle Id
- 證書所信任的Device Id
- 還有一些權(quán)限文件(如:Apple Pay,通知,VPN,iCloud)
3、Mac打包APP
在Mac本地有了描述文件之后,就可以對(duì)APP進(jìn)行打包了,打包這個(gè)過程除了對(duì)APP的壓縮之外,更重要的其實(shí)是指對(duì)APP的加密。
之前本地把公鑰M發(fā)送給Apple服務(wù)器,本地剩下的私鑰M就是用來加密APP的,得到一個(gè)APP的簽名文件,再將上一步得到的描述文件,以及MachO文件一起打包壓縮,最終就得到了我們的ipa包了。
所以ipa其實(shí)包含以下三種東西
- MachO文件
- APP的簽名文件
- 描述文件
4、iPhone驗(yàn)證ipa文件
上文提到的私鑰A是用來加密了公鑰M,與之對(duì)應(yīng)的公鑰A其實(shí)在我們激活iPhone的同時(shí)已經(jīng)下載好了,一直躺在我們的iPhone里面。
有了公鑰M,那么一切就簡(jiǎn)單了,
- 公鑰A解開ipa中攜帶的描述文件中的證書得到公鑰M
- 對(duì)公鑰M進(jìn)行Hash,對(duì)比證書中的Hash
- 對(duì)比通過之后,用公鑰M對(duì)加密的APP進(jìn)行解密,得到最終APP。
3、手動(dòng)對(duì)APP進(jìn)行重簽名 (如果不想看具體過程,可以跳到本節(jié)末尾,有流程總結(jié))
從上面可以得知,雙層簽名其實(shí)本質(zhì)就是如下三個(gè)步驟:
- APP的Bundle id的驗(yàn)證
- 描述文件本身的驗(yàn)證
- 對(duì)APP簽名的驗(yàn)證
注:對(duì)APP進(jìn)行重新簽名,前提是這個(gè)APP已經(jīng)被砸殼了。
下載已經(jīng)砸殼成功的APP,以下例子用微信舉例:越獄版本微信7.0.2 提取碼: 2w87
具體步驟:
Step 1 進(jìn)入WeChat目錄
解壓出 Wechat7.0.2越獄 ,進(jìn)入WeChat目錄
// 進(jìn)入WeChat的目錄
cd /Users/dengbin/Desktop/分享/主目錄/資料/Wechat7.0.2越獄/Payload
Step 2 查看APP的證書情況
codesign -d -vv「WeChat.app路徑」
Step 3 查看驗(yàn)證APP是否被加密
進(jìn)入APP的包內(nèi)容可以看到其中有一個(gè)WeChat的可執(zhí)行文件,也就是是MachO文件,就是要查看這個(gè)MachO文件時(shí)候被加密
otool -l WeChat | grep cryp
其中cryptid
為0
代表已經(jīng)砸殼,即解密,為1
或者2
表示以第1類
或者第2類
加密方案加密。
有些老鐵回復(fù)說復(fù)制代碼運(yùn)行后會(huì)報(bào)錯(cuò),有兩種情況:
1、電腦里沒有Xcode-select,應(yīng)該先去裝一次,很簡(jiǎn)單,自行百度。
2、如果還不行,代碼不要復(fù)制,自己敲一遍,就可以。(為何有些人復(fù)制不行就不得而知了)。
Step 4 查看本地證書并記錄需要用到的證書
security find-identity -v -p codesigning
Step 5 刪除不可簽名的插件(還有Watch中的插件)
由于本地存在一些插件,這些插件是不可被我們重簽,并且這個(gè)過程我們用不著,所以我們索性就刪掉。
其中包括:整個(gè)目錄PlugIns目錄和整個(gè)Watch目錄(因?yàn)閃atch.app中也有個(gè)PlugIns)
Step 6 Framework重簽名
這一步就是比較繁瑣的了,需要將Frameworks下的所有Framework進(jìn)行重簽名,運(yùn)用到XCode提供的codesign
指令,參數(shù)中的證書就是Step 4
中的一個(gè)。具體使用哪個(gè)就看個(gè)人了
codesign –fs 「證書串」 「文件名」
Step 7 給MachO添加可執(zhí)行權(quán)限
由于MachO本身就有可執(zhí)行權(quán)限,所以這一步跳過。
Step 8 App重簽名
新建一個(gè)WeChat同名工程(下文稱NewWeChat,原來的微信APP稱之為WeChat)
-
Build NewWeChat工程,進(jìn)入被編譯出的WeChat.App目錄,找到其中的embedded.mobileprovision文件,將其復(fù)制到WeChat.App(越獄微信)中
Build后的WeChatembedded.mobileprovision文件復(fù)制后的結(jié)果 -
在WeChat.App找到info.plist,并修改其中的BundleId為NewWeChat的BundleId
更改BundleId 查看embedded文件
security cms -D -i 「 embedded文件路徑」
找到其中的entitlements字段,并且復(fù)制entitlements字段和其中的內(nèi)容
-
在NewWeChat中新建entitlements.plist文件,將上一步復(fù)制得到的「entitlements字段內(nèi)容」拷貝入新的entitlements.plist文件,然后將entitlements.plist復(fù)制到WeChat.app的同級(jí)目錄下。
拷貝entitlements復(fù)制entitlements 對(duì)APP重新簽名
進(jìn)入WeChat目錄,對(duì)APP使用新的描述文件進(jìn)行重簽
codesign -fs 「證書串」 --no-strict --entitlements=entitlements.plist
- 壓縮Playload
zip –ry 「輸出文件名」 「輸入文件名」
Step 9 安裝新的ipa
可以通過各種途徑安裝ipa,如Xcode,PP助手,fir,iTunes等等, 如果手機(jī)上有正版的微信,在安裝完我們重簽名的ipa包后會(huì)發(fā)現(xiàn)手機(jī)上就有兩個(gè)微信啦!!!
如果想用LLDB調(diào)試微信,可以將重簽后的WeChat.app替換NewWeChat Build后的WeChat.app,然后直接運(yùn)行(Run)項(xiàng)目,就會(huì)發(fā)現(xiàn)我們可以用LLDB了。
Step 10 再次驗(yàn)證新的ipa是否真的重簽成功
這一步其實(shí)是重復(fù)Step 3
codesign -d -vv「WeChat.app路徑」
步驟總結(jié):
1、cd WeChat // 進(jìn)入WeChat的目錄
2、codesign -d -vv「WeChat.app路徑」 // 查看APP的證書情況
3、otool –l WeChat | grep cryp // 查看APP是否被加密
4、security find-identity -v -p codesigning // 查看本地證書
5、刪除不可簽名的插件(還有Watch中的插件)
6、codesign –fs 「證書串」 「文件名」 // Framework重簽名
7、chmod +x 可執(zhí)行文件 // 給文件添加權(quán)限
8、App重簽名
① 新建一個(gè)項(xiàng)目并且命名為 WeChat(下文稱NewWeChat,原來的微信APP稱之為WeChat) -> Build -> 找到APP中的權(quán)限文件 embedded.mobileprovision
② 復(fù)制embedded.mobileprovision到WeChat.app中
③ 修改WeChat.app中info.plist的BundleId
④ security cms -D -i 「 embedded文件路徑」 //查看WeChat中的embedded文件,復(fù)制WeChat中entitlements.plist文件的entitlements字段
⑤ 在NewWeChat中新建entitlements.plist文件,將上一步復(fù)制得到的「entitlements字段和其中的內(nèi)容」拷貝入新的entitlements.plist文件
⑥ codesign -fs 「證書串」 --no-strict --entitlements=entitlements.plist //復(fù)制新的entitlements到WeChat.app的同級(jí)目錄,并且對(duì)APP重新簽名
⑦ zip –ry 「輸出文件名」 「輸入文件名」 // 壓縮Playload
9、安裝ipa
10、再次驗(yàn)證新的ipa是否真的重簽成功
- 注意:有些人會(huì)安裝失敗,或者安裝成功會(huì)有Crash的問題,這是因?yàn)楫?dāng)前描述文件在我們的手機(jī)還不受信任,用新工程N(yùn)ewWeChat在手機(jī)上跑一遍,然后刪除NewWeChat,在嘗試安裝新的ipa,問題可以解決。
4、使用Shell腳本進(jìn)行重簽
上面所有的步驟其實(shí)是固定不變的,而且所有需要操作的文件相對(duì)于ipa文件的「相對(duì)地址」也是固定的,所以就可以用腳本來代替所有的操作。
以下腳本適用于適用XCode直接調(diào)試,點(diǎn)擊下載Demo:AppReSign,使用方法詳見demo的Readme
附上腳本代碼
# ${SRCROOT} 它是工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾,我們提前在工程目錄下新建一個(gè)APP文件夾,里面放ipa包
ASSETS_PATH="${SRCROOT}/APP"
#目標(biāo)ipa包路徑
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
#清空Temp文件夾
rm -rf "${SRCROOT}/Temp"
mkdir -p "${SRCROOT}/Temp"
#----------------------------------------
# 1\. 解壓IPA到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解壓的臨時(shí)的APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路徑是:$TEMP_APP_PATH"
#----------------------------------------
# 2\. 將解壓出來的.app拷貝進(jìn)入工程下
# BUILT_PRODUCTS_DIR 工程生成的APP包的路徑
# TARGET_NAME target名稱
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "app路徑:$TARGET_APP_PATH"
rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
#----------------------------------------
# 3\. 刪除extension和WatchAPP.個(gè)人證書沒法簽名Extention
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"
#----------------------------------------
# 4\. 更新info.plist文件 CFBundleIdentifier
# 設(shè)置:"Set : KEY Value" "目標(biāo)文件路徑"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
#----------------------------------------
# 5\. 給MachO文件上執(zhí)行權(quán)限
# 拿到MachO文件的路徑
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可執(zhí)行權(quán)限
chmod +x "$TARGET_APP_PATH/$APP_BINARY"
#----------------------------------------
# 6\. 重簽名第三方 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
這邊文章主要講了關(guān)于雙層簽名的原理,已經(jīng)利用雙層簽名的原理對(duì)APP(已越獄)進(jìn)行重簽,但其實(shí)其中有一點(diǎn)非常非常重要的內(nèi)容在這片文章知識(shí)被一筆帶過,那就是LLDB,能夠用LLDB調(diào)試我們的APP意味著無限的可能。
所以對(duì)LLDB運(yùn)用,也是咱們逆向的必經(jīng)之路。后續(xù)文章也會(huì)提到,待更新。
注意!!!
警告!!!
警告!!!
警告!!!
重簽后不要用自己的賬號(hào)登錄,有封號(hào)的危險(xiǎn)!!!