iOS逆向工程之Hopper+LLDB調試第三方App

来源:http://www.cnblogs.com/ludashi/archive/2016/09/21/5730338.html
-Advertisement-
Play Games

LLDB是Low Level Debugger的簡稱,在iOS開發的調試中LLDB是經常使用的,LLDB是Xcode內置的動態調試工具。使用LLDB可以動態的調試你的應用程式,如果你不做其他的額外處理,因為debugserver缺少task_for_pid許可權,所以你只能使用LLDB來調試你自己的A ...


LLDBLow Level Debugger的簡稱,在iOS開發的調試中LLDB是經常使用的,LLDB是Xcode內置的動態調試工具。使用LLDB可以動態的調試你的應用程式,如果你不做其他的額外處理,因為debugserver缺少task_for_pid許可權,所以你只能使用LLDB來調試你自己的App。那麼本篇博客中就要使用LLDB來調試從AppStore下載安裝的App,並且結合著Hopper來分析第三方App內部的結構。LLDB與Hopper的結合,會讓你看到不一樣的東西,本篇博客就會和你一起領略LLDB與Hopper的魅力。

 

一、SSH的USB連接--usbmuxd

之前我們ssh連接iOS設備是通過區域網也就是WiFi來連接的,當網路環境不好的時候輸入個命令行都卡,所以我們需要一種更快的訪問iOS設備的方式,那就是使用USB連接了。本篇博客中無論是SSH連接iOS設備還是LLDB連接iOS設備,我們都使用USB的方式進行設備的訪問,這樣速度就快的不行不行的了。本篇博客的第一部分就是介紹如何使用USB進行設備的SSH連接,這部分也是本篇博客的基礎,不過內容還算是簡單。

1、獲取usbmuxd

usbmuxd雖然目前最新的版本是1.1.0,但是1.1.0版本和1.0.9版本僅支持Linux系統,也就是說我們的Mac還是得下載v1.0.8的版本,下載地址(usbmuxd-v1.0.8)。下載完後,將下載的文件進行解壓,內容如下所示:

  

 

2.使用usbmuxd連接iOS越獄設備

(1) 使用usbmuxd轉發介面

切換到上述文件夾下的python-client目錄下,執行下方的命令,將iOS上的22埠轉發到當前設備的2221埠,如下所示。

./tcprelay.py -t 22:2221

下方是執行上述命令的結果:

  

 

(2) 使用ssh連接到越獄設備

ssh root@localhost -p 2222

上述命令就是ssh連接的命令 -p後邊緊跟的是上述轉發的埠,執行上述命令後,結果如下:

  

 使用usbmuxd就可以通過USB來連接我們的iOS越獄設備了,下方的LLDB連接iOS設備也是通過USB連接的。具體請看下文。

 

二、配置debugserver

在做iOS開發時,在Mac上輸入LLDB的命令就可以控制iOS端的App,是因為在我們iOS客戶端中有一個debugserver伺服器。debugserver專門用來連接Mac端的LLDB客戶端,接收LLDB所提供的命令,並且進行相應的執行。如果你的iOS設備進行過真機調試的話,設備中就會被安裝上debugserver, 不過該debugserver只能用來調試你自己的相關應用。如果想要調試從AppStore中獲取的App的話,那麼我們需要對iOS設備上的debugserver進行處理。該部分就是要處理我們的debugserver。

1.獲取debugserver

首先我們得找到iOS設備中debugserver,並將其拷貝到Mac上進行處理,下方就是位於/Developer/usr/bin目錄下的debugserver。此debugserver只支持調試我們自己的App, 如果需要調試其他人的App的話,需要對此debugserver進行處理,處理過程見下文。

  

 

2.對debugserver進行瘦身

lipo -thin arm64 debugserver -output debugserver

進入到到Mac中debugserver所在的目錄下執行上述命令即可,-thin後方填寫你的測試機相應的ARM架構即可,因為我的測試機是iPhone 6 Plus, 是arm64的架構,所以此處填的參數是arm64, 如果你的是iPhone5的設備,那麼就是armv7s了。

 

3.給debugserver添加task_for_pid許可權

給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的步驟,如下所示:

  

 

4、將debugserver拷貝到iOS設備中

最後一步就是將處理好的debugserver拷貝到我們的越獄設備中,並且給debugserver賦上可執行的許可權。因為/Developer/usr/bin目錄下的debugserver是只讀的,所以你不能將處理好的debugserver拷貝到上述文件,你要將處理好的debugserver拷貝到/usr/bin/目錄下(當然此處我們藉助IFunBox進行文件的拷貝)。

將debugserver拷貝到/usr/bin目錄下後,執行下方的賦許可權的命令,將可執行的許可權賦給debugserver,如下所示:

chmod +x debugserver

賦完許可權後,你就可以使用debugserver命令來開啟debuserver了,如下所示:

  

 

三、debugserver的開啟與LLDB的連接

1.開啟debugserver

在越獄設備中,我們就可以通過下方命令行來開啟debugserver了,我們此處以調試微信App為例。下方的命令就是啟動debugserver來監聽來自任何IP地址的接入,iOS設備的接入埠是12345,所要調試的App為“WeChat”。命令如下:

debugserver *:12345 -a "WeChat"

在我們iOS設備上執行上述命令的效果如下所示,執行完上述命令後,我們的iOS設備就會等待Mac終端LLDB的接入。

  

 

2.LLDB連接debugserver

LLDB連接debugserver可以使用WIFI進行連接,可是WIFI是不穩定的,而且特別的慢,所以此處我們要使用usbmuxd進行LLDB和debugserver的連接。

(1)進行埠的轉發

和第一部分中的內容相同,我們使用usbmuxd進行埠的轉發,將上述的“12345”埠對接到Mac本地的某個埠,此處我們使用“12345”埠。進入到usbmuxd-1.0.8目錄下的python-client下執行下方的命令。

./tcprelay.py -t 12345:12345

具體操作步驟如下所示:

 

(2)Mac端LLDB的接入

進行埠轉發後,接下來我們就開始進入lldb模式,然後進行debugserver的連接了。首先在terminal上輸入lldb命令,然後輸入下方的地址進行連接。因為我們使用usbmuxd進行了埠的轉發,因此可以使用本地的環回測試地址來進行debugserver的連接。

process connect connect://127.0.0.1:12345

下方是連接後的結果,LLDB與debugserver建立完成後,我們就可以使用lldb來調試微信這個應用了。

 

四、Hopper + LLDB

在上篇博客《iOS逆向工程之給WeChat脫殼》 我們已經給微信進行可脫殼處理,所以使用Hopper進行處理是沒有問題的。此部分我們就要將Hopper與LLDB結合在一起發揮其雙劍合璧的作用。該部分也算是本篇博客中實戰的一部分。

1.查看線程中的WeChat

LLDB連接上debugserver後,我們首先使用下方的命令來查看當前進程中的所有模塊。從這些輸出信息中我們能找到“WeChat”這個進程在虛擬記憶體相對於模塊基地址的偏移量。

image list -o -f

lldb連接debugserver後,執行上述命令輸出的部分結果如下所示。下方截圖中,第一個就是“WeChat”程式的相關信息。左邊紅框就是ASLR偏移量(隨機偏移量),ASLR偏移量其實就是虛擬記憶體的其實地址,相對於模塊基地址的偏移量。右邊紅框中的地址就是偏移後的地址。

在介紹地址這塊的東西是先熟悉一下下方的兩個概念:

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

從下方的輸出結果我們可以知道:ASLR偏移量 = 0x5b000, 模塊偏移後基地址 = 0x5f000

  

 

下方是使用Hopper打開的解密後的微信的安裝包,其起始地址從下圖中我們可以看出是0x4000, 這個地址就是模塊偏移前的地址,也就是模塊在虛擬記憶體中的起始地址。從Hopper中我們可以知道:模塊偏移前的基地址=0x4000

  

從上面兩組數據我們可以得出:

  模塊偏移後的基地址(0x5f000)= ASLR偏移量(0x5b000)+ 模塊偏移前基地址(0x4000)

上面這個公式是尤為重要的,因為Hopper中顯示的都是“ 模塊偏移前基地址”,而LLDB要操作的都是“模塊偏移後的基地址”。所以從Hopper到LLDB,我們要做一個地址偏移量的轉換。這個在下方會多次用到。當然,有一點需要註意的是Hopper與LLDB所選擇的AMR架構的位數得一致,要麼是32位,要麼都是64位,如果位數不匹配的話,那麼計算出來的記憶體地址肯定是不對的

 

2、使用LLDB給微信登錄添加斷點

(1)、加斷點前的分析

“斷點”這個東西在iOS開發中可謂是經常使用的東西,接下來我們要做的就是給在微信點擊登錄進行頁面跳轉時添加一個斷點。就是點擊左邊截圖的登錄按鈕往右邊頁面跳轉時添加一個斷點。我們暫且將斷點添加在右邊頁面的初始化方法中。

  

 

要給上述右邊頁面添加斷點首先得知道上面“手機號登錄”視圖控制器的記憶體地址,然後才可以使用LLDB添加斷點。那麼尋找上述視圖控制器的記憶體地址的任務就交給了我們的Hopper來做了。在Hopper中我們搜索“Login”,然後會篩選出好的帶有Login關鍵字的ViewController,然後我們在篩選的結果中再次尋找可疑目標對象。然後我們找到了一個名為“WCAccountPhoneLoginControlLogic”(我們可以翻譯一下英文,大概意思就是“微信手機賬號登錄控制邏輯”)的類,從這個類的名字中我們不難推斷出該類極有可能就是我們要尋找的“手機賬號登錄”頁面。

  

經過上述分析後,我們決定要給該類的“initWithData”(這肯定是個初始化方法)使用LLDB添加斷點。

 

(2)、定位斷點地址

經過第一步找到添加斷點的類中的方法後,接下來我們要計算出該方法的記憶體地址,然後使用LLDB給該地址添加斷點。通過Hopper我們很容易定位到上述的“initWithData:”方法,的位置,如下所示。下方截圖中這個帶“星號”的地址就是“initWithData:”方法偏移前的基地址。根據上面的公式我們很容易就可以計算出該方法“偏移後的基地址”也就是真正的記憶體地址。演算法如下所示:

initWithData記憶體地址 = 0x1304b60 + 0x5b000(ALSR偏移) = 0x135FB60

  

 

(3)、添加斷點

使用下述命令,給上述地址添加斷點。斷點添加後,點擊登錄按鈕就會跳轉到“手機號登錄”頁面就會執行該斷點,下方截圖的紅框中就是“斷點”執行後的效果。從下方截圖中我們可以看出該斷點的編號是1,Breakpoint後方就是斷點編號,該編號會在操作斷點是會用到,下方會給出實例

br s -a 0x135FB60

  

 

(4)、斷點的單步執行(ni, si)

你可以通過nexti (簡寫:ni)stepi (簡寫:si)來進行單步的調試。ni遇到跳轉不會進入到跳轉中去,而si則會跳轉到相應的分支中去。下方就是通過si和ni進行單步調試的效果截圖。

  

 

(5) 放開執行該斷點(c)

命令c可以執行該斷點, 上面這種情況如果執行c命令,因為只有一個斷點,該斷點執行後,就會跳轉到“手機號登陸頁面”。

 

(6)斷點的禁用和開啟

上面也有提到,上述創建的斷點的編號是1,我們要對該斷點進行禁用和開啟操作,具體命令如下所示:

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

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

br dis  -- 禁用所有斷點

br en  -- 啟用所有斷點

具體操作結果如下, 當斷點禁用後,點擊登錄按鈕就不會觸發該斷點了。當斷點重啟後,點擊登錄按鈕還是會觸發該斷點的。具體效果如下所示:

  

 

(7) 斷點的刪除

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

br del  -- 刪除所有斷點

 

3.輸出寄存器的值(p, po)

在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結合起來使用了吧。今天我們以“微信”為例子,並沒有別的意思,只是想在真正的實例中實現一下。使用微信做實驗的原因就是微信做的足夠安全,畢竟微信的團隊還是很強大的。因為用我的越獄設備做完上述實驗後,該越獄設備已經不能登錄微信賬號了,肯定是微信的後臺監測到該“越獄設備”的異常行為了,從而做了一些安全措施。

攻與防”就像“矛與盾”相輔相成。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 記錄狀態欄和導航欄的設置和控制,統一在基類視圖控制器中完成。 狀態欄。 狀態欄高度為20,iOS7以後背景完全透明。 樣式枚舉如下: typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault = 0, // Dark ...
  • 1、ApkTool工具 安裝ApkTool工具,該工具可以解碼得到資源文件,但不能得到Java源文件。安裝環境:需要安裝JRE1.61> 到http://code.google.com/p/android-apktool/ 下載apktool1.3.2.tar.bz2 和apktool-instal ...
  • 今天發的是TabHost結合ViewPager實現首頁底部導航的效果,雖然說網上有很多這樣的Demo,不過呢,我還是要把自己練習寫的發出來,沒錯!就是這麼任性; 先上效果圖,如下: 代碼裡面有註釋,就不過多解釋了,說幾點需要註意的問題 1:TabHost 、TabWidget、FrameLayout ...
  • 接著第一章的繼續 昨天沒有更新,很抱歉 1、Socket編程 以及一些第三方框架Socket-IO GCDAsyncSocket通信框架? 1、使用系統自帶的CFsocket 2、第三方Socket-IO 3、GCDAsyncSocket 想要瞭解更多 請看http://www.jianshu.co ...
  • 1.使用List集合方式 用list保存activity實例,然後逐一干掉 在需要退出程式的時候,調用: 簡而言之,通過單例模式把每個Activity 的引用添加到一個全局鏈表中,每次退出程式調用System.exit(0)時,先調用鏈表中Activity 的finish方法 優點:實現簡單,邏輯清 ...
  • 先看效果圖: 1概述 Activity啟動方式有四種,分別是: standard singleTop singleTask singleInstance 可以根據實際的需求為Activity設置對應的啟動模式,從而可以避免創建大量重覆的Activity等問題。 設置Activity的啟動模式,只需要 ...
  • 首先,十分感謝下麵諸位大神,通過你們的分享讓我解決了實際的問題,也學到了豐富的知識。 這些大神都是我平時在解決問題時,在百度搜索發現的,被他們技術知識所吸引,就收藏了起來。 以下排名不分先後,以後會慢慢對各位大神的博客做分析,以便大家能良好的利用。 iOS大神 封神榜 polobymulberry ...
  • Android4.4之前: 在4.4中會報許可權異常 Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=2269, uid=20016那是因為Android4.4中 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...