一烂叔、IPA 的簡單認識
首先有一個這樣的 ipa 包文件:
直接修改文件后綴為:IPADev.zip, 然后解壓,是這樣的:
從這個解壓的文件結構來看蚜厉,說明一個 ipa 包,實際上就是一個壓縮文件包畜眨。解壓之后是一個 Payload 的文件夾昼牛,這個文件夾中帶有一個 .app 文件夾,再次進入這個文件夾康聂,具體內(nèi)容如下:
這是一個贰健,簡單的 app 文件夾,實際項目中這里面的文件會很多恬汁。
以上就是對一個 ipa 包的結構做的一個簡要介紹伶椿,但是以上是一個通過 Xcode 的 Aechive 打的一個 Ad Hoc 包。不同的包的結構會有所不同,比如從 App Store 下載下來的會多一層包裝脊另,但是大體的結構還是一樣的导狡。
二、簡單的打包
新創(chuàng)建一個項目 IPADev偎痛,然后開始打包旱捧,這里的打包并非使用 Xcode 的 Archive 打包,而是另類的手動打包踩麦。先看下面項目的配置:
配置好之后枚赡,直接 command+b, 然后發(fā)現(xiàn) Products 文件夾下面的 .app 文件變黑了,直接 Show in Finder 進入這樣的界面:
通過上一小節(jié)的介紹谓谦,我們可以通過這個 IPADev.app 手動構建一個 ipa 包么贫橙?答案是可以的,將 IPADev.app 放入一個空的 Payload 文件夾中反粥,然后壓縮成 zip 文件卢肃,將 zip 改成 ipa 即可。最后是這樣的:
現(xiàn)在 Payload.ipa 就是一個正規(guī)的 ipa 包了星压。當然這個包與平時看到的文件名有點不一樣践剂,手動改成 IPADev.app 即可,改不改都一樣娜膘。
那么問題來了逊脯,這么生成的 ipa 包能安裝到真機上么?試一下就知道答案了竣贪。當然了军洼,只能安裝到一個已在 .app 文件中 embedded.mobileprovision 配置文件中包括注冊的設備上,與一個 Ad Hoc 包的性質(zhì)是一樣的演怎。當然了匕争,可以在任意的越獄手機上安裝的。
但是如果手動將 IPADev.app 中與簽名相關的文件刪除再壓縮的話爷耀,只能在越獄真機上安裝甘桑,在非越獄真機上直接報錯。在安裝的過程中歹叮,明顯感覺越獄真機上的安裝速度比較快跑杭。說明...
三狮荔、對現(xiàn)有包重簽名
常規(guī)開發(fā)中是沒有這樣操作的域蜗,往往是為了將別人的 ipa 占為己有涯穷,添加自己開發(fā)的代碼(動態(tài)庫)抖僵,這一操作被叫做 動態(tài)庫注入宝鼓。動態(tài)庫注入的方式有很多糯崎,簡單的介紹一下相對常規(guī)的一種通過 Theos 技術生成 dylib 庫的注入方式队询。
顯然往踢,通過 Theos 生成的 dylib 庫只能在越獄手機上使用。要想在非越獄設備上運行椭盏,只能通過動態(tài)庫注入组砚,然后重簽名打包,這樣才能在非越獄設備上運行庸汗。
3.1 資源準備
- 即將重簽名的 .app 文件惫确。
- 即將添加的 dylib 庫。
- 簽名配置文件(embedded.mobileprovision)蚯舱。
- dylib 關聯(lián)的動態(tài)庫 CydiaSubstrate改化。
- 動態(tài)庫注入工具 insert_dylib。
如下圖所示:
3.2 動態(tài)庫注入
將 hgdev.dylib 放入 HGSecurityDev.app 中枉昏,通過然后執(zhí)行如下命令:
./insert_dylib @executable_path/hgdev.dylib HGSecurityDev.app/HGSecurityDev --weak --all-yes HGSecurityDev.app/HGSecurityDev
命令格式為:./insert_dylib ++動態(tài)庫文件++ ++Mach-O文件++ ++--weak --all-yes++ ++最終生成的 MachO 文件++
通過 otool 查看一下動態(tài)庫的關聯(lián)情況:
otool -L HGSecurityDev.app/HGSecurityDev
說明成功注入陈肛。
在這里,還需要注意一個問題兄裂,這個動態(tài)庫(hgdev.dylib)實在越獄設備上生成的句旱,會默認關聯(lián)一個越獄設備上特有的動態(tài)庫(CydiaSubstrate),通過如下命令查看:
otool -L HGSecurityDev.app/hgdev.dylib
最后希望在非越獄的真機上也能運行晰奖,所以需要手動的添加并重新關聯(lián)谈撒。將 CydiaSubstrate 也放入 HGSecurityDev.app 中,然后執(zhí)行如下命令:
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate HGSecurityDev.app/hgdev.dylib
再次查看動態(tài)庫信息如下:
到現(xiàn)在為止匾南,關于動態(tài)庫的注入操作啃匿,都結束了。接下來就是數(shù)字簽名蛆楞。
3.3 給相應的文件簽名
一般情況溯乒,只要是 .app 文件有所改動,這些文件將需要重新簽名豹爹。
- app 文件裆悄。
- 動態(tài)庫文件。
- app 關聯(lián)的擴展項目臂聋。
3.3.1 簽名前的準備
對 app 文件簽名光稼,必須要有一個簽名配置文件(embedded.mobileprovision),如果破解的是一個 Ad Hoc 的包孩等,那么在 .app 文件中會有一個艾君,如果是沒有的,可以自己準備一個自己的瞎访。
先來看一下 Xcode 是如何簽名的:
接下來腻贰,我們使用的就是這個指令吁恍。上圖中的 .xcent 文件扒秸,就是 簽名配置文件(embedded.mobileprovision)轉(zhuǎn)化后的配置文件(后面介紹如何轉(zhuǎn))播演。
對于動態(tài)庫的簽名,只要有證書編號即可伴奥,查看證書編號的命令:
security find-identity -v -p codesigning
給動態(tài)庫簽名的指令很簡單写烤,格式為:codesign -fs 證書編號 Mach-O 文件 。分別給兩個動態(tài)庫簽名拾徙,命令如下:
codesign -fs 283729D4DDC7F173281DA85F105982C4B1E3C15E HGSecurityDev.app/CydiaSubstrate
codesign -fs 283729D4DDC7F173281DA85F105982C4B1E3C15E HGSecurityDev.app/hgdev.dylib
如圖所示:
給 .app 文件簽名洲炊。
先從 embedded.mobileprovision 文件中提取出 entitlements.plist 權限文件
,命令如下:
security cms -D -i embedded.mobileprovision > temp.plist
/usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist
分成兩步尼啡,最終生成一個權限文件 entitlements.plist暂衡。
正式簽名的命令如下:
codesign -fs 283729D4DDC7F173281DA85F105982C4B1E3C15E --entitlements entitlements.plist HGSecurityDev.app
最終我們看到的 .app 文件是這樣的:
上面的 CydiaSubtrate 與 hgdev.dylib 是新添加的動態(tài)庫。至此崖瞭,重簽名的操作已經(jīng)全部完成狂巢,下一步,直接變成 ipa 文件书聚。
到這里唧领,有一個關鍵性的問題:
為什么需要重簽名操作?
因為注入動態(tài)庫之后雌续,對當前的 Mach-O 文件有所修改斩个,破壞了之前的簽名,想要保證在非越獄的設備上也能安裝驯杜,那么就需要重新簽名受啥。
3.4 壓縮成 ipa 文件
將 HGSecurityDev.app 放入一個空的 Payload 文件夾中,壓縮改名為 HGSecurityDev.ipa 即可艇肴。
生成的包可以直接安裝到越獄設備中腔呜,也可以安裝在非越獄的設備中(前提是要在簽名文件中注冊與 Ad Hoc 包的性質(zhì)一樣)。
四再悼、注意事項
上面是以我自己創(chuàng)建的一個簡單項目為例子核畴,但是通常我們所要重簽名的包都是來自 App Store。步驟都是一致的冲九,但是有幾點需要注意:
- 必須是未加殼的 Mach-O 文件重簽名打包后才能安裝于非越獄的設備谤草。
- 重簽名生成的 ipa 包一般是不能上線App Store 的,只能自己使用或者企業(yè)賬號下使用莺奸。
- 這是一個簡單的例子丑孩,在實際的項目中可能還會有其它的 framework, 這樣在 .app 文件夾中就會有所有的 framework,那么在重簽名的時候需要先給這個 framework 中的 MachO 文件重簽名灭贷。當我們進入某一個 framework 會發(fā)現(xiàn)都有一個 _CodeSignature 文件夾(下一小節(jié)會介紹)温学,所以也需要將這些提前重簽名。
五甚疟、關于簽名文件
對于一個 ipa 文件來說仗岖,打開 .app 文件夾就會有一個這樣的文件夾:
據(jù)我觀察一個 Mach-O 文件會有一個這樣的文件夾逃延,這個簽名文件中的內(nèi)容是當前 Mach-O 文件所在目錄中的所有文件進行簽名。比如當前的項目還有其它的 framework 文件轧拄,那么在這個 framework 中也會有這樣的文件夾揽祥。
其實我們比較關心的是 可執(zhí)行文件的簽名文件夾中簽名內(nèi)容。
在這里要注意一個問題:我們都知道蘋果的這一套數(shù)字簽名是唯一的檩电。但是對于一個已經(jīng)上架的 App Store 來拄丰,安裝到不同的設備上,卻不是唯一的俐末。
我們都知道料按,只要是上線之后的包,肯定是固定不變的卓箫。但是一旦安裝到不同的設備站绪,就不一樣了。同樣是從 App Store 上下載丽柿,但是我們不同的設備下載下來的可能會不一樣恢准。比如:
你在 arm-64 設備上下載的,那么在設備上世紀下載安裝的就是 arm-64 的可執(zhí)行文件甫题,這應該也是 App Store 做的一個優(yōu)化馁筐。
還有另一種情況,關于 iOS 的應用坠非,我們還可以其它的渠道直接下載 ipa 文件敏沉, 比如 itools,如果通過這樣的方式下載安裝的話炎码,會發(fā)現(xiàn)我們安裝的包是這樣的:
是一個胖二進制文件盟迟。
那么上面說的問題就很好理解了,不同的情況安裝到設備上的可執(zhí)行文件不一樣潦闲,那這個簽名文件也會不一樣就不足為奇了攒菠。