iOS逆向與安全:基礎篇

weixin_33994444發表於2018-10-31
1363078-a0a7899eba0c7a15.png

前言

從本篇文章開始,筆者會整理iOS逆向相關的筆記。作為一位新人,希望通過整理筆記能夠更好的理解和掌握知識。作為新人能力有限,在行文時難免出現錯誤歡迎批評和指正。

前期準備:

  • 一臺越獄的iOS裝置,筆者使用iPad mini2系統iOS9.2.1(推薦使用iOS9.1或者可以完美越獄的系統)
  • 一臺電腦,筆者使用的是MacBook Pro
  • 一條資料線

如何越獄

網上有很多教程幫助你來越獄,這裡推薦兩個網站:

注意:在購買iOS裝置時直接購買對應版本的系統,由於蘋果官方關閉降級通道所以無法刷韌體降級。

越獄成功後,桌面上會出現一個叫做Cydia的應用,它是越獄後的App Store可以安裝各種第三方的軟體,比如:外掛、補丁、APP等。該應用的作者Jay Freeman(saurik),一位骨灰級大神。

必裝外掛或補丁

  • Apple File Conduit 2:可以訪問整個iOS裝置的檔案系統。作者是Jay Freeman
  • AppSync unified: 可以繞過系統驗證,隨意安裝、執行破解的IPA安裝包。
  • PP助手: 一個應用商店,可以自由安裝海量APP。
  • OpenSSH: 用於遠端登入iOS裝置。

Mac 必備

  • iFunBox: 管理檔案系統。
  • PP助手:一個應用商店。
  • iTerm2: 一款優秀的命令列工具
  • Alfred: 便捷搜尋,自定義工作流,調高效率的工具

配置遠端登入

SSH:Secure Shell的縮寫,安全外殼協議,是一種可以為遠端登入提供安全保障的協議。使用SSH可以把所有傳輸的資料進行加密,防止中間人攻擊、DNS欺騙和IP欺騙。
OpenSSH: 是SSH協議的免費開源實現。通過它讓Mac登入iOS裝置,在Cycript中搜尋安裝。

使用密碼登入

如果iOS裝置上已經安裝了OpenSSH,此時就可以通過Mac終端登入iOS裝置。前提,iOS裝置和Mac需要處於相同WiFi環境下。在設定中檢視iOS裝置的IP地址。開啟終端輸入:

ssh root@iOS裝置IP地址
// 回車,會提示時候建立連線輸入yes即可。之後提示輸入密碼,預設密碼是`alpine`。

iOS裝置上有兩個預設賬號:root,mobile。

  • root:最高許可權賬戶,$HOME是/var/root。或者通過終端輸入pwd檢視。
  • mobile:普通許可權賬戶,只能操作一些普通檔案,$HOME是/var/mobile
  • mobile登入方式:ssh mobile@伺服器地址。初始密碼alpine
  • 修改root密碼:passwd,修改mobile使用者密碼:passwd mobile

公鑰登入

上面的密碼登入方式比較麻煩,在每次登入時都需要輸入密碼。SSH提供了公鑰登入,以省去密碼的步驟。下面來看看公鑰登入流程:
將電腦端的SSH公鑰儲存在iOS裝置中,登入時iOS裝置端會向電腦端傳送一個隨機字串,登入使用者通過自己的私鑰加密後傳送給iOS端,iOS端通過事先儲存好的公鑰解密,如果解密成功,證明使用者是可信的。

檢視$HOME/.ssh/目錄,是否有id_rsa私鑰和id_rsa.pub公鑰,如果沒有使用ssh-keygen生成。

上傳公鑰到遠端裝置,通過ssh-copy-id命令。

ssh-copy-id -i $HOME/.ssh/id_rsa.pub root@地址

該條命令的作用是將id_rsa.pub公鑰追加到iOS裝置的$HOME/.ssh/authorized_keys檔案中。

cat $HOME/.ssh/authorized_keys //檢視檔案內容

通過USB登入裝置

在WiFi不穩定的情況下,通過WiFi登入會非常的卡頓。可以通過介面轉發的方法,使用USB SSH登入,保證連線的穩定性。

方法很簡單,首先安裝libimobiledevice,然後使用裡面提供iproxy把本地埠(例如:2222)對映到裝置的TCP埠22,就可以通過本地的2222埠建立連線了。

brew install libimobiledevice
iproxy 2222 22
ssh root@localhost -p 2222

如果,每次輸入iproxy 2222 22進行介面轉換比較麻煩,可以將其配置到電腦的開機啟動項中。建立~/Library/LaunchAgents/com.usbmux.iproxy.plist,填入一下:

1363078-fd54d1638acce3b4.png

執行命令launchctl load ~/Library/LaunchAgents/com.usbmux.iproxy.plist使之生效。

每次輸入ssh root@localhost -p 2222也很麻煩,可以通過指定一個名稱進行SSH連線,開啟$HOME/.ssh/config檔案,沒有建立一個,寫入一下內容。

Host ipad 
Hostname localhost
User root
Port 2222 

通過以上配置,在終端輸入ssh ipad即可登入iOS裝置了。

砸殼

App Store下載應用都會進行加密,破解加密稱為砸殼。本節記錄在學習砸殼中遇到的問題和解決方法。

三種砸殼方案:

這三種方案網上很多教程,下面整理的是第三種方案簡單高效。

配置環境

iOS裝置和電腦都需安裝Frida

iOS裝置安裝Frida,開啟Cydia新增軟體源https://build.frida.re,之後搜尋Frida安裝。電腦端通過pip命令sudo pip install frida安裝。

接下來,克隆frida-ios-dump庫到本地。倉庫有兩個分支分別對應python2.xpython3.x,需要根據本地Python版本來判斷。

// Mac終端
python -V
// 筆者:Python 3.6.3 :: Anaconda custom (64-bit)

由於筆者配置的Python 3.x,切換到3.x分支安裝firda-ios-dump依賴。在frida-ios-dump倉庫目錄下執行下面命令。

sudo pip install -r requirements.txt --upgrade

安裝結束後,將越獄裝置通過USB連上電腦進行埠對映:

iproxy 2222 22

到此配置結束,如果一切順利就可以進行砸殼了。

進行砸殼

frida-ios-dump目錄下,使用命令./dump.py -l檢視應用名稱和Bundle ID,通過命令./dump.py + 程式名字 or BundleID即可砸殼。當程式執行完,在當前目錄中會出現一個xxx.ipa

不過,通往成功的道路永遠不是一帆風順的,在執行./dump.py命令是出現了錯誤Waiting for USB device...。在這個issue中給出瞭解決方案。

推薦文章一條命令完成砸殼

Reveal配置

Reveal是一款用於檢視程式介面結構和除錯介面的工具,可以在開發中動態修改除錯程式碼修改程式的樣式,也可以注入到第三方APP檢視應用的介面結構。

本節將會學習如何在越獄裝置和非越獄裝置上檢視應用的結構。

越獄裝置整合Reveal

筆者在越獄裝置整合Reveal遇到了一個問題,新版的RevealServerFramework而舊版的是dylib,兩者整合方式不同,但是網上很多資料都是過時的,所以這裡給出新版的整合方式。

首先在Cydia下載Reveal2Loader外掛。外掛安裝後進入設定找到Reveal-->Enabled Applications選擇要檢視的App。例如:簡書

電腦端安裝Reveal軟體,正常情況下,開啟手機上的簡書APP會在Reveal中看到下圖,點選進入即可檢視介面結構。

1363078-577e14f4816e38e0.png

有時會出現RevealServer.framework版本問題,電腦端點選Help->Show Reveal Library in FinderFramework拷貝到手機Library/Frameworks目錄下替換原來的。

非越獄裝置整合Reveal

如果在開發中整合Reveal直接使用CocoaPods即可,在Podfile檔案加入以下內容:

//只在Debug模式下開啟
 pod 'Reveal-SDK', :configurations => ['Debug']

之後執行pod install即可整合。

如果想在非越獄裝置檢視其它App的介面結構,需要使用MonkeyDev工具輔助完成。
首先安裝MonkeyDev,安裝在GitHub倉庫有文件。

非越獄裝置整合Reveal還需要目標App的脫殼ipa包。具體步驟檢視文章:

Cycript配置

Cycript是允許開發者使用Objective-C++Javascript組合語法檢視及修改執行時APP記憶體資訊的工具。

在越獄裝置上安裝

Cycriptsaurik提供的工具,在Cydia中搜尋Cycript並安裝即可。

安裝完成後,用SSH登入裝置輸入cycript命令,就可以進入互動介面。

在越獄裝置上,可以使用一些命令注入目標程式,除錯目標函式。下面例子:指令碼注入到SpringBoard(桌面)中,使其彈出一個提示框。

iPad:~ root# cycript -p SpringBoard
cy# var alert = [[UIAlertView alloc] initWithTitle:@"Hello" message:@"Hello, wold!" delegate:nil cancelButtonTitle: @"cancel" otherButtonTitles: nil]
#"<UIAlertView: 0x1348bd1f0; frame = (0 0; 0 0); layer = <CALayer: 0x1321c89b0>>"
cy# [alert show]

這是《iOS應用逆向與安全》中給出的一個簡單的例子。

Cycript分析應用

上面例子中使用了一條命令cycript -p SpringBoard,通過該命令可以除錯指定APP。該命令有兩種使用方式,除了上面的cycript -p 程式名稱,還可以通過cycript -p 程式程式ID。注意這裡的程式的名稱並不是APP的名稱。

檢視程式的名稱和程式ID可以通過安裝一個外掛adv-cmds。通過它使用ps命令檢視當前執行程式的程式ID及可執行檔案的路徑。

安裝完成後,通過ps -A命令檢視當前裝置的程式ID和可執行檔案的路徑。同時,支援關鍵詞搜尋ps -A | grep 關鍵詞

例如,檢視簡書的路徑和程式ID

1363078-222a9702273c9d50.png
簡書

由於程式的程式ID是會發生變換的推薦使用名稱。

下面就以簡書為例,學習如何使用cycript的使用。

檢視應用資訊

cy# NSHomeDirectory() // 沙盒路徑
cy# NSBundle.mainBundle().bundleIdentifier //BundleID
cy# NSBundle.mainBundle().bundlePath //mainBundlePath
cy# NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES)[0] // Document Path
cy# NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES)[0] // cache Path

檢視APPApplication資訊,例如:檢視簡書的Application物件,為自定義的HGApplication

cy# UIApp 
# "<HGApplication: 0x154d49910>" 

檢視rootViewController

cy# UIApp.keyWindow .rootViewController
#"<HGTabBarController: 0x155006200>"

還可以使用地址檢視資訊。例如:檢視HGTabBarControllerview

cy# #0x155006200.view
#"<UILayoutContainerView: 0x154fca480; frame = (0 0; 1024 768); autoresize = W+H; layer = <CALayer: 0x154f65a20>>"

另外Cycript提供了choose()函式選擇某個類的例項陣列。例如:學習簡書中所有的Button類的所有例項陣列。

cy# choose(UIButton)
[#"<UIButton: 0x157210600; frame = (0 8.5; 685 16); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x15705f020>>",
#"<HGAvatarButton: 0x15724ead0; baseClass = UIButton; frame = (16 14.5; 45 45); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1572088b0>>".....]

以上是cycript的基本用法。

cycript高階用法

每次要輸入那麼多的程式碼是在有點麻煩,能不能將常用的程式碼封裝起來呢?答案是肯定的。

Cycript本身是支援載入自己的指令碼的,可以通過@import命令載入。例如:載入mjscript指令碼。

cy# @import mjcript

關於如何將自己學的指令碼新增到手機上檢視【越獄-逆向】基於Cycript實現的一些實用函式文件,對如何新增,如何使用寫的比較詳細,這裡就不再重複贅述。

Class-dump

本節學習如何使用工具匯出第三方App的標頭檔案,學習前需要補充點基礎知識。

Mach-O檔案

想讓程式在裝置上執行起來,需要將寫好的程式碼生成可執行檔案這樣才能被作業系統所理解。比如,在Linux下可執行檔案的格式是ELF,在Window中可執行檔案是PE32/PE32+,而在MACiOS中是Mach-O格式。

Mach-O的組成結構如下圖:

1363078-9fb657a1bbd733ca.png
圖片來自《Mach-O 檔案格式探索》

可以看的出 Mach-O 主要由 3 部分組成:

  • Mach-O 頭(Mach Header):這裡描述了 Mach-O 的 CPU 架構、檔案型別以及載入命令等資訊;
  • 載入命令(Load Command):描述了檔案中資料的具體組織結構,不同的資料型別使用不同的載入命令表示;
  • 資料區(Data):Data 中每一個段(Segment)的資料都儲存在此,段的概念和 ELF 檔案中段的概念類似,都擁有一個或多個 Section ,用來存放資料和程式碼。

如何獲取Mach-O檔案,在App Store中下載應用.ipa改成.zip格式,之後解壓縮會在裡面發現一個應用同名的檔案。
下面是簡書的Mach-O檔案:

1363078-d2ab060158eb4397.png

Class-dump使用

class-dump的作用就是把Mach-O檔案的class資訊匯出來生成標頭檔案。

下載後將其中的class-dump拷貝到/usr/local/bin目錄下,就可以在終端使用class-dump命令。

終端輸入class-dump

class-dump 3.5 (64 bit) (Debug version compiled Sep 17 2017 16:24:48)
Usage: class-dump [options] <mach-o-file>

  where options are:
        -a             show instance variable offsets
        -A             show implementation addresses
        --arch <arch>  choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64, armv6, armv7, armv7s, arm64)
        -C <regex>     only display classes matching regular expression
        -f <str>       find string in method name
        -H             generate header files in current directory, or directory specified with -o
        -I             sort classes, categories, and protocols by inheritance (overrides -s)
        -o <dir>       output directory used for -H
        -r             recursively expand frameworks and fixed VM shared libraries
        -s             sort classes and categories by name
        -S             sort methods by name
        -t             suppress header in output, for testing
        --list-arches  list the arches in the file, then exit
        --sdk-ios      specify iOS SDK version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk
                       or /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS<version>.sdk)
        --sdk-mac      specify Mac OS X version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX<version>.sdk
                       or /Developer/SDKs/MacOSX<version>.sdk)
        --sdk-root     specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)

安裝成功,可以解析標頭檔案方法很簡單,常用指令。

class-dump -H mach-o路徑 -o 標頭檔案儲存路徑

以簡書App為例,使用之前砸殼的ipa檔案,找到裡面的Mach-O檔案。

class-dump -H Hugo -o ./Header

在當前目錄中會生成Header資料夾,裡面包含所有的標頭檔案。

參考文章

相關文章