當前位置:
首頁 > 新聞 > 使用Ghidra對iOS應用進行msgSend分析

使用Ghidra對iOS應用進行msgSend分析

背景

之前在《使用IDA Pro的REobjc模塊逆向Objective-C二進位文件》一文中,我們提到了在使用IDA Pro分析iOS應用的過程中,由於Objective-C語言的動態特性,大部分的方法調用都是通過調用_objc_msgSend方法加上實際調用方法名作為參數的方式進行,以至於在IDA Pro分析完成後,在交叉引用列表中缺失了許多原本應該存在的引用記錄。

DUO Labs的Todd Manning開發了一款IDA Pro的腳本,可以幫助逆向研究者更全面地獲取交叉引用的信息。可惜的是,這款腳本僅面向x64平台,所以如果我們分析的是iOS應用,這款工具只能補全針對模擬器編譯的應用包,對於實際情況下的逆向工作還是有許多的限制。

在今年三月份舉辦的2019年RSA大會上,美國國家安全局(NSA)公開介紹並演示了一款名為Ghidra的逆向工程框架,並且將Ghidra作為開源工具開放給了大眾使用。由於其為java編寫的特點,所以可以跨平台使用,並且支持多種CPU架構。Ghidra可以對主流操作系統的二進位文件進行分析,包括Android和iOS。同時,用戶可以使用開放的API介面開發自己的Ghidra插件組件或腳本。對於這樣一款功能強大並且是開源的逆向工具,我們也第一時間將其使用到了日常逆向工作中。

初步分析

我們搭建了一個iOS的測試工程,選擇真機設備進行編譯,使其編譯後的應用包為arm64的CPU架構,然後拖入Ghidra和IDA Pro進行分析。

我們創建了一個名為Lion的類,在其中創建一個名為lionFirstMethod的方法。然後在ViewController類的method1方法中使用[lion lionFirstMethod]的方式進行調用。同時,我們在Lion類的lionSecondMethodWithArg1: andArg2:方法中使用同樣的方式進行調用。通過之前的研究我們可以知道,這些方法調用實際上都是通過_objc_msgSend的方式進行調用。我們在IDA Pro和Ghidra中針對lionFirstMethod及其交叉引用信息進行分析,結果發現:

在IDA Pro中,僅分析出了lionSecondMethodWithArg1: andArg2:方法中的調用。

在Ghidra中,不僅分析出了lionSecondMethodWithArg1: andArg2:方法中的調用,而且還分析出了另外一處method1中的調用。

這不禁引起了我們的注意和興趣,經過分析我們發現,Ghidra解析出了測試工程中大部分的_objc_msgSend調用,而IDA Pro只解析出了一部分。

解析_objc_msgSend

對於逆向工程來說,準確並全面的交叉引用信息尤為重要,它可以幫助我們分析某個關鍵函數在二進位文件中是否被調用以及如何被調用。基於這點,我們開始研究在Ghidra中編寫Python腳本來分析所有的_objc_msgSend方法,試圖解析出實際調用的類和方法名。

首先我們需要找出_objc_msgSend,於是我們遍歷可執行文件中所有的方法,在每個方法中遍歷arm指令,如果遇到bl指令,判斷其是否是_objc_msgSend。由於在bl指令調用_objc_msgSend方法前,處理器會讀取內存數據,向寄存器中寫入類、方法名和參數信息,所以如果是_objc_msgSend,我們就可以按地址往前尋找ldr指令。

上面是一個非常簡單的例子,這裡可以看到,程序在地址0x100006134處調用了_objc_msgSend,而此處實際調用的方法是[Lion alloc]。我們按地址往前尋找,可以看到在0x100006128和0x10000612c處都使用了ldr指令從內存中讀取了數據寫入了寄存器。根據arm的ABI文檔,我們可以知道,在函數調用時,前幾個寄存器會被用來存放函數的參數。所以對於沒有參數的[Lion alloc]來說,Lion和alloc便是_objc_msgSend函數的兩個參數,我們也可以在arm指令中看出,在bl指令調用_objc_msgSend之前,指向類Lion和方法alloc的引用分別被寫入了X0和X1寄存器。

在找到ldr指令後,我們可以分析ldr指令對應的操作數,如果對應到的是一個引用,就可以提取其引用信息。通過遞歸跟蹤其引用地址,可以分析出其最終指向的內容。如果指向的內容是類名,那我們就找到了此次_objc_msgSend調用對應的類信息,如果指向的內容是方法名,那我們就找到了此次_objc_msgSend調用對應的方法信息。以此,我們就可以拼湊出該_objc_msgSend對應的實際方法調用。

完善腳本

在編寫腳本的過程中,我們發現,ldr指令中對應的操作數,其最終指向的內容多為__objc_methname和__objc_classname段中的數據。因此,我們在真正開始分析之前,先要解析這兩個段中的數據並保存起來,以便解析_objc_msgSend的時候可以快速地對映到相關類名和方法名。

此外,由於Ghidra在初始分析完成之後,交叉引用信息已經比較完善,並且在大部分的_objc_msgSend調用處都已經添加了對應分析完成的注釋,所以我們可以將這兩類信息一併加以分析並輔助我們的分析結果。

腳本編寫完成後可以發現,通過腳本解析的_objc_msgSend的類名和方法名與Ghidra分析的類名和方法名一致。

此外,由於Objective-C動態的特性,有一些諸如」performSelector」這樣的反射方法。我們編寫腳本的時候也考慮到了這個特點,如果分析得到的方法名為performSelector,我們會追加分析其參數,以便解析出真正的調用方法。

在腳本編寫完成後,我們嘗試在測試工程中運行腳本。共解析出93處交叉引用,其中通過腳本補全了其中的18處。相同的測試工程在IDA Pro分析後僅解析出交叉引用共14處。

目前該腳本已經在Github上開源:https://github.com/PAGalaxyLab/ghidra_scripts/blob/master/AnalyzeOCMsgSend.py

參考及來源:

http://galaxylab.com.cn/使用ida-pro的reobjc模塊逆向objective-c二進位文件/

作者:銀河安全實驗室 姜若芾

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

CVE-2019-0708漏洞:RDP=Really DO Patch?