教你如何動態除錯 iOS App(反編譯App)

在路上。發表於2018-04-18

開篇

通過本文你能瞭解 iOS 逆向的基本知識,對 iOS App 的安全有一定了解。然後能舉一反三,在自家 App 找到危險漏洞加以預防,保證使用者資料安全。

在安全領域,攻與防永遠存在。哪怕是 iPhone 有著強大的安全防護機制,也擋不住那些極客們一次又一次的好奇,開發了很多強大且便利的工具。本文就是在這些極客們提供的工具的基礎上完成的!

準備工具

HTTP(S) 抓包

HTTP 抓包

第一步:獲取 MAC IP

按下Option鍵,同時點選 Mac 選單欄上的無線網 Icon,能看到當前電腦的 IP 地址。 或在終端輸入 ifconfig en0 也可檢視。

第二步:設定代理

保證手機和電腦在同一 WIFI 下,在手機上,點選“設定->無線區域網->連線的WiFi”,設定HTTP代理:

伺服器:為 Mac 電腦 IP 地址(如192.168.1.122)

埠:8888

第三步:抓包

在電腦端,開啟 Charles。使手機發生網路請求,Charles 會彈出一個詢問的對話方塊

點選“Allow”允許,Charles 會出現手機的 HTTP 請求記錄列表。

HTTPS 抓包

第一步: 獲取證書安裝地址

安裝 SSL 證書到手機裝置。點選 Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device

出現彈窗得到地址 chls.pro/ssl

第二步:iPhone 安裝證書

在手機 Safari 瀏覽器輸入地址 chls.pro/ssl,出現證書安裝頁面,點選安裝,手機設定有密碼的輸入密碼進行安裝

第三步:配置代理 host

Charles 設定 Proxy。選擇 Proxy -> SSL Proxying Settings...

勾選 Enable SSL Proxying,點選 Add

Host 設定要抓取的 HTTPS 介面,Port 填寫 443。

讓手機重新傳送 HTTPS 請求,可看到抓包。

注意:不抓包請關閉手機 HTTP 代理,否則斷開與電腦連線後會連不上網!

拿到 .h 標頭檔案

從 AppStore 直接下載的 ipa, 蘋果公司對其做了 FairPlay DRM 技術進行加密保護,無法直接使用 class-dump 工具獲取標頭檔案。但是如果是通過 development 打包出來的話的 App 的話,是可以直接使用 class-dump 檢視所有標頭檔案的,此部分介紹就是通過此情況來說明如何獲取 .h 檔案的。

此處不再介紹 class-dump 工具的安裝過程,具體步驟請直接百度。

進入到 appName.ipa 所在目錄,修改副檔名為 .zip,然後解壓檔案,得到 appName.app。

然後執行:

class-dump -H appName.app -o ./headers/

命令執行完成後,會在當前目錄下的 headers 目錄裡看到 app 所有標頭檔案。

如果新增引數 -A -S 會在標頭檔案裡標記處類方法和屬性的 IMP 地址(模組偏移前基地址)。

class-dump -H -A -S appName.app -o ./headers/

SSH 訪問手機檔案目錄

在你的越獄手機上使用 Cydia 應用市場安裝 OpenSSH,並保證 Mac 和 iPhone 處於同一個WIFI下,在 MAC 終端輸入:

ssh root@IP ,IP 替換為 iPhone 的 IP 地址

輸入預設密碼:alpine

即可進入 iPhone 終端。

使用 Clutch 反編譯 App

第一步:重新簽名 debugserver

取得 debugserver 有兩種方式。

第一種是在 Mac 電腦中拿到

進入路徑 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.3/DeveloperDiskImage.dmg(其中路徑裡 8.3,代表 iOS 系統版本,需與準備的越獄手機系統版本保持一致)。雙擊 DeveloperDiskImage.dmg,將目錄裡的 usr/bin/debugserver 複製到指定資料夾中。

第二種是在越獄手機裡拿到

如果手機連線過手機並通過 XCode 除錯過 app,會在手機裡的 /Developer/usr/bin/ 目錄下生成一個 debugserver 檔案。通過 iFunbox 匯出至 Mac 桌面。或使用 scp 命令 cpoy 出來。

重簽名 debugserver

即給 debugserver 新增 task_for_pid 許可權

建立 entitlements.plist,新增如下四個 key:

複製程式碼

key 對應的 value 都設為設為 ture

將 entitlements.plist 和 debugserver 放在同一個目錄下,執行以下命令:

codesign -s - --entitlements entitlements.plist -f debugserver

此命令會重新簽名 debugserver,將簽名後的 debugserver 拷貝至手機系統的 /usr/bin/ 目錄下。

注意:不要將 debugserver 拷貝至 /Developer/usr/bin/ 路徑下

第二步: 通過 Clutch 拿到反編譯後的 App 可執行檔案

將下載好的 Clutch 放入手機的 /usr/bin/ 路徑下。然後,給 Clutch 賦予許可權,通過 SSH 登入到手機,進入 /usr/bin/ 執行 chmod a+x ./Clutch

通過命令 Clutch -i,列出所有的可被 Clutch 的應用。

對指定序號的應用進行脫殼,如企業微信,序號是1,命令是 Clutch -d 1。執行完成後,會得到脫殼後的 ipa。

第三步:使用 class-dump 拿到 .h 標頭檔案

使用上文 【拿到.h標頭檔案】 介紹的方法拿到脫殼後的 App 標頭檔案和並記下要打斷點的方法的 IMP 地址。

動態除錯 App

本文動態除錯用到的偵錯程式是 lldb。

第一步:使 iPhone 進入等待掛載狀態

SSH 登入到手機,執行 ps -e 命令得到 App PID 或專案名稱。

進入 /usr/bin/ 執行 ./debugserver IP:port -a PID|appProjectName。 其中第一個引數 IP 可以替換為 Mac 電腦 IP地址,或者使用 * 萬用字元,允許所有 IP 除錯;第二個引數 port 隨便寫一個就行。第四個引數 可以指定要除錯 App 的 PID 或專案名稱。比如要除錯的 PID 為 6019 的搜狗輸入法專案名稱為SogouInput,則命令即為:

./debugserver *:1234 -a 6019./debugserver *:1234 -a ‘SogouInput’

此命令執行完成後,app會進入等到掛載狀態,app會被卡住點選無反應。正常現象!

如果此命令報錯,如出現 Segmentation fault: 11 等情況,說明 App 做了反動態除錯保護。遇到此種情況,需先確定 App 採用了哪種保護方案,然後進一步找到對應措施,幹掉它的反動態除錯保護。

第二步:監聽程式,進入掛載狀態

重新開啟一個 Mac 終端執行 lldb 進入 lldb 除錯狀態。然後輸入

process connect connect://iPhoneIP:port

iPhoneIP 替換為 iPhone 的 IP 地址;port 改為剛才指定的埠,即 1234。

待命令執行完成後,App 即進入掛載狀態。

第三步:獲取 App 的 ASLR 偏移量

ASLR偏移量其實就是虛擬記憶體的地址相對於模組基地址的偏移量。有兩個概念需要熟悉一下:

  • 模組在記憶體中的起始地址 ---- 模組基地址
  • ASLR偏移 ---- 虛擬記憶體起始地址與模組基地址的偏移量

在 lldb 偵錯程式模式下,執行 imge list -o -f

模組偏移後的基地址 = ASLR 偏移量 + 模組偏移前基地址(方法的 IMP 地址)

上面這個公式是尤為重要的,因為 Class-dump 中顯示的都是“模組偏移前基地址”,而 lldb 要操作的都是“模組偏移後的基地址”。所以從 Class-dump 到 lldb 要做一個地址偏移量的轉換。

至此,已得到了 App 的 ASLR 偏移量和方法的 IMP 地址。

第四步:打斷點,除錯

在 lldb 模式下執行,br s -a 'ASLR 偏移量+ IMP',然後執行 c,使 App 跑起來,觸發一個方法呼叫,就會進入斷點模式。輸入 po $arg1 列印第一個引數。

然後,配合著抓包工具 Charles(比如分析網路請求加密邏輯) 和 Class-dump(比如修改某個類的方法返回值)等工具,你就可以隨意動態除錯 App 了,就像在 XCode 裡除錯一樣!

br 命令說明

br dis 1 -- 禁用(disable)編號為1的斷點

br en 1 -- 啟用(enable)編號為1的斷點

br dis -- 禁用所有斷點

br en -- 啟用所有斷點

br del 1 -- 刪除(delete)編號為1的斷點

br del -- 刪除所有斷點

br list -- 列出所有斷點

使用 dumpdecrypted 破殼 App

dumpdecrypted 脫殼工具的原理是:將應用程式執行起來(iOS 系統會先解密程式再啟動),然後將記憶體中的解密結果 dump 寫入檔案中,得到一個新的可執行程式。

第一步:生成 .dylib 檔案

在終端進入到下載後的目錄中,cd dumpdecrypted-master,然後執行 make,即可生成 dumpdecrypted.dylib

第二步:找到 App 的 Documents 資料夾路徑

通過 SSH 登入到 iPhone,然後執行 ps -e 檢視程式,獲取要破殼的程式 PID。然後執行 cycript -p PID 附加到 PID 程式上。最後執行 [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]得到 Documents 資料夾路徑。

第三步:開始破殼

將第一步生成的 dumpdecrypted.dylib 拷貝到第二步得到的 .../Documents/ 路徑下,命令如下:scp ~/dumpdecrypted.dylib root@IP:/var/mobile/Containers/Data/Application/2B4C6281-C015-4FF3-A8EC-5E5C7554D447/Documents(將路徑裡的 UDID 替換為你的要破殼的 App 的 UDID)

進入 Documents 目錄下,執行DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/ Application/BFED82A3-3238-4F41-B797-C1CB584CBE05/appProjectName.app/appProjectName(將路徑裡的 UDID 替換為你的要破殼的 App 的 UDID;將 appProjectName 替換為要破殼 App 的專案名稱)

待命令執行完,會在當前目錄生成一個名為 appProject.decrypted 的檔案,這個就是破殼後的 App 可執行檔案,要的就是它!使用 Class-dump 即可得到標頭檔案。或使用 Hopper 或 IDA Pro 進行反編譯。

給你的 App 新增反動態除錯機制

ptrace

為了方便應用軟體的開發和除錯,從Unix的早期版本開始就提供了一種對執行中的程式進行跟蹤和控制的手段,那就是系統呼叫 ptrace()。 通過 ptrace 可以對另一個程式實現除錯跟蹤,同時 ptrace 還提供了一個非常有用的引數那就是 PTDENYATTACH,這個引數用來告訴系統,阻止偵錯程式依附。

所以最常用的反除錯方案就是通過呼叫ptrace來實現反除錯。

sysctl

當一個程式被除錯的時候,該程式會有一個標記來標記自己正在被除錯,所以可以通過 sysctl 去檢視當前程式的資訊,看有沒有這個標記位即可檢查當前除錯狀態。

檢測到偵錯程式就退出,或者製造崩潰,或者隱藏工程,當然也可以定時去檢視有沒有這個標記。

syscall

為從實現從使用者態切換到核心態,系統提供了一個系統呼叫函式 syscall,上面講到的 ptrace 也是通過系統呼叫去實現的。

在Kernel Syscalls27這裡可以找到 ptrace 對應的編號。

26. ptrace 801e812c T

所以如下的呼叫等同於呼叫 ptrace:

syscall(26,31,0,0,0);

arm

syscall 是通過軟中斷來實現從使用者態到核心態,也可以通過彙編 svc 呼叫來實現。

覺得不錯的話,歡迎關注我的公眾號哦!


相關文章