Jump to content

4.研究Xtensa架構特性現在我們已經將所有段加載到適當的地址,我們可以開始逆向工程了。

但為了高效地做到這一點,我們需要更多地了解Xtensa 架構,包括:

1.指令中的參數順序

2.條件跳轉的執行細節

3.編譯器調用約定

4.堆棧組織

首先要探索的是指令中的參數順序。例如:MOV R1, R2.您可以在所有架構中找到此類指令,但這可能意味著將R1 複製到R2 或將R2 複製到R1。因此,了解指令中源代碼的位置以及目標寄存器的位置至關重要。您可以在GitHub 上找到Xtensa 指令集描述。

至於該MOV指令,在Xtensa中,表示將R2複製到R1。因此,第一個參數將是大多數簡單指令(例如數學相關指令)中的目的地。例如,指令addi a14, a1,0x38意味著a14=a1 +0x38。

但對於存儲數據的指令,情況則相反。例如,該指令s32i.n a5, a1,0x10意味著的值a5必須存儲在地址處(a1 +0x10)。

要學習的第二件事是條件跳轉的完成方式。有兩種方法可以做到這一點:

1.使用專用指令進行比較操作,設置標誌寄存器,然後進行條件跳轉。

2.使用一條指令一次性執行所有這些操作。

Xtensa 執行後者:beqz a10, loc_400E1C54

使用單個指令來檢查是否a10等於零,然後它要么跳轉到loc_400E1C54,要么不跳轉。

第三步是檢查編譯器使用的調用約定:將參數傳遞給函數的方式以及如何返回值。

Xtensa 以一種非常不尋常的方式傳遞參數。參數在調用指令之前放入寄存器中。但它們在函數中出現的寄存器與調用之前所在的寄存器不同:

image.png

以下是如何在彙編程序級別將參數傳遞給函數的示例:

image.png

這裡我們有三個論據:

a10 是目的地址

a11 是源地址

a12 是要復印的尺寸

然而,一旦代碼進入memcpy函數,這些值就會自動分別傳輸到a2、a3和a4寄存器中。

同樣的技巧也用於返回值。在memcpy函數內部,該值存儲在寄存器中a2,但從函數返回後,該值出現在a10.

返回的樣子如下0:

image.png

這就是檢查返回值的樣子:

image.png

benz.na10在從調用返回時檢查寄存器的值。

最後,有必要了解堆棧是如何組織的。

Xtensa 使用a1 寄存器來創建堆棧幀。每個函數都以入口指令開始:entry a1,0xC0,其中0xC0是堆棧幀的大小,即函數需要用於堆棧變量的堆棧量。

通常,這些函數從初始化堆棧變量開始:

image.png

寄存器中的零值a5被寫入基於a1寄存器的堆棧變量中。

在獲得有關Xtensa 架構的所有必要知識後,我們終於可以開始逆向其代碼了。

5. 在IDA 中對Xtensa 代碼進行逆向工程與ARM、MIPS 和PowerPC 相比,Xtensa 不是最流行的架構,並且沒有完整的功能列表。因此,IDA處理器模塊會存在一些我們需要克服的限制。

IDA 中Xtensa 處理器模塊的主要限制是:

函數參數沒有自動註釋

堆棧幀不會自動創建

一些ESP32 函數屬於IROM,因此存在對硬編碼地址的調用

部分Xtensa指令未反彙編

讓我們討論一些克服這些挑戰的技巧。

5.1.函數參數的類型系統和註釋從IDA 7.7 開始提供Xtensa類型系統。在IDA 中擁有可用的類型系統非常重要,因為它使逆向變得方便。特別是,它允許您導入C 結構的定義並指定IDA 使用的函數原型,以便在傳輸函數參數的指令附近放置自動註釋。

但是,如果您沒有類型系統,還有一個解決方法。

首先,讓我們看看有類型系統時函數是什麼樣子的:

image.png

屏幕截圖13. 當有可用的類型系統時函數的外觀

函數原型設置有參數的名稱和類型,以便IDA 可以使用此信息在調用站點註釋參數:

image.png

屏幕截圖14. 函數原型

但Xtensa 不會有這樣的事情。另一種方法是使用IDA 中的可重複註釋功能。如果您在函數的開頭設置可重複的註釋,它將顯示在所有調用站點上。

image.png

屏幕截圖15. 設置可重複註釋

image.png

屏幕截圖16. 可重複的註釋顯示在所有調用站點上

因此,我們可以使用此功能來定義函數參數:

image.png

屏幕截圖17. 使用可重複註釋功能定義函數參數

調用站點將如下所示:

image.png

屏幕截圖18. 調用站點

您可以在註釋中選擇寄存器名稱,IDA 會在代碼中突出顯示它。因此,您可以輕鬆找到參數值。

5.2.恢復堆棧幀要恢復堆棧幀,您需要手動指定堆棧大小,然後通過在每個與堆棧一起使用的指令處按K 鍵來顯示IDA 的使用位置。

讓我們探索一下config_router_safe函數,例如:

image.png

屏幕截圖19. config_router_safe 函數

很明顯這裡的棧幀大小是0xC0。我們在函數的堆棧設置中使用該值(Alt+P):

image.png

屏幕截圖20. 使用0xC0 值(堆棧幀大小)

從視覺上看,什麼也不會發生,但是如果您通過按Ctrl+K 轉到該函數的堆棧幀,您會注意到堆棧空間現在已分配:

image.png

屏幕截圖21. 分配堆棧空間

接下來要做的是使用entry指令指定堆棧移位。在此之前,我們建議啟用堆棧指針可視化,如下面的屏幕截圖所示:

image.png

屏幕截圖22. 啟用堆棧指針可視化

現在,代碼應該如下所示:

image.png

屏幕截圖23.啟用堆棧指針可視化後的代碼

000是當前堆棧指針移位值,我們需要將其移位0xC0。為此,請將光標置於入口指令處,然後按Alt+K以查看以下窗口,您可以在其中指定新舊堆棧指針之間所需的差異:

image.png

屏幕截圖24. 將當前堆棧指針值移動0xC0

作為此操作的結果,代碼將如下所示:

image.png

屏幕截圖25. 移動當前堆棧指針移位值後的代碼

現在,如果您開始在與寄存器一起使用的每條指令處按Ka1,IDA 將創建堆棧變量:

image.png

屏幕截圖26.IDA 創建新的堆棧變量

還可以編寫IDA 腳本來自動執行這些操作。

5.3.調用IROM調用位於CPU 的IROM 部分而不是固件中的某些低級API 的情況並不少見。在這種情況下,固件僅與包含定義的IROM 函數地址的特殊鏈接器定義文件鏈接。

在逆向期間,IROM 函數調用如下所示:

image.png

屏幕截圖27. IROM 函數調用

40058E4C是IROM 內的地址。但不可能知道固件調用了哪個函數。因此有必要檢查ESP32 工具鏈以查找鏈接器定義。

ESP32 芯片的IDE 是Espressif IDE。在IDE 文件中搜索IROM 地址,我們會找到:C:\Espressif\frameworks\esp-idf-v4.4.2\components\esptool_py\esptool\flasher_stub\ld\rom_32.ld

image.png

屏幕截圖28. ESP32 ROM 地址表

這些值可以輕鬆轉換為枚舉數據類型:

image.png

屏幕截圖29. 將值轉換為枚舉數據類型

然後,我們需要導入IDA,以便將enum 應用於IROM 地址值:

image.png

屏幕截圖30. 將枚舉應用於IROM 地址值

如果我們在IROM 地址附近添加可重複的註釋,它將使所有內容更容易閱讀:

image.png

屏幕截圖31. 在IROM地址附近添加可重複註釋後的代碼

5.4.無法識別的指令經常發生的情況是,處理器模塊已針對指令集的某些特定變體實現。然後製造商製造出具有99% 兼容指令集的新CPU,其中包含10 多個新指令,這是最初沒人想到的。因此IDA、Ghidra和Radare等工具可能無法反彙編一些新指令。

克服這一挑戰的正確方法是擴展處理器模塊並添加對新指令的支持。這需要對反彙編器API 有深入的了解,而這些API 並不那麼容易理解。

讓我們討論一種可能的解決方法,用於解決以下情況:儘管存在一些無法識別的指令,但您只想讓IDA 創建函數。假設IDA 不知道RER 指令,並且在包含RER 操作碼的情況下無法創建該函數:

image.png

屏幕截圖32. 如果函數包含RER 操作碼,IDA 無法創建該函數

您可以按P多次。除了控制台窗口中出現錯誤外,不會發生任何事情:

image.png

屏幕截圖33. 控制台窗口中的錯誤

但是,這並不意味著IDA 無法創建遵循RER 指令的指令。您可以跳過RER 指令的三個字節,然後創建代碼:

image.png

屏幕截圖34. 跳過RER 指令的三個字節後創建代碼

接下來,您可以選擇從輸入到最後的整段代碼retw.n,然後按P:

image.png

屏幕截圖35. 選擇從Entry 到retw.n 的整段代碼

之後,IDA 將創建該函數:

image.png

屏幕截圖36.IDA 創建一個函數

通常,反彙編程序無法識別的擴展指令在逆向過程中不會產生太大差異。可能導致問題的是執行調用、跳轉或加載/存儲等操作的新指令,因為代碼流丟失並且對數據的引用丟失。

結論對於涉及逆向工程物聯網固件的項目來說,在轉向業務邏輯之前研究未知的硬件架構至關重要。儘管逆向工程師可能需要幾週的時間來學習該架構,但從長遠來看,這種深入的研究有助於提高進一步工作的速度。

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...