IOS逆向技術入門

目錄

 

環境準備

使用USB調試iphone

ssh連接越獄iPhone

默認密碼

免密登錄

數據傳輸

靜態分析篇

iOS應用程序砸殼

使用dumpdecrypted砸殼

使用frida-ios-dump砸殼(推薦使用)

Class-dump導出頭文件

使用restore-symbol恢復部分Symbol

使用IDA分析可執行程序

動態調試篇

使用LLDB調試

配置debugserver

在iOS上用debugserver來attach進程

對抗反調試問題

LLDB+Python

使用IDA-Server調試

使用Frida調試

使用Objection調試

其他分析方法

BurpSuite截獲網絡流量

Reveal -- UI分析利器

重打包技術

附錄

iPhone與CPU架構對應關係

LLDB Cheatsheet


環境準備

使用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]

參考:SSH連接越獄iPhone

 

下面的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截獲網絡流量

參考官方網站的介紹:

https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp

 

流量中,可能會有些被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

 

LLDB Cheatsheet

LLDB Cheatsheet

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章