[iOS 逆向 6] 分析與調試

逆向核心環節,但是隻能通過實踐學習,後面有專門的實踐文章。至於本文,瀏覽一遍即可,並安裝幾個分析工具。

靜態分析

靜態分析就是在不運行程序的情況下分析程序。

藉助工具對二進制反彙編進行靜態分析,可以得到被分析文件的反彙編代碼、流程圖及僞代碼,也可以直接修改彙編指令,生成新的可執行文件。工具中提供的反編譯僞代碼功能讓彙編基礎薄弱的人也能做靜態分析,大大降低了逆向工程的門檻。下面介紹兩個反彙編工具:Hopper Disassembler 和 IDA Pro。

Hopper Disassembler

Hopper 提供 Mac、Linux 版本。使用 Hopper 打開目標可執行文件,可以自動識別出文件包含的架構,選擇某一架構開始分析。

界面十分簡潔易用,第一次使用的用戶也能看出界面左側是符號和字符串列表,中間是反彙編得到的代碼。逆向工程中,我們一般是想了解或修改程序中的某個功能,而功能肯定是在某個函數內實現的,所以肯定要先找到函數名,然後才能找到對應的彙編代碼進行靜態分析。下面列舉幾個尋找目標函數的例子。

  • 按鈕或其他視圖的事件響應函數:通過界面調試工具,找到視圖組件對象,打印出它的事件響應對象,進而得到響應函數。
  • 一些後臺默默進行的任務,比如獲取地理位置,向服務器發送操作日誌:這類操作一般程序員都會封裝爲專門的工具類,通過提取頭文件,分析頭文件大概率可以找到。
  • 通過判斷某個值來影響某個視圖的內容:一切與視圖有關的逆向分析都可以使用界面調試工具找到視圖對象、控制器對象,然後結合對象所屬類的頭文件,分析行爲可能發生在哪個函數內,然後去看彙編代碼確保是目標函數。

找到目標函數後,如果是要學習功能實現,只看代碼邏輯即可;如果要修改邏輯,可以 hook 目標函數或者判斷條件的函數,或者在 hook 函數內直接將條件滿足。後面文章會介紹 hook。

在用工具分析彙編代碼時,有一些功能經常用到:

  • 查看某個函數的僞代碼,工具條上有轉換按鈕。
  • 選中函數或變量,用快捷鍵 X 或在界面右邊欄查看交叉引用,便於分析調用關係。
  • 用快捷鍵 G 跳轉到指定地址。
  • 用快捷鍵 空格 在流程圖和彙編代碼之間切換查看。
  • Mac 逆向中經常會修改彙編指令,在菜單欄中可以打開修改窗口。

IDA Pro

IDA Pro 提供 Windows、Mac、Linux 版本,功能比 Hopper 多一些。目前網絡上能免費下載的最高爲 7.0 版本,但是在最新的 macOS 10.15 上無法安裝,解決辦法是先在低版本的 mac 上安裝,把安裝成功後的 app 直接複製到高版本 mac,如果沒有低版本 mac,可以直接在這裏下載。安裝後有兩個 app,分別提供 32 位和 64 位二進制文件的解析,如果打不開其中的 ida64,執行此命令即可:sudo xattr -rd com.apple.quarantine ida64.app。如果仍然打不開,則切換輸入法爲英文,再嘗試。使用時如果崩潰,先檢查輸入法,只能用英文。

如果只做 iOS 逆向,那麼這兩個反彙編工具的比較:
Hopper 最新版($100) = IDA Pro 7.0(網上下載) > Hopper 舊版(網上下載)
IDA Pro 最新版($1000+)禁止大陸 IP 購買,不在考慮範圍內。

使用 IDA 打開文件,選擇架構。主界面整體結構和 Hopper 相同,擁有 Hopper 的所有功能,額外的常用功能有:

  • 快捷鍵 F5 用於查看僞代碼,免費的前提下,可讀性最高。
  • 快捷鍵 Tab 在彙編代碼和僞代碼間切換查看。
  • 菜單欄中提供多種搜索方式,包括字符串、立即數、地址等。
  • 在僞代碼中按 / 輸入註釋,在彙編代碼中按 / 把僞代碼插入到彙編代碼中。
  • 快捷鍵 N 可以給地址、標籤、寄存器、變量重命名。
  • 選中數字,用快捷鍵 H 在十進制和十六進制互相轉換。

動態調試

靜態分析只能分析函數內部執行邏輯,但是如果想獲取程序在運行過程中的參數傳遞、實際執行過程、寄存器和內存等信息,就需要使用動態調試。下面介紹 LLDB 命令行調試和直接使用 Xcode 調試。

LLDB

準備

Xcode 自帶 LLDB 調試工具,支持本地/遠程調試。當遠程調試手機 App 時,Xcode 會將 debugserver 文件複製到手機中,在手機上啓動一個服務,等待 Xcode 連接。所以得先真機調試一次,手機上纔會有 debugserver 文件,位於 /Developer/usr/bin 目錄。

debugserver 默認只能調試自己開發的應用,調試從 App Store 下載的應用會報錯,這時需要給 debugserver 賦予調試任意程序的權限。

用 Xcode 創建一份 plist 文件,寫入以下鍵值對:
在這裏插入圖片描述
如果 iOS 版本較高,如 iOS 12 以上,可能需要加更多鍵值對,我用的完整內容如下:
在這裏插入圖片描述
執行chmod +x debugserver以確保 debugserver 有執行權限,然後簽名:
codesign -fs 'iPhone Developer: 證書 (xxx)' --entitlements xxx.plist debugserver
完成對 debugserver 授權後,將其複製到手機的 /usr/bin 目錄下。

打開目標程序,然後開啓調試服務:
debugserver *:3333 -a TomatoTime,最後一個參數是可執行文件名或 pid。
此時被調試進程會被阻塞,等待 debugserver 的消息。如果正在調試 SpringBoard,則整個桌面都會卡住。在電腦命令行中執行 lldb,使用命令 process connect connect://192.168.1.107:3333 連接。如果連接成功會輸出:
在這裏插入圖片描述
使用 Wi-Fi 連接比較慢,可以用之前提到的 USB 轉發:執行 proxy 3333 3333,然後在 lldb 中執行 process connect connect://localhost:3333

一個超級大坑:按以上方法操作之後死活連不上,可能的原因是 debugserver 不支持 ipv6 地址,要在開啓調試服務時指定使用 ipv4 地址:debugserver 127.0.0.1:3333 -a TomatoTime,如果不用 iproxy 就需要將 127.0.0.1 修改爲電腦的地址。

調試

常用的調試命令及解釋如下。注意是在命令行中調試,不是 Xcode 內置的 lldb。

1.1 continue:繼續執行,簡寫 c
1.2 Control + C:暫停執行
1.3 s:step in
1.4 n:next

打斷點時注意,因爲地址空間隨機化的存在,真實的虛擬地址等於模塊被加載的基地址加上目標在模塊內的偏移地址。
2.1 image list -o -f [模塊名]:查看加載的各個[或指定]模塊的基地址和文件位置,簡寫 im li
2.2 print:打印任何內容,簡寫 p。對於數字,print/x 或 p/x 可以指定打印格式爲十六進制,經常用於:p/x 模塊基地址+函數偏移地址 獲得虛擬地址;打印對象時會打印所有屬性,print object 簡寫 po,可以簡潔地打印對象,一般調試只用 po;打印的內容還可以是寄存器、OC 函數等,例如 po $x0po [$x0 class],打印對象時如果對象實現了 description 方法則默認打印 description 方法的返回值。

3.1 breakpoint 0x12345678 或 breakpoint set -a 0x12345678:在某地址處打斷點,簡寫 b 或 br s -a,a 是 address 縮寫,-n 表示參數是函數名 name。
3.2 breakpoint disable [編號]或 enable,關閉或打開斷點,簡寫 br dis 或 en;列舉斷點 breakpoint list,都是可以按單詞舉一反三的。刪除 br del [編號]

4.1 register read x0 或 write x0 1:讀寫寄存器,簡寫 reg r 或 w
4.2 memory read 或 write:讀寫內存,打印當前棧的內容:memory read -force -f A $sp $fp;
4.3 x/5xg 0x1234:讀取參數地址處到內存。第一個 x 是讀內存,5g 是讀 5*8 個字節,第二個 x 是按十六進制顯示。
4.4 bt:打印函數調用棧,找到棧頂也就是調用者地址,image lookup -a 0x1234 得到地址所在模塊,此地址減去模塊基地址得到模塊內偏移,到 IDA 中按 G 跳轉到該偏移就得到了調用者函數。

5.1 finish:返回上層調用棧
5.2 thread return:不再執行下面代碼,直接從當前調用棧返回一個值
5.3 thread info:當前線程信息

6.1 help xxx:查看 xxx 命令的使用方式
6.2 apropos xx:查看關鍵字含 xx 的命令的使用方式

此外,可以在 ~/.lldbinit 文件中自定義命令別名。


下面的內容有機會再補充

用 LLDB 解密
用 Xcode 調試第三方應用
LLDB 高級調試技巧
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章