iOS逆向學習之十二(iOS簽名機制)

iOS簽名機制的做用

在學習了上一章什麼是加密解密、數字簽名以及證書以後,如今咱們再來學習iOS的簽名機制就事半功倍了。其實iOS簽名機制的做用就是保證安裝到用戶手機上的App都是通過Apple官方容許的。固然,越獄設備除外。ios

在平時開發時,不論是真機調試,仍是發佈App到App Store,咱們都須要通過如下幾個步驟git

  • 首先,在Mac上生成CertificateSigningRequest.certSigningRequest文件
  • 而後在Apple開發者網站上獲取到ios_development.cer或者ios_distribution.cer證書文件,前者是開發證書,後者是發佈證書
  • 在Apple開發者網站上註冊device,添加App ID。
  • 選擇device、App ID以及開發證書或者生產證書,生成mobileprovision文件

通過以上的一系列操做以後,咱們最終就能夠拿到ios_development.cer或者ios_distribution.cer證書文件,以及mobileprovision描述文件。經過安裝這些文件到Mac上就能夠進行真機調試。固然,若是你在Xcode中勾選了Automatically manage signing選項,那麼Xcode會自動幫咱們執行以上的全部操做。github

那麼,以上操做每一步執行的做用是什麼?最後得到的ios_development.cer或者ios_distribution.cer證書文件,以及mobileprovision描述文件的做用又是什麼?這些文件中又包含了什麼內容?bash

iOS簽名流程

要想知道上述全部文件的具體做用,就須要瞭解iOS簽名的完整流程。在使用Xcode編譯、運行完項目以後,Xcode其實幫咱們作了簽名操做。markdown

其實就是利用codeSign指令對.app文件進行簽名操做。app

準備

想要執行iOS簽名流程,就須要有如下公鑰、私鑰信息iphone

  • Mac設備的公鑰和私鑰,通常是Mac設備本身生成
  • Apple官方的私鑰,保存在Apple的後臺
  • Apple官方的公鑰,每一臺iPhone出廠以後都會保存Apple官方的公鑰信息

簽名流程分析

iOS項目在編譯完成以後會生成.app文件,App的簽名操做從拿到.app文件開始ide

  • 第一步,拿到.app文件以後,使用Mac私鑰對.app文件進行簽名操做,生成的簽名文件存放在.app目錄下的_CodeSignature/CodeResources

  • 第二步,使用Apple私鑰對Mac公鑰進行簽名,生成證書文件

  • 第三步,將第二步獲取到的證書文件和devices、app id以及entitlement一塊兒使用Apple私鑰再次進行簽名,生成mobileprovision文件,也就是描述文件。

  • 第四步,將第一步簽名事後的.app文件和第三步生成的mobileprovision文件一塊兒壓縮生成ipa安裝包。

  • 最後,完整的簽名打包過程以下

驗證流程

對.app安裝包進行簽名以後,壓縮生成ipa安裝包,而後將ipa安裝包安裝到iPhone上時,會進行簽名驗證操做。工具

  • 第一步,使用iPhone上存放的Apple公鑰驗證mobileprovision文件中的簽名。
  • 第二步,簽名驗證成功以後,拿到mobileprovision中存放的devices、app id以及entitlement信息。同時拿到證書文件。而後使用Apple公鑰對證書中的簽名進行驗證。驗證成功以後拿到Mac公鑰。
  • 第三步,拿到Mac公鑰以後,使用Mac公鑰對App的簽名文件進行驗證,若是驗證成功,則代表當前的App的源碼沒有被篡改過。而後此App就能安裝到iPhone上
  • 最後獲得完整的簽名加驗證流程,以下

在文件mobileprovision中,有devices、app id以及entitlement信息,它們的做用分別是:oop

  • devices標識着哪些設備能夠安裝此App,若是設備不在devices中,安裝會失敗。
  • app id,指定此標識的App才能安裝,若是App的惟一標識和此app id不對應,則安裝失敗。
  • entitlement中存放在App所具有的權限信息,若是App所使用的權限和entitlement中存放的權限不一致,也會產生問題。

簽名實際操做流程

上文學習了iOS簽名的具體流程,如今,咱們就來一步步的執行實際的操做來對咱們所學的簽名流程進行驗證。同時瞭解ios_development.cer或者ios_distribution.cer證書文件,以及mobileprovision等文件的實際做用。

  • 第一步,在Mac上生成CertificateSigningRequest.certSigningRequest文件,其實這個文件就是Mac設備的公鑰。

  • 第二步,登陸Apple開發者網站,獲取證書,安裝到Mac設備。
    • 建立certificates

- 選擇證書類型,有開發證書和發佈證書。

- 上傳CertificateSigningRequest.certSigningRequest文件,也就是Mac公鑰信息。

- 下載證書,安裝到Mac設備上

此步驟就是利用Apple的私鑰,對Mac公鑰進行簽名,生成證書文件ios_development.cer和ios_distribution.cer

  • 第三步,生成mobileprovision
    • 建立mobileprovision,能夠選擇開發環境或者生產環境

- 選擇App ID

- 選擇設備devices

- 選擇證書certificates

- 生成mobileprovision文件,下載到Mac上進行安裝

此步驟就是將devices、app id、entitlement和證書文件,經過Apple私鑰進行簽名,生成最後的mobileprovision文件。並且生成的mobileprovision文件就決定了當前App能夠安裝的設備有哪些,能夠安裝的App的BundleId,以及App所擁有的權限。

Apple官方驗證流程

Apple官方驗證流程以下:

重簽名

當咱們逆向了一款App,爲App編寫了相應的插件,而且安裝到了咱們本身的越獄手機上。可是,逆向過的App只能在本身越獄手機上使用,若是咱們想要將App和咱們本身編寫的插件從新打包,安裝到未越獄的iPhone上,那就須要學習如何對App進行重簽名。

學習重簽名以前,須要注意幾點

  • 第一,安裝包中的可執行文件必須是進行過脫殼操做的,重簽名纔會生效,否則會安裝失敗
  • 第二,重簽名所須要的mobileprovision文件必須是付費開發者帳號申請的才能夠,免費開發者帳號沒法進行重簽名。
  • 第三,.app包中的全部動態庫(.framework,.dylib)、AppExtension(PlugIns文件夾,拓展名是appex)、WatchApp(Watch文件夾)等都須要進行重簽名操做

CodeSign指令重簽名

具體步驟

  • 首先,須要準備一個embedded.mobileprovision文件(必須是付費開發者帳號生成的,裏面的appid、device等須要匹配),而後將此文件放入.app包中

生成mobileprovision文件有兩種方式,第一種是經過Xcode自動生成,在編譯後的App包中能夠找到,第二種是到Apple官網生成,上文有詳細步驟。

  • 從embedded.mobileprovision文件中提取出entitlements.plist權限文件,具體有兩步:
// 首先從embedded.mobileprovision文件中導出權限信息,存放到temp.plist中
security cms -D -i embedded.mobileprovision > temp.plist

# 而後使用PlistBuddy工具將temp.plist轉換成Entitlements格式的文件entitlements.plist
/usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist
複製代碼
  • 查看Mac上可使用的證書,獲取到證書的Identity,後續簽名須要使用,具體指令以下
security find-identity -v -p codesigning
複製代碼

獲得的結果以下

➜  ~ security find-identity -v -p codesigning
  1) D9E2802126C89BF6BF6621064FC5547F895FC25E "iPhone Developer: xxxxx@xxxx.com (KT9PJDKFVG)"
複製代碼
  • 對.app包中的全部動態庫、AppExtension等進行重簽名,前提是修改過這些動態庫或者AppExtension,若是沒有修改的動態庫或者AppExtension,能夠跳過此步驟。指令以下:
# -fs 是 -f -s 的縮寫
codesign -fs 證書ID xxx.dylib
複製代碼
  • 對.app包進行簽名,須要使用到以前生成的entitlements.plist文件,指令以下:
codesign -fs 證書ID --entitlements entitlements.plist xxx.app
複製代碼

Theos插件重簽名

使用Xcode編譯本身的項目,咱們知道源碼,因此知道怎麼修改Mach-O文件,可是若是咱們在逆向別人的App時,是不知作別人的源碼的,因此沒法直接修改Mach-O文件。

以前的文章中學習了Theos,知道了怎麼經過建立Tweak項目來修改App的行爲,具體流程能夠查看iOS逆向學習之六(Theos實戰演練)這篇文章。

Tweak加載方式

建立了Tweak項目以後,經過Cydia安裝到越獄手機上,而後就能夠改變App的行爲。具體是怎麼實現的呢?

  • 首先,Tweak項目通過編譯生成的是一個dylib動態庫文件,存放在Tweak項目目錄.theos/obj/debug/目錄下。
  • 執行make package打包以後生成對應的deb文件,存放在packages目錄下。
  • 執行make install以後,會經過Cydia安裝到手機上,dylib文件存放在~/Library/MobileSubstrate/DynamicLibraries/目錄下。
  • 在App啓動以後,會同時將dylib加載到內存中,App中若是訪問被咱們hook的類中的方法,會直接執行dylib中的方法。

動態庫的注入

Tweak項目本質上是生成動態庫,並且動態庫不是存放在.app目錄下,因此,想要將咱們逆向過的App安裝到別人的手機上,首先須要作的就是將Tweak項目生成的動態庫注入到App中的可執行文件中,也就是Mach-O文件中。

可使用insert_dylib庫來將動態庫注入到Mach-O文件中,能夠經過insert_dylib庫主頁下載insert_dylib工具。在Release環境下編譯,獲得命令行工具,將命令行工具放在/usr/local/bin目錄下。

insert_dylib庫用法

insert_dylib的本質其實就是往Mach-O文件的Load Commands中添加了一個LC_LOAD_DYLIB或者LC_LOAD_WEAK_DYLIB。具體注入方法以下:

insert_dylib 動態庫加載路徑 Mach-O文件 --all-yes --weak
複製代碼
  • --weak選項表示,即便當前注入的動態庫找不到,App也不會報錯
  • --all-yes選項表示,後面全部的選項都選yes
查看Mach-O的動態庫依賴信息

查看動態庫依賴信息兩種方式

  • 經過otool查看Mach-O的動態庫依賴信息
otool -L Mach-O文件
複製代碼

  • 經過MachOView查看Mach-O的動態庫依賴信息

更改動態庫的加載地址

在向Mach-O文件中注入動態庫以後,須要更改Mach-O文件中動態庫的加載地址,不然在App運行時,會由於找不到動態庫報錯。

可使用install_name_tool指令來修改Mach-O文件中動態庫的加載地址:

install_name_tool -change 舊地址 新地址 Mach-O文件
複製代碼

須要注意的是,上述指令中的新地址,必須填寫全路徑地址,可是咱們不知道App安裝到手機上後dylib存放的具體地址,所以,可使用如下兩個經常使用的環境變量:

  • @executable_path表明可執行文件所在的目錄,也就是Mach-O文件所在目錄。咱們將dylib和可執行文件放在同一個目錄下,而後將地址修改成@executable_path/dylib名稱。這就表示在加載動態庫時,到可執行文件所在的目錄下去尋找動態庫。
  • @loader_path表明動態庫所在的目錄,此環境變量通常在動態庫依賴其它動態庫的狀況下使用,若是咱們須要注入的動態庫還依賴其它動態庫,那麼就須要將所依賴的動態庫和原動態庫存放在同一目錄下,而後更改動態庫的加載地址爲@loader_path/動態庫名稱。這表示到原動態庫所在目錄下加載須要依賴的動態庫。

Theos開發的動態庫插件注意事項

  • 咱們使用Theos開發的動態庫插件(dylib)由於使用過Cydia安裝的,因此它默認是依賴CydiaSubstrate插件的。CydiaSubstrate插件存放目錄爲iPhone的/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate。
  • 若是想要將咱們開發的動態庫插件打包到ipa中, 就須要同時將CydiaSubstrate一塊兒打包到ipa中,而且須要修改CydiaSubstrate的加載地址。

重簽名GUI工具

iReSign

能夠點擊下載iReSign源碼,運行裏面的Mac應用,提供.app包的路徑、entitlements.plist路徑和embedded.mobileprovision的路徑,就能夠對.app進行重簽名,而後打包生成ipa文件。

iOS App Signer

能夠點擊下載iOS App Signer源碼,選擇Release環境進行編譯,拿到編譯後的Mac應用,就能夠直接使用。只需提供.app包的路徑和embedded.mobileprovision的路徑

重簽名練習

練習1、使用codesign指令對Xcode生成.app文件進行重簽名

如今咱們就來使用Xcode生成.app包,而後一步一步實現重簽名的過程。

  • 首先,建立iOS項目TestSign,在ViewController中增長以下代碼
#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *labelA;
@property (weak, nonatomic) IBOutlet UILabel *labelB;
@property (weak, nonatomic) IBOutlet UILabel *labelResult;

@end

@implementation ViewController

int a = 10;
int b = 20;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.labelA.text = [NSString stringWithFormat:@"%d",a];
    self.labelB.text = [NSString stringWithFormat:@"%d",b];
    self.labelResult.text = [NSString stringWithFormat:@"%d",a + b];
}


@end
複製代碼
  • 運行項目在界面上能夠看到10 + 20 = 30的效果,此時,拿到編譯Product目錄下生成的.app包TestSign.app
  • 此時,建立PayLoad文件夾,將TestSign.app放到文件夾中,壓縮PayLoad文件夾,修改壓縮文件的後綴爲.ipa,將PayLoad.ipa直接安裝到手機上,是能夠直接安裝成功的,由於編譯的時候就是選擇的是真機編譯,並且mobileprovision文件也是由Xcode自動生成,包含當前設備。
  • 經過以前的學習咱們知道,在Mach-O文件中,全局變量存放的位置是__DATA段,使用MachOView打開estSign.app中的可執行文件,以下

<font color=red>0A</font>轉換成10進制就是10,對應着全局變量a,<font color=red>14</font>轉換成10進制就是20,對應着全局變量b。
複製代碼
  • 直接修改Mach-O文件,將全局變量a的值修改爲14,也就是將a的值改成20。

  • 從新壓縮生成.ipa文件,使用iFunBox將ipa安裝到同一臺手機上,會出現安裝失敗提示,緣由是.app中的Mach-O文件已經被篡改,它的簽名也將會失效。因此安裝在iPhone上時對App的簽名驗證也會失敗,因此會致使安裝失敗。此時就須要對.app進行重簽名。

  • 拿到TestSign.app包中的embedded.mobileprovision文件,從embedded.mobileprovision文件中提取出entitlements.plist文件,指令以下:

// 首先從embedded.mobileprovision文件中導出權限信息,存放到temp.plist中
security cms -D -i embedded.mobileprovision > temp.plist

# 而後使用PlistBuddy工具將temp.plist轉換成Entitlements格式的文件entitlements.plist
/usr/libexec/PlistBuddy -x -c 'Print :Entitlements' temp.plist > entitlements.plist

複製代碼
  • 經過如下指令獲取到證書ID,要與embedded.mobileprovision文件中的證書保持一致:
security find-identity -v -p codesigning
複製代碼
  • 使用codesign指令對.app包進行重簽名
codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 --entitlements entitlements.plist TestSign.app 
複製代碼

出現上圖效果,代表重簽名成功,此時,從新壓縮TestSign.app文件,獲得ipa,安裝到以前的手機上就能夠安裝成功,同時,由於全局變量a的值被咱們改爲了20,因此界面上展現的是20 + 20 = 40。至此,重簽名操做完成。

練習2、Theos開發插件,注入騰訊視頻App,安裝到非越獄手機

下面爲騰訊視頻開發Theos插件,而後注入到騰訊視頻App,而且從新生成ipa,安裝到非越獄手機上,

  • 首先,下載騰訊視頻App,能夠經過愛思助手、PP助手下載已經進行過脫殼的App,或者經過App Store下載,而後使用Clutch工具進行脫殼操做。注意,必需要是脫殼後的App才能進行重簽名,不然簽名無效。
  • 鏈接手機,使用Reveal查看騰訊視頻的頁面,找到主界面QLHomeController。具體流程可參考iOS逆向學習之二(Mac遠程操控iPhone)和iOS逆向學習之三(Cycript)
  • 建立Tweak項目。使用nic.pl指令建立Tweak項目,按步驟填寫所須要的信息。注意MobileSubstrate Bundle filter填寫騰訊視頻App的bundle ID,經過Cycript獲取到bundle ID爲com.tencent.live4iphone。
  • 在Tweak.x文件中添加以下代碼,效果是在騰訊視頻首頁彈出一個Alert彈框。
@interface QLHomeController

- (id)presentViewController:(id)controller animated:(BOOL)animated completion:(id)completion;

@end

%hook QLHomeController

- (void)viewDidAppear:(BOOL)animated{

    %orig;
  
    UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"提示框" message:@"測試Theos插件" preferredStyle:UIAlertControllerStyleAlert];
    [alertVc addAction:[UIAlertAction actionWithTitle:@"關閉" style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alertVc animated:YES completion:nil];
}

%end

複製代碼
  • 執行make package && make install,對Tweak項目進行打包,打包完成後經過Cydia安裝到iPhone上,等待iPhone重啓,而後打開騰訊視頻,在首頁就能夠看到咱們寫的彈框了。

  • 獲取如下簽名須要的一些文件

    • 在iPhone上的/var/mobile/Containers/Bundle/Application/目錄下找到live4iphone.app安裝包。
    • 在/Library/MobileSubstrate/DynamicLibraries/目錄下找到咱們編寫的插件所生成的動態庫test_live.dylib。
    • 在/Library/Frameworks/CydiaSubstrate.framework/目錄下找到test_live.dylib依賴的動態庫CydiaSubstrate。
    • 獲取以前練習中使用的embedded.mobileprovision文件。
  • 將test_live.dylib、CydiaSubstrate和embedded.mobileprovision文件複製到live4iphone.app包中。

  • 向live4iphone.app包中的可執行文件中注入動態庫

insert_dylib @executable_path/test_live.dylib live4iphone --all-yes --weak live4iphone
複製代碼

出現如下結果代表注入成功:

➜  live4iphone.app insert_dylib @executable_path/test_live.dylib live4iphone --all-yes --weak live4iphone
live4iphone already exists. Overwrite it? [y/n] y
Binary is a fat binary with 2 archs.
LC_CODE_SIGNATURE load command found. Remove it? [y/n] y
LC_CODE_SIGNATURE load command found. Remove it? [y/n] y
Added LC_LOAD_WEAK_DYLIB to all archs in live4iphone
複製代碼

使用otool指令或者MachOView查看騰訊視頻的可執行文件,能夠發現動態庫已經注入到Mach-O文件當中

  • 修改CydiaSubstrate庫的路徑
    • 經過otool查看test_live.dylib的依賴庫信息。

- 此時發現<font color=red>CydiaSubstrate</font>的路徑是<font color=red>/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate</font>,可是在非越獄手機上是沒有這個路徑的,因此須要經過install_name_tool指令來改變更態庫的加載路徑。
```
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate test_live.dylib
```
再次查看<font color=red>test_live.dylib</font>的依賴庫信息,會發現<font color=red>CydiaSubstrate</font>庫的路徑變成了<font color=red>@loader_path/CydiaSubstrate</font>
複製代碼
  • 分別對test_live.dylib和CydiaSubstrate進行重簽名
➜  live4iphone.app codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 test_live.dylib
test_live.dylib: replacing existing signature
➜  live4iphone.app codesign -fs 1BEA2FE8783A297CF30B7728849EB225231D67E8 CydiaSubstrate
CydiaSubstrate: replacing existing signature
➜  live4iphone.app
複製代碼
  • 使用iOS App Signer對live4iphone.app進行重簽名,生成ipa安裝包

  • 將live4iphone.ipa安裝到非越獄手機上,能夠發現安裝成功,而且進入以後出現彈框。

相關文章
相關標籤/搜索