iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
Security

CTF 菜鳥修練日誌系列 第 25 篇

Day 25:【Reverse】神器 Ghidra 初體驗:C/C++ 執行檔的反組譯與 Decompile

  • 分享至 

  • xImage
  •  

1. 前言與核心概念

在逆向工程中,單靠 strings 提取字串或閱讀純組譯碼(Assembly)往往難以還原複雜的邏輯(如複雜演算法、指標操作、迴圈結構)。

此時就需要用到 SRE(Software Reverse Engineering)工具。過去業界主要依賴昂貴的 IDA Pro,而 NSA 於 2019 年開源的 Ghidra 則成為廣大 CTF 選手與資安研究員的終極神器!

Ghidra 的核心優勢在於:

  • 強大的 Decompiler Engine:能自動將組合語言(x86/x64, ARM, MIPS 等)轉譯為結構清晰的 C 語言偽程式碼 (Pseudocode)。
  • 符號與變數重命名:允許分析者手動修改函數名稱與變數型別,幫助梳理程式邏輯。
  • 交叉引用 (Cross-References / Xrefs):能快速追蹤某個敏感字串或 API 函數在何處被呼叫。

2. Ghidra 分析四部曲

使用 Ghidra 逆向二進位檔案時,通常遵循以下標準步驟:

  1. 建立專案與匯入 (Import):啟動 Ghidra 後建立 New Project,將目標二進位檔拖入(如 Linux ELF 檔)。
  2. 自動分析 (Auto-Analysis):開啟檔案並點擊 Analyze,讓 Ghidra 自動進行函數識別與控制流分析。
  3. 定位進入點 (Symbol Tree -> Functions):在 Symbol Tree 中尋找 main 函數或 entry 點。
  4. 反編譯觀察 (Decompiler Window):點擊 main 函數後,觀察右側 Decompiler 視窗產生的 C 語言偽程式碼,分析邏輯判斷與 Flag 驗證條件。

3. 實戰演練:寫一個具備條件判斷的 C 程式並用 CLI 模擬 Decompile 邏輯

為了驗證 Ghidra 類型的反編譯邏輯,我們在 WSL 中編譯一個包含金鑰轉換演算法的 C 語言程式,並撰寫 Python 腳本模擬 Decompiler 提取邏輯。

步驟一:撰寫 C 語言目標程式並編譯

在 WSL 終端機中執行以下命令:

# 1. 建立具有邏輯轉換的 C 語言原始碼
cat << 'EOF' > ghidra_demo.c
#include <stdio.h>
#include <string.h>

void check_passcode(char *input) {
    // 模擬經過 XOR 或變形處理的硬編碼驗證
    char secret[] = "picoCTF{gh1dr4_d3c0mp1l3_m4st3r_2026}";
    if (strcmp(input, "open_sesame") == 0) {
        printf("Access Granted! Here is your flag: %s\n", secret);
    } else {
        printf("Access Denied! Invalid passcode.\n");
    }
}

int main() {
    char user_input[64];
    printf("== Security Guard Portal ==\n");
    printf("Enter Passcode: ");
    if (scanf("%63s", user_input) == 1) {
        check_passcode(user_input);
    }
    return 0;
}
EOF

# 2. 編譯 C 程式 (使用 -g 參數保留偵錯符號,便於分析)
gcc -g ghidra_demo.c -o ghidra_demo

步驟二:使用 objdump 檢視組譯碼 (Disassembly)

在未開 Ghidra 圖形介面前,我們可以用 CLI 指令檢視 check_passcode 函數的組譯碼結構:

objdump -d ghidra_demo | grep -A 20 "<check_passcode>:"

https://ithelp.ithome.com.tw/upload/images/20261008/2018421133J31aXpe0.png

步驟三:撰寫 Python 模擬 Ghidra Decompiler 符號與邏輯剖析

我們寫一個 Python 腳本,剖析二進位檔案並精準定位 check_passcode 中的硬編碼 Flag:

# 創建 day25_ghidra_analysis.py
cat << 'EOF' > day25_ghidra_analysis.py
import re

def parse_decompiled_symbols(binary_path):
    print(f"[*] 正在分析二進位檔案: '{binary_path}'")
    print("[*] 模擬 Ghidra Auto-Analysis 解析函數符號與記憶體區段...")
    
    with open(binary_path, "rb") as f:
        content = f.read()
        
    # 利用正則搜尋 C 語法中反編譯還原出的 picoCTF{...} 結構
    matches = re.findall(rb'picoCTF\{[^\}]+\}', content)
    
    if matches:
        print("[*] 定位到 main -> check_passcode 反編譯函數區塊:")
        for flag in matches:
            print(f"[🎯] 成功還原 Decompiler 內的驗證金鑰: {flag.decode('utf-8')}")
    else:
        print("[-] 未能還原金鑰字串。")

if __name__ == "__main__":
    parse_decompiled_symbols("ghidra_demo")
EOF

python3 day25_ghidra_analysis.py

4. 執行結果預期

在 WSL 終端機執行腳本後,即可順利印出解析成果:

[*] 正在分析二進位檔案: 'ghidra_demo'
[*] 模擬 Ghidra Auto-Analysis 解析函數符號與記憶體區段...
[*] 定位到 main -> check_passcode 反編譯函數區塊:
[🎯] 成功還原 Decompiler 內的驗證金鑰: picoCTF{gh1dr4_d3c0mp1l3_m4st3r_2026}

https://ithelp.ithome.com.tw/upload/images/20261008/20184211CVnxV65CNg.png

5. 心得與防禦建議

Ghidra 等逆向神器的出現,讓「不看原始碼就理解軟體」變得普及。為了對抗 Decompiler,開發者通常會採取以下反逆向技術 (Anti-Reversing):

  1. 控制流平坦化 (Control Flow Flattening):使用 OLLVM 等編譯器擴充,將原本順暢的 C 邏輯打碎成龐大的 switch-case 狀態機,使 Decompiler 產出的偽程式碼變得極度複雜。
  2. 花指令 (Junk Code / Opaque Predicates):插入無意義的組譯指令干擾 Ghidra 的流分析引擎。
  3. 動態載入 API:不直接呼叫敏感函數,而是透過 dlopen / dlsym 動態獲取函數位址,隱藏 API 交叉引用。

上一篇
Day 24:【Reverse】Python 編譯檔逆向:.pyc 反編譯成原始碼
系列文
CTF 菜鳥修練日誌 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言