LLDB是Low Level Debugger的簡稱,在iOS開發的調試中LLDB是常用的,LLDB是Xcode內置的動態調試工具。使用LLDB能夠動態的調試你的應用程序,若是你不作其餘的額外處理,由於debugserver缺乏task_for_pid權限,因此你只能使用LLDB來調試你本身的App。那麼本篇博客中就要使用LLDB來調試從AppStore下載安裝的App,而且結合着Hopper來分析第三方App內部的結構。LLDB與Hopper的結合,會讓你看到不同的東西,本篇博客就會和你一塊兒領略LLDB與Hopper的魅力。html
以前咱們ssh鏈接iOS設備是經過局域網也就是WiFi來鏈接的,當網絡環境很差的時候輸入個命令行都卡,因此咱們須要一種更快的訪問iOS設備的方式,那就是使用USB鏈接了。本篇博客中不管是SSH鏈接iOS設備仍是LLDB鏈接iOS設備,咱們都使用USB的方式進行設備的訪問,這樣速度就快的不行不行的了。本篇博客的第一部分就是介紹如何使用USB進行設備的SSH鏈接,這部分也是本篇博客的基礎,不過內容還算是簡單。python
usbmuxd雖然目前最新的版本是1.1.0,可是1.1.0版本和1.0.9版本僅支持Linux系統,也就是說咱們的Mac仍是得下載v1.0.8的版本,下載地址(usbmuxd-v1.0.8)。下載完後,將下載的文件進行解壓,內容以下所示:git
切換到上述文件夾下的python-client目錄下,執行下方的命令,將iOS上的22端口轉發到當前設備的2221端口,以下所示。算法
./tcprelay.py -t 22:2221spring
下方是執行上述命令的結果:安全
ssh root@localhost -p 2222服務器
上述命令就是ssh鏈接的命令 -p後邊緊跟的是上述轉發的端口,執行上述命令後,結果以下:微信
使用usbmuxd就能夠經過USB來鏈接咱們的iOS越獄設備了,下方的LLDB鏈接iOS設備也是經過USB鏈接的。具體請看下文。網絡
在作iOS開發時,在Mac上輸入LLDB的命令就能夠控制iOS端的App,是由於在咱們iOS客戶端中有一個debugserver服務器。debugserver專門用來鏈接Mac端的LLDB客戶端,接收LLDB所提供的命令,而且進行相應的執行。若是你的iOS設備進行過真機調試的話,設備中就會被安裝上debugserver, 不過該debugserver只能用來調試你本身的相關應用。若是想要調試從AppStore中獲取的App的話,那麼咱們須要對iOS設備上的debugserver進行處理。該部分就是要處理咱們的debugserver。架構
首先咱們得找到iOS設備中debugserver,並將其拷貝到Mac上進行處理,下方就是位於/Developer/usr/bin目錄下的debugserver。此debugserver只支持調試咱們本身的App, 若是須要調試其餘人的App的話,須要對此debugserver進行處理,處理過程見下文。
lipo -thin arm64 debugserver -output debugserver
進入到到Mac中debugserver所在的目錄下執行上述命令便可,-thin後方填寫你的測試機相應的ARM架構便可,由於個人測試機是iPhone 6 Plus, 是arm64的架構,因此此處填的參數是arm64, 若是你的是iPhone5的設備,那麼就是armv7s了。
給debugserver添加task_for_pid權限後,咱們就可使用LLDB調試其餘App了。此部分咱們須要一個存儲配置信息的xml文件,該文件的內容以下。你能夠將下下方的文本進行拷貝,而後存儲成ent.xml便可。
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.springboard.debugapplications</key> <true/> <key>get-task-allow</key> <true/> <key>task_for_pid-allow</key> <true/> <key>run-unsigned-code</key> <true/> </dict> </plist>
在給debugserver符權限時,咱們須要使用到ldid命令,若是你的Mac上沒有安裝ldid命令,那麼請用brew進行install。執行下方的命令行就能夠給咱們的debugserver賦上task_for_pid權限。須要注意的是-S與ent.xml文件名中是沒有空格的。
ldid -Sent.xml debugserver
下方截圖就是咱們處理debugserver的步驟,以下所示:
最後一步就是將處理好的debugserver拷貝到咱們的越獄設備中,而且給debugserver賦上可執行的權限。由於/Developer/usr/bin目錄下的debugserver是隻讀的,因此你不能將處理好的debugserver拷貝到上述文件,你要將處理好的debugserver拷貝到/usr/bin/目錄下(固然此處咱們藉助IFunBox進行文件的拷貝)。
將debugserver拷貝到/usr/bin目錄下後,執行下方的賦權限的命令,將可執行的權限賦給debugserver,以下所示:
chmod +x debugserver
賦完權限後,你就可使用debugserver命令來開啓debuserver了,以下所示:
在越獄設備中,咱們就能夠經過下方命令行來開啓debugserver了,咱們此處以調試微信App爲例。下方的命令就是啓動debugserver來監聽來自任何IP地址的接入,iOS設備的接入端口是12345,所要調試的App爲「WeChat」。命令以下:
debugserver *:12345 -a "WeChat"
在咱們iOS設備上執行上述命令的效果以下所示,執行完上述命令後,咱們的iOS設備就會等待Mac終端LLDB的接入。
LLDB鏈接debugserver可使用WIFI進行鏈接,但是WIFI是不穩定的,並且特別的慢,因此此處咱們要使用usbmuxd進行LLDB和debugserver的鏈接。
和第一部分中的內容相同,咱們使用usbmuxd進行端口的轉發,將上述的「12345」端口對接到Mac本地的某個端口,此處咱們使用「12345」端口。進入到usbmuxd-1.0.8目錄下的python-client下執行下方的命令。
./tcprelay.py -t 12345:12345
具體操做步驟以下所示:
進行端口轉發後,接下來咱們就開始進入lldb模式,而後進行debugserver的鏈接了。首先在terminal上輸入lldb命令,而後輸入下方的地址進行鏈接。由於咱們使用usbmuxd進行了端口的轉發,所以可使用本地的環回測試地址來進行debugserver的鏈接。
process connect connect://127.0.0.1:12345
下方是鏈接後的結果,LLDB與debugserver創建完成後,咱們就可使用lldb來調試微信這個應用了。
在上篇博客《iOS逆向工程之給WeChat脫殼》 咱們已經給微信進行可脫殼處理,因此使用Hopper進行處理是沒有問題的。此部分咱們就要將Hopper與LLDB結合在一塊兒發揮其雙劍合璧的做用。該部分也算是本篇博客中實戰的一部分。
LLDB鏈接上debugserver後,咱們首先使用下方的命令來查看當前進程中的全部模塊。從這些輸出信息中咱們能找到「WeChat」這個進程在虛擬內存相對於模塊基地址的偏移量。
image list -o -f
lldb鏈接debugserver後,執行上述命令輸出的部分結果以下所示。下方截圖中,第一個就是「WeChat」程序的相關信息。左邊紅框就是ASLR偏移量(隨機偏移量),ASLR偏移量其實就是虛擬內存的地址相對於模塊基地址的偏移量。右邊紅框中的地址就是偏移後的地址。
在介紹地址這塊的東西是先熟悉一下下方的兩個概念:
從下方的輸出結果咱們能夠知道:ASLR偏移量 = 0x5b000, 模塊偏移後基地址 = 0x5f000
下方是使用Hopper打開的解密後的微信的安裝包,其起始地址從下圖中咱們能夠看出是0x4000, 這個地址就是模塊偏移前的地址,也就是模塊在虛擬內存中的起始地址。從Hopper中咱們能夠知道:模塊偏移前的基地址=0x4000
從上面兩組數據咱們能夠得出:
模塊偏移後的基地址(0x5f000)= ASLR偏移量(0x5b000)+ 模塊偏移前基地址(0x4000)
上面這個公式是尤其重要的,由於Hopper中顯示的都是「 模塊偏移前基地址」,而LLDB要操做的都是「模塊偏移後的基地址」。因此從Hopper到LLDB,咱們要作一個地址偏移量的轉換。這個在下方會屢次用到。固然,有一點須要注意的是Hopper與LLDB所選擇的AMR架構的位數得一致,要麼是32位,要麼都是64位,若是位數不匹配的話,那麼計算出來的內存地址確定是不對的。
「斷點」這個東西在iOS開發中可謂是常用的東西,接下來咱們要作的就是給在微信點擊登陸進行頁面跳轉時添加一個斷點。就是點擊左邊截圖的登陸按鈕往右邊頁面跳轉時添加一個斷點。咱們暫且將斷點添加在右邊頁面的初始化方法中。
要給上述右邊頁面添加斷點首先得知道上面「手機號登陸」視圖控制器的內存地址,而後纔可使用LLDB添加斷點。那麼尋找上述視圖控制器的內存地址的任務就交給了咱們的Hopper來作了。在Hopper中咱們搜索「Login」,而後會篩選出好的帶有Login關鍵字的ViewController,而後咱們在篩選的結果中再次尋找可疑目標對象。而後咱們找到了一個名爲「WCAccountPhoneLoginControlLogic」(咱們能夠翻譯一下英文,大概意思就是「微信手機帳號登陸控制邏輯」)的類,從這個類的名字中咱們不難推斷出該類極有可能就是咱們要尋找的「手機帳號登陸」頁面。
通過上述分析後,咱們決定要給該類的「initWithData」(這確定是個初始化方法)使用LLDB添加斷點。
通過第一步找到添加斷點的類中的方法後,接下來咱們要計算出該方法的內存地址,而後使用LLDB給該地址添加斷點。經過Hopper咱們很容易定位到上述的「initWithData:」方法,的位置,以下所示。下方截圖中這個帶「星號」的地址就是「initWithData:」方法偏移前的基地址。根據上面的公式咱們很容易就能夠計算出該方法「偏移後的基地址」也就是真正的內存地址。算法以下所示:
initWithData內存地址 = 0x1304b60 + 0x5b000(ALSR偏移) = 0x135FB60
使用下述命令,給上述地址添加斷點。斷點添加後,點擊登陸按鈕就會跳轉到「手機號登陸」頁面就會執行該斷點,下方截圖的紅框中就是「斷點」執行後的效果。從下方截圖中咱們能夠看出該斷點的編號是1,Breakpoint後方就是斷點編號,該編號會在操做斷點是會用到,下方會給出實例。
br s -a 0x135FB60
你能夠經過nexti (簡寫:ni)和stepi (簡寫:si)來進行單步的調試。ni遇到跳轉不會進入到跳轉中去,而si則會跳轉到相應的分支中去。下方就是經過si和ni進行單步調試的效果截圖。
命令c能夠執行該斷點, 上面這種狀況若是執行c命令,由於只有一個斷點,該斷點執行後,就會跳轉到「手機號登錄頁面」。
上面也有提到,上述建立的斷點的編號是1,咱們要對該斷點進行禁用和開啓操做,具體命令以下所示:
br dis 1 -- 禁用(disable)編號爲1的斷點
br en 1 -- 啓用(enable)編號爲1的斷點
br dis -- 禁用全部斷點
br en -- 啓用全部斷點
具體操做結果以下, 當斷點禁用後,點擊登陸按鈕就不會觸發該斷點了。當斷點重啓後,點擊登陸按鈕仍是會觸發該斷點的。具體效果以下所示:
br del 1 -- 刪除(delete)編號爲1的斷點
br del -- 刪除全部斷點
在iOS開發中,咱們在使用LLDB調試時,常常會用到po命令來輸出某個變量或者常量的值。在使用LLDB調試WeChat時,咱們也可使用某些命令來輸出寄存器中的值。咱們使用$來訪問某個寄存器中的值,而且使用p命令進行打印。下方就是經過p命令將r1寄存器中所存的內容進行打印,在打印以前將$r1進行類型轉換,po命令則輸出了Objective-C的對象,而p輸出的是C語言類型的數據。以下所示:
咱們還能夠將一個地址所存放的值進行打印,下方這個命令就是輸出了$sp指針所指的地址處所存放的值:
p/x $sp
4.修改寄存器中的值
咱們不只能夠查看某些寄存器中的值,並且可修改寄存器中的中,經過下述命令咱們就能夠修改指的寄存器中的值。
register write 寄存器 值
接下來咱們將要經過一個實例來實戰一下register write這個命令,經過在Hopper中對登陸模塊的分析,咱們不難發現「WCAccountManualAuthControlLogic」這個類中的「handleAuthResponse:」方法就是用來處理「登陸認證響應」的方法。也就是說「handleAuthResponse:」負責處理登陸業務邏輯的網絡響應,而且在這個函數的前邊有一個比較(cmp r0, r1), 根據r0和r1的比較結果來進行跳轉。
接下來咱們要作的事情就是,在比較寄存器r0和r1中的值時咱們要改變r1寄存器中的值,而後觀察App的運行效果。下方這個截圖是隨便輸入手機號和密碼時所提示的內容。也就是正常的流程會彈出下方的框。
接下來咱們要作的就是給0x1063a24 + 0x5b000 = 0x10BEA24 (cmp)這個內存地址添加斷點,而後去修改寄存器r1的值。下方截圖就是給0x10BEA24這個內存址添加了斷點,而且在輸入手機號和密碼後,點擊登陸會執行咱們添加的斷點,以下所示。在斷點出咱們清楚的看到了cmp r0, r1這行ARM指令。
接下來咱們先將r0和r1中的值進行打印,$r0 = 8, $r1 = 351。而後咱們將$r1中的值改爲8,而後輸入c繼續執行,發現以前正常流程的alter就不會彈出來了,而是從新進行了一次網絡請求。
上述示例都是在32位系統上作的,若是你使用的是arm64架構的設備,如iPhone6Plus,那麼你的地址會比上述地址要長一倍。下方兩個截圖是使用iPhone 6 Plus越獄設備作實驗的截圖,能夠和上述步驟進行一下對比,雖然有所不一樣,可是上述內容在調試下方內容時也是適用的。
本篇博客的內容就到這兒吧,至此,你應該能將LLDB與Hopper結合起來使用了吧。今天咱們以「微信」爲例子,並無別的意思,只是想在真正的實例中實現一下。使用微信作實驗的緣由就是微信作的足夠安全,畢竟微信的團隊仍是很強大的。由於用個人越獄設備作完上述實驗後,該越獄設備已經不能登陸微信帳號了,確定是微信的後臺監測到該「越獄設備」的異常行爲了,從而作了一些安全措施。
「攻與防」就像「矛與盾」相輔相成。