Ghidra 逆向實戰
STM32(ARM) MCU 韌體逆向工程
無符號表(Symbol-less)分析技巧


實作過程

說明與注意事項

本文默認讀者已安裝所有必要工具,如果還不熟悉,建議先參考以下文章:

Ghidra 逆向實戰|STM32(ARM) MCU 韌體逆向工程 : 工具說明

本實做將以 STM32H7A3 系列微控制器為範例,示範如何在 Ghidra 中進行無符號表(Symbol-less)韌體靜態分析,方法不分先後,依照實際需求與情況選擇適合的步驟進行。這些方法可協助使用者在缺乏符號表的情況下,仍能有效地進行韌體分析。

注意事項:

  • 本範例以 Ghidra 的靜態分析為主,不涉及動態調試或其他進階技術。
  • 本範例假設讀者已取得目標韌體的二進位檔,且該檔案未經加密或保護。
  • 本範例假設讀者具備更新目標裝置韌體的權限(能力)。
  • 本範例假設讀者明確知道目標韌體平台。
  • 本範例無法保證可在所有韌體或硬體平台上成功執行,實際結果可能因版本或架構而異。
  • 本範例僅供學術研究與學習用途,請勿用於任何非法用途。
  • 實際操作時,請務必遵循當地法律法規與相關道德準則。

尋找字串常數

在韌體中,字串常數(如 ASCII 或 Unicode 格式)常見於除錯訊息、錯誤提示、人機介面標示等。若編譯時未移除這些資訊,便能在韌體中直接找到相關字串。

這些字串對逆向工程極為有用,不僅能協助判斷韌體所用的架構或函式庫,還能快速定位程式碼中調用這些字串的位置,是分析流程的重要切入點。

Ghidra 操作:
可透過 Window → Defined Strings 功能,快速檢視與搜尋所有字串常數,並追蹤其被調用的程式區段。
Ghidra Defined Strings 訊息框
圖:Ghidra 的 Defined Strings 視窗,用於檢視和搜尋字串常數。

啟動入口與中斷向量表

在韌體中,啟動入口(如 Reset_Handler)與 中斷向量表 是韌體執行的起點。這些區域通常包含初始化程式碼、系統設定與中斷處理程式等。而這些位置的程式碼通常會在韌體啟動時被執行,因此可以作為分析的起點。

不同架構中斷向量表的位置與格式可能有所不同,但通常會包含一系列的函式指標,指向各種中斷服務程式(ISR)或系統呼叫。在 ARM Cortex-M 架構中,中斷向量表規定位於韌體開頭(例如 STM32 通常從 0x08000000 開始,這是由於重定向和偏移),格式如下:

                
Offset  內容
0x00    初始堆疊指標(Initial Stack Pointer)
0x04    Reset_Handler(重設處理函式)
0x08    NMI_Handler(不可屏蔽中斷)
0x0C    HardFault_Handler
0x10    MemManage_Handler
0x14    BusFault_Handler
0x18    UsageFault_Handler
...     其他中斷服務程式(ISR)指標
                
            

這些指標實際上是函式位址,Ghidra 可自動辨識並標註為函式。啟動時便是從 Reset_Handler 開始,追蹤其初始化流程與主程式流向。

Ghidra 操作:
  • 若有符號表,Ghidra 會自動辨識中斷向量表並標註為函式。
  • 若無符號表,可直接於程式開頭(通常為 Flash 起始位址,如 STM32 的 0x08000000)檢查指標。
  • 分析中斷向量表時,可參考 ARM 官方文件與晶片廠商提供的外設中斷表。

附註:

補充說明:
  • 由於中斷向量擺放位置相對固定,對應的 ISR 函數的標記也就相對容易,於是 ISR 通常會是逆向分析的起點。
  • 對於 ARM 架構而言,在剛開始分析時會先重點標記 Reset_HandlerSVCPendSVSysTick,因為這些 ISR 服務被用於 RTOS 的上下文切換、排程與任務。
  • 而一個程式到底是裸機程式還是 RTOS 程式,通常可以從這些 ISR 的邏輯與結構來判斷,並且這個判斷對後續的分析策略有直接影響。

標記中斷服務函數(ISR)

在 Ghidra 逆向韌體時,標記 ISR(中斷服務函數)是分析的重要一步,以下以 STM32/ARM MCU 為例,說明實際操作流程:

  1. 定位中斷向量表:
    開啟 Ghidra 程式碼視窗,跳至韌體開頭(通常是 Flash 起始位址,如 0x08000000)。檢查每 4 bytes 的指標。如果 Ghidra 沒有自動標記類數據類型,右鍵選擇 Data → Pointer 或使用快捷鍵 'p' 進行手動標記(請注意 Initial Stack Pointer 是 uintdword)。
  2. 建立函式:
    在中斷向量表中的每個函式指標上快點左鍵兩下跳轉到對應的程式碼位址。到達後,右鍵選擇 Function → Create Function,讓 Ghidra 將該位址標記為一個函式。 創建函數
  3. 命名與註解:
    依據 ARM 或晶片手冊,對應每個向量表項目,右鍵點擊已建立的函式名稱,選擇 Edit Function,輸入正確的函式名稱(如 Reset_HandlerSysTick_Handler 等),並可加上註解說明其用途。
    Ghidra 編輯函數選項 Ghidra 函數名稱編輯介面
    圖:在 Ghidra 中編輯函式名稱和屬性。
  4. 檢查與追蹤:
    點擊已標記的 ISR 函式名稱,使用 Window → Function GraphWindow → Function Call Tree,分析其內部邏輯與呼叫關係。
  5. 輔助工具:
    可搭配 Window → Symbol Tree 快速檢查所有已建立的函式,或用 Window → Defined Strings 搜尋相關字串輔助判斷。
小技巧:
  • 若 Ghidra 未自動辨識向量表,可手動於每個指標位址建立函式。
  • 部分 ISR 可能未實作(弱定義),在 Ghidra 中可能顯示為空函式或跳轉到一個無限迴圈,可直接略過或標註為空函式。
  • 建議優先標記 SVCPendSVSysTick 這三個與 RTOS 核心功能高度相關的 ISR。
Ghidra 標記 ISR 示意圖
圖:Ghidra 標記中斷向量表和 ISR 函式的示意。

判斷韌體架構:裸機或 RTOS

即便沒有符號表,依然可從程式流與常數變數中進行逆向工程判斷。韌體架構主要分為 裸機(Bare-metal)RTOS(即時作業系統) 兩大類型。此判斷將直接影響後續的分析策略。

裸機(Bare-metal)特徵

  • 主流程通常集中於 main() 函式,初始化後進入明顯的大型無限迴圈(如 while(1))。
  • 中斷服務程式(ISR)邏輯簡單,僅處理基本事件,無複雜排程或上下文切換。
  • 很少或沒有多執行緒、任務管理、排程等結構。
  • Reset Handler 初始化後,主流程持續執行,不會很快結束。

RTOS(即時作業系統)特徵

  • 初始化後會建立多個 Thread/Task,主流程很快結束或進入空迴圈(等待排程)。
  • 中斷服務程式(如 SVCPendSVSysTick)包含複雜控制流程,負責上下文切換與任務排程。
  • 指針的大量運用 (callback、Thread 建立、事件通知、ISR 與 Thread 間通訊等)。
  • 常見直接操作 0xE000ED04 (此位址為 ARM 架構專用的中斷控制暫存器 ICSR)觸發 PendSV 中斷,或強制「軟體內」觸發計時器等外設中斷。
  • 常數區可能出現 FreeRTOSRTXThreadX 等關鍵字,可大概率判定 RTOS 類型。
  • 常數區可能出現 KernelThreadtaskQueue 等關鍵字,可判定存在 RTOS。

快速判斷方法(依可靠度排序):

生成 BinDiff 用參考檔案

當完成基本架構分析後,利用 BinDiff 這類二進位比對工具,搭配官方 HAL 層範例程式碼 或已知韌體版本,建立「參考檔案」進行比對。

具體步驟如下:

  1. 先從 MCU 官方範例HAL/LL 驅動程式 取得對應版本的原始碼,並以相同編譯器與設定編譯出 bin/elf 檔。
  2. 將參考檔案與目標韌體載入 Ghidra,利用 BinExport 外掛將兩者匯出為 BinDiff 可讀取的格式。
  3. 使用 BinDiff 工具載入匯出的檔案,進行函式比對。
  4. 比對結果可協助快速標記出標準函式、外設驅動、RTOS 相關 API,顯著提升逆向效率。
  5. 若比對結果函式相似度高,通常可直接複製參考檔案的符號名稱與註解,大幅減少手動分析時間。
Ghidra 操作:
  • 於 Ghidra 安裝 BinExport 外掛 (BinDiff 通常是獨立工具)。
  • 匯入參考檔案與目標韌體,分別進行分析。
  • 使用 File → Export Program,選擇 BinExport 格式,匯出兩個檔案。
  • 打開 BinDiff 工具,載入這兩個匯出的檔案進行比對。
  • 依比對結果,手動或利用腳本批次標記 Ghidra 中的函式名稱與註解,加速後續分析。
  • 前面的分析出的架構越準確這步能獲得的訊息越多。
HAL 驅動程式 BinDiff 比對範例 HAL 驅動程式 flashdb 比對範例
左為HAL庫,右為 flashdb
搜尋常數區關鍵字圖示
RTOS 比較