iOS逆向與安全:基礎篇
前言
從本篇文章開始,筆者會整理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
,填入一下:
執行命令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.x
和python3.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遇到了一個問題,新版的RevealServer
是Framework
而舊版的是dylib
,兩者整合方式不同,但是網上很多資料都是過時的,所以這裡給出新版的整合方式。
首先在Cydia
下載Reveal2Loader
外掛。外掛安裝後進入設定找到Reveal-->Enabled Applications
選擇要檢視的App。例如:簡書
電腦端安裝Reveal
軟體,正常情況下,開啟手機上的簡書APP會在Reveal
中看到下圖,點選進入即可檢視介面結構。
有時會出現RevealServer.framework
版本問題,電腦端點選Help->Show Reveal Library in Finder
將Framework
拷貝到手機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記憶體資訊的工具。
在越獄裝置上安裝
Cycript
是saurik
提供的工具,在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
由於程式的程式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
檢視APP
的Application
資訊,例如:檢視簡書的Application
物件,為自定義的HGApplication
。
cy# UIApp
# "<HGApplication: 0x154d49910>"
檢視rootViewController
。
cy# UIApp.keyWindow .rootViewController
#"<HGTabBarController: 0x155006200>"
還可以使用地址檢視資訊。例如:檢視HGTabBarController
的view
。
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+
,而在MAC
和iOS
中是Mach-O
格式。
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檔案:
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資料夾,裡面包含所有的標頭檔案。
參考文章
- Mach-O 檔案格式探索
- 趣探 Mach-O:檔案格式分析
- 《iOS應用逆向與安全》作者:劉培慶
相關文章
- iOS逆向之旅(基礎篇) — Macho檔案iOSMac
- iOS逆向之旅(基礎篇) — 彙編(一)— 彙編基礎iOS
- iOS逆向-彙編基礎(一)iOS
- iOS逆向之旅(基礎篇) — 彙編(五) — 彙編下的BlockiOSBloC
- iOS逆向工程 iOS工具篇iOS
- iOS逆向之旅(基礎篇) — 彙編(四) — 彙編下的函式iOS函式
- iOS逆向之旅(基礎篇) — 彙編(二) — 彙編下的 IF語句iOS
- iOS 逆向 - lldb高階篇 Chisel 與 CycriptiOSLLDB
- 《iOS 應用逆向與安全》讀後感iOS
- iOS逆向之旅(基礎篇) — 彙編(三) — 彙編下的 Switch語句iOS
- 羽夏逆向——逆向基礎
- 20192204-exp1-逆向與Bof基礎
- 逆向基礎(六)
- 逆向基礎(五)
- 逆向基礎(四)
- 逆向基礎(三)
- 逆向基礎(十一)
- 逆向基礎(十)
- 逆向基礎(十二)
- 逆向基礎(一)
- 逆向基礎(二)
- 逆向基礎(九)
- 逆向基礎(八)
- 逆向基礎(七)
- iOS 繪製漸變·基礎篇iOS
- iOS 動畫基礎總結篇iOS動畫
- iOS開發小記-基礎篇iOS
- 逆向工程核心原理(1)逆向基礎
- iOS逆向之旅(進階篇) — 工具(LLDB)iOSLLDB
- iOS逆向之旅(進階篇) — HOOK(Logos)iOSHookGo
- iOS逆向之旅(進階篇) — HOOK(FishHook)iOSHook
- iOS逆向之旅(基礎篇) — App的簽名機制【Xcode是如何將App安裝到手機的】iOSAPPXCode
- iOS逆向之旅(進階篇) — 程式碼注入iOS
- iOS逆向之旅(進階篇) — HOOK(Method Swizzling)iOSHook
- iOS開發基礎篇--NSNotificationCenter使用小結iOS
- 逆向基礎(十三) JAVA (一)Java
- iOS開發基礎109-網路安全iOS
- java安全編碼指南之:基礎篇Java