目錄
環境準備
使用USB調試iphone
用wifi調試的時候,會覺得有些卡殼,所以,改用USB,這樣速度會明顯提升。使用USB連接,需要安裝usbmuxd,安裝以後,做端口轉發即可。
ssh連接越獄iPhone
usbmuxd自帶工具iproxy,iproxy可以快捷連接iPhone操作。由於Mac上只支持4位的端口號,所以需要把iPhone的默認端口22映射到Mac上,相當於建立一個Mac和iPhone的通道。
終端輸入:
iproxy 25025 22
然後會自動顯示如下等待連接字樣
waiting for connection
在另外一個終端輸入:
ssh -p 25025 [email protected]
下面的nohup命令是讓iproxy在後臺運行,這樣,可以避免起多個terminal:
nohup iproxy 25025 22 > /dev/null 2>&1 &
ssh root@localhost -p 25025
默認密碼
越獄以後的默認密碼:alpine
免密登錄
在/var/root/.ssh/authorized_keys文件中添加本機的id_rsa.pub內容,可以實現免密ssh登錄iOS。
數據傳輸
scp -P 25025 image.jpg root@localhost:/var/mobile/Containers/Data/Application/498DC197-C1C2-46B0-A828-3AF1E9C36CE1/tmp/
靜態分析篇
要對一個iOS應用進行分析,尤其是有殼的應用程序,需要先砸殼。下面就從砸殼開始說起,如果沒有殼,也不影響,可以將應用程序dump成IPA,方便進一步分析。
iOS應用程序砸殼
使用dumpdecrypted砸殼
下面就介紹砸殼的過程:
- 下載和編譯下面的dumpdecrypted,編譯完成以後,會生成dumpdecrypted.dylib
參考:https://github.com/stefanesser/dumpdecrypted
- 將dumpdecrypted.dylib拷貝到當前權限可以寫的目錄下(看到不少文章寫要放在對應的document目錄,應該是對於沒有越獄的iphone,有權限限制的問題)
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Applications/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/AAA.app/AAA
- 執行完成以後,就會發現有一個AAA.decrypted的程序,這樣,就解決加殼的問題了。
使用frida-ios-dump砸殼(推薦使用)
除了上面的方法,還有使用frida-ios-dump的一鍵砸殼,可以參考:
http://www.alonemonkey.com/2018/01/30/frida-ios-dump/
這種方法對於動態庫(dylib)加殼是非常有用的,可以方便處理。默認dump.py使用的事2222端口,所以,需要將2222映射到IOS的22端口上。
nohup iproxy 2222 22 > /dev/null 2>&1 &
frida-ios-dump之前的版本,在Frida 12.5.0以後,存在兼容性問題,不過,後面作者修改了code,已經解決了。所以,如果你的Frida版本高於12.5.0,一定要用最新版的frida-ios-dump。
# 列出iOS設備上的應用程序
python dump.py -l
PID Name Identifier
---- -------------------- ---------------------------------
672 微信 com.tencent.xin
1250 綠傘身份 com.antgroup.nacIphoneClient
1180 設置 com.apple.Preferences
670 郵件 com.apple.mobilemail
1108 釘釘 com.laiwang.DingTalk
# 使用Name或者Identifier,進行砸殼
python dump.py com.tencent.xin -o=wechat.ipa
Class-dump導出頭文件
通過Class-dump工具可以從應用程序文件中導出相應的頭文件,這對於逆向而言,是非常重要的資源,畢竟有些code可以參考,要不直接在IDA裏逆向要來的快。
下面是class-dump的命令行參數,支持不同的arch,具體可以參考下面的說明。
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)
這裏,以微信爲例,將微信的頭文件導出到wechat-7.0.4文件夾中。
$ class-dump -H -o ~/Desktop/wechat-7.0.4/ WeChat
使用restore-symbol恢復部分Symbol
iOS應用程序可以恢復一部分符號,以AlipayWallet爲例。
# 檢查AlipayWallet是不是fat file
lipo -info AlipayWallet
# 瘦身
lipo AlipayWallet -thin arm64 -output AlipayWallet.arm64
# 恢復符號
restore-symbol AlipayWallet.arm64 -o AlipayWallet.arm64.symbol
# 使用ida_search_block.py生成json file
# https://github.com/tobefuturer/restore-symbol/blob/master/search_oc_block/ida_search_block.py
# 恢復block symbol
restore-symbol AlipayWallet.symbol -o AlipayWallet.symbol.2 -j AlipayWallet_block_symbol.json
# 將AlipayWallet.symbol.2拷貝到Payload/AlipayWallet.app/AlipayWallet
cp AlipayWallet.symbol.2 Payload/AlipayWallet.app/AlipayWallet
# 獲得權限文件
ldid -e Payload/AlipayWallet.app/AlipayWallet > ~/workspace/alipay-ios8/AlipayWalletEntitlements.plist
# 簽名
codesign -f -s "iPhone Developer: xxxxx" --entitlement ~/workspace/alipay-ios8/AlipayWalletEntitlements.plist Payload/AlipayWallet.app/AlipayWallet
# 壓縮打包成ipa,用iTools安裝到手機上
細節可以參考:
http://www.cocoachina.com/cms/wap.php?action=article&id=23921
http://blog.imjun.net/posts/restore-symbol-of-iOS-app/
使用IDA分析可執行程序
這個毋庸多說,直接找對應的可執行程序,拷貝到mac上,然後,用IDA打開就可以了。
動態調試篇
使用LLDB調試
配置debugserver
默認連接xcode給ios添加的debugserver是支持多個CPU架構的,需要根據自己的機型選擇合適的CPU架構,這些信息可以參考下面的iPhone與CPU架構對應關係
目前個人使用的是iphone5s,所以,保留arm64的平臺。
從ios上將debugserver拷貝到mac上,然後,用下面的命令給debugserver瘦身。
lipo -thin arm64 ./debugserver -output ./debugserver
給debugserver添加task_for_pid權限,需要先下載ent.xml, 然後,用下面的命令:
ldid -Sent.xml debugserver
然後,將瘦身的debugserver再拷貝到iphone的/user/bin目錄下,可以直接執行
在iOS上用debugserver來attach進程
調試器常用的兩種方式,一種是attach process,另外一種是start process,下面分別介紹:
attach process
啓動debugserver,並attach SpringBoard,開放端口25026給LLDB客戶端連接
debugserver *:25026 -a "SpringBoard"
在MacOS的終端上,先做端口轉發,將本地25026端口轉發到iphone的25026端口上
nohup iproxy 25026 25026 > /dev/null 2>&1 &
在LLDB中用下面的命令連接:
process connect connect://localhost:25026
參考:iOS應用逆向工程
start process
debugserver -x backboard *:25026 path-to-application
網上有些說法是用posix代替backboard,個人實驗以後,發現下面的情況:
1) backboard可以看到用戶界面
2)posix看不到UI
具體使用哪種,視情況而定
對抗反調試問題
對於有反調試保護的APP,需要繞開反調試,目前反調試的方法主要還是以後ptrace,所以,只要跳過ptrace即可。
實現方法多樣,可以是調試器的command,也可以是script,也可以自己編寫tweak。
用command的話,下面的命令可供參考:
# set breakpoint at ptrace
b ptrace
# continue and trigger breakpoint
c
# modify $pc to return address
register write pc `$lr`
# continue to run
c
更多細節可以參考https://segmentfault.com/a/1190000012199291
也可以使用我寫的lldb script: https://github.com/michaelpdu/lldb_scripts/blob/master/aadebug.py
LLDB+Python
LLD內置Python解釋器,這樣就可以做很多事了。
詳細可以參考官方文檔:https://lldb.llvm.org/python-reference.html
使用IDA-Server調試
暫時還沒有玩過,以後玩過了再補上。
使用Frida調試
Frida是跨平臺插樁工具,支持多種平臺,iOS和Android都支持,具體的內容可以參考官網:https://www.frida.re/
Frida可以直接使用JavaScript來hook iOS應用的函數,最方便的是可以做到在Objective-C++語言級別上的函數調用。
下面的代碼片段是通過Frida的ObjC.classes來完成應用程序中的函數調用,方便探測對應函數的結果是什麼
[iPhone::PID::843]-> var rootPath = ObjC.classes.APDataCenter["+ preferencesRootPath"]()
[iPhone::PID::843]-> console.log(rootPath)
/var/mobile/Containers/Data/Application/AB8040C3-FCDF-4E01-98E1-9EC3414C8867/Documents/Preferences
[iPhone::PID::843]-> var dataCenter = ObjC.classes.APDataCenter["+ defaultDataCenter"]()
[iPhone::PID::843]-> var commonPerf = dataCenter["- commonPreferences"]()
[iPhone::PID::843]-> console.log(commonPerf.path())
/var/mobile/Containers/Data/Application/AB8040C3-FCDF-4E01-98E1-9EC3414C8867/Documents/Preferences/9c7c560b34de477b.db
[iPhone::PID::843]-> var userPerf = dataCenter["- userPreferences"]()
[iPhone::PID::843]-> console.log(userPerf.path())
/var/mobile/Containers/Data/Application/AB8040C3-FCDF-4E01-98E1-9EC3414C8867/Documents/Preferences/eacb882264825e7d.db
[iPhone::PID::843]-> var lruPerf = ObjC.classes.APLRUDiskCache["+ sharedPreferences"]()
[iPhone::PID::843]-> console.log(lruPerf.path())
/var/mobile/Containers/Data/Application/AB8040C3-FCDF-4E01-98E1-9EC3414C8867/Documents/Preferences/LRU.db
使用Objection調試
Objection是基於Frida做的一個高層API,可以很方便地Hook class,這對動態分析非常有幫助。
可以使用下面的命令進入objection的交互界面,這樣,就可以利用其強大的功能了。
objection --gadget xxx explore
其他分析方法
BurpSuite截獲網絡流量
參考官方網站的介紹:
流量中,可能會有些被gzip壓縮,需要安裝一個插件:
Extender --> BApp Store --> Decompressor
Reveal -- UI分析利器
對於大型的客戶端程序,裏面包含的ViewController數以千計,想要快速地定位到程序邏輯,從UI入手最簡單,這是,就需要Reveal的幫助。具體使用,可以參考:
http://wiki.jikexueyuan.com/project/ios-security-defense/reveal.html
其中,安裝Reveal以後,找不到libReveal.dylib,可以將RevealServer重命名爲libReveal.dylib,拷貝過去即可
scp -P 25025 /Applications/Reveal.app//Contents/SharedSupport/iOS-Libraries/RevealServer.framework/RevealServer root@localhost:/Library/MobileSubstrate/DynamicLibraries/libReveal.dylib
修改libReveal.plist,將要分析的APP bundles添加到filter中。
{
Filter = {
Bundles = ("com.apple.AppStore");
};
}
重啓設備(或者killall SpringBoard),然後,就可以看到相應的應用程序了。
這篇文章上說的方法:https://www.jianshu.com/p/45dc72ec9499
是直接使用Cydia,安裝Reveal Loader(新版本可以用Reveal2Loader),不過,這裏封裝的Reveal版本未必與當前機器上安裝的版本一致,如果較低的話,會出現下面這樣的錯誤。
重打包技術
使用MonkeyDev中的MonkeyApp,可以簡單地完成應用程序重打包的目的。具體可以參考下面wiki:
https://github.com/AloneMonkey/MonkeyDev/wiki/%E9%9D%9E%E8%B6%8A%E7%8B%B1App%E9%9B%86%E6%88%90
(1)創建MonkeyApp
(2)使用frida-ios-dump對應用程序砸殼以後,會產生一個IPA文件,將其copy到TargetApp目錄中。
(3)在build settings的最下面User-Defined選項中,有幾個比較重要,這裏,簡單介紹一下。
- MONKEYDEV_CLASS_DUMP: 就是上面class-dump的功能
- MONKEYDEV_DEFAULT_BUNDLEID: 使用默認的bundle ID,這個可以設置爲YES
- MONKEYDEV_RESTORE_SYMBOL: restore-symbol的功能
附錄
iPhone與CPU架構對應關係
armv6: iPhone、iPhone 2、iPhone 3G、iPod Touch(第一代)、iPod Touch(第二代)
armv7: iPhone 3Gs、iPhone 4、iPhone 4s、iPad、iPad 2
armv7s: iPhone 5、iPhone 5c (靜態庫只要支持了armv7,就可以在armv7s的架構上運行)
arm64(注:無armv64): iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、 iPhone 7 、iPhone 7 Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3、iPad mini4、iPad Pro