TryHackMe Basic Malware RE (zh-TW)
題目資訊
- 平台: TryHackMe
- 房間名稱: Basic Malware RE
- 分類: Malware Analysis / Reverse Engineering
- 房間連結: https://tryhackme.com/room/basicmalwarere
- 難度: Easy
- ZIP 密碼: MalwareTech
- 學習目標: 靜態惡意軟體分析基礎
- 備註: 這些壓縮檔真的都有病毒,Windows會自動刪除,不管是執行strings、file查看,所以可以先暫時把掃毒關掉,如果單純只對reverse有興趣,還沒有要往Malware Analysis,有疑慮也可以先略過這題喔!
前言
這個房間包含三個挑戰(strings1, strings2, strings3),旨在教授靜態分析技術。所有題目都有一個共同點:
- 程式執行時會計算某個字串的 MD5 hash 並顯示
- 我們的任務是不執行程式,用逆向工程工具找出那個原始字串(flag)
重要原則: 👉 Never run the executable! 這是惡意軟體分析的黃金法則,如果真的需要,也建議在沙盒或是虛擬機跑,避免感染電腦。
工具準備
必備工具
- Ghidra: 免費開源的反編譯工具 (https://ghidra-sre.org/)
- strings: Linux 內建的字串提取工具
- md5sum: 驗證答案用
環境建議
- Linux 虛擬機(Kali, Ubuntu 等)
- 或 Windows + WSL
- 隔離環境(不要在主系統分析惡意軟體樣本)
Challenge 1: strings1.exe
題目描述
This executable prints an MD5 Hash on the screen when executed. Can you grab the exact flag? Note: You don't need to run the executable!
解題過程
Step 1: 基礎偵察
首先檢查檔案類型:
file strings1.exe_
# strings1.exe_: PE32 executable (GUI) Intel 80386, for MS Windows, 6 sections
md5sum strings1.exe_
# 76b58619d2834419e82e0f6a605c8811
Step 2: 字串掃描(遇到陷阱)
strings strings1.exe_ | head -50
發現:
- ⚠️ 千個
FLAG{...}格式的假 flag - 可疑字串:
"We've been compromised!" - API 呼叫:
MessageBoxA,sprintf,%02x
陷阱識別: 大量假 flag 是典型的反分析技術,用來混淆一般的字串方法。
Step 3: Ghidra 反編譯分析
3.1 導入與分析
- 開啟 Ghidra,建立新專案
- 導入
strings1.exe_ - 執行自動分析(Analysis → Auto Analyze)
3.2 定位 entry 函數
在 Symbol Tree → Functions 中找到 entry 函數:
void entry(void)
{
char *lpText;
lpText = md5_hash(PTR_s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00432294);
MessageBoxA((HWND)0x0, lpText, "We've been compromised!", 0x30);
ExitProcess(0);
}
程式邏輯:
- 對某個字串呼叫
md5_hash()函數 - 將 MD5 結果透過 MessageBox 顯示
- 標題是
"We've been compromised!"← 不是被 hash 的內容!
3.3 追蹤指標鏈(關鍵步驟)
第一次跳轉 - 雙擊 PTR_s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00432294:
PTR_s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00432294 XREF[1]: entry:004022b4(R)
00432294 28 48 42 00 addr s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00424828
= "FLAG{CAN-I-MAKE-IT-ANYMORE-OB"
→ 這是個指標,指向地址 0x00424828
第二次跳轉 - 雙擊 s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00424828:
s_FLAG{CAN-I-MAKE-IT-ANYMORE-OBVIO_00424828 XREF[2]: entry:004022b9(*), 00432294(*)
00424828 46 4c 41 ds "FLAG{Redacted}"
47 7b 43
41 4e 2d
🎯 找到真正的 flag!
Step 4: 驗證答案
echo -n "FLAG{Redacted}" | md5sum
# 4c827c4ca62781d707cd049da13539ee
程式行為圖解
┌────────────────────────────────────────────┐
│ entry() │
│ │
│ 1. 讀取指標 0x00432294 │
│ └→ 指向 0x00424828 │
│ └→ "FLAG{CAN-I-MAKE-IT-ANYMORE- │
│ OBVIOUS}" │
│ │
│ 2. 計算 MD5 │
│ └→ 4c827c4ca62781d707cd049da13539ee │
│ │
│ 3. 顯示在 MessageBox │
│ Title: "We've been compromised!" │
│ Text: (MD5 hash) │
└────────────────────────────────────────────┘
Flag
FLAG{Redacted}
MD5: 4c827c4ca62781d707cd049da13539ee
學習重點
🎯 反分析技術識別
- 大量假 flag: 用來混淆 strings 工具
- 多層指標: 真正資料藏在指標的指標後面
- 誤導性字串: MessageBox 標題看似重要,實際是煙霧彈
Challenge 2: strings2.exe
題目描述
與 strings1 相同,找出被計算 MD5 的原始字串。
解題過程
Step 1: Ghidra 反編譯
直接用 Ghidra 打開 strings2.exe,找到 entry 函數:
void entry(void)
{
char local_2c [36];
char *local_8;
builtin_strncpy(local_2c, "FLAG{STACK-STRINGS-ARE-BEST-STRINGS}", 0x24);
local_8 = md5_hash(local_2c);
MessageBoxA((HWND)0x0, local_8, "We've been compromised!", 0x30);
ExitProcess(0);
}
🎯 直接看到完整 flag! 比 strings1 還簡單!
Step 2: 驗證
echo -n "FLAG{Redacted}" | md5sum
# e80782d8c30671eb61acc63c5dca914e
為什麼這題反而更簡單?
原本的設計意圖
根據 MalwareTech 的教學設計,strings2 應該讓學習者:
- 查看組合語言中的 stack 操作
- 手動解析每個 byte 的 hex 值
- 將 hex 轉換成 ASCII 字元重建字串
原本應該看到類似這樣:
mov BYTE PTR [ebp-0x2c], 0x46 ; 'F'
mov BYTE PTR [ebp-0x2b], 0x4c ; 'L'
mov BYTE PTR [ebp-0x2a], 0x41 ; 'A'
mov BYTE PTR [ebp-0x29], 0x47 ; 'G'
; ... 更多逐字元賦值
但 Ghidra 太聰明了!
Ghidra 的反編譯器識別出這是 strncpy 操作,直接顯示完整字串,所以這題變成最簡單的!
strings 工具驗證
strings strings2.exe_ | grep "STACK"
# (沒有結果)
❌ 找不到!因為字串是動態建構在堆疊上,不存在於靜態資料區段。
技術對比
| 特性 | strings1 | strings2 |
|---|---|---|
| 儲存位置 | .rdata (靜態) |
Stack (動態) |
| strings 可見 | ✅ (混在假 flag 中) | ❌ 完全不可見 |
| Ghidra 難度 | 需追蹤 2 層指標 | 直接顯示 |
| 隱藏技術 | 大量假 flag | Stack strings |
Flag
FLAG{Redacted}
MD5: e80782d8c30671eb61acc63c5dca914e
學習重點
🎯 Stack Strings 技術
- 定義: 在執行時動態在堆疊上建構字串,而非硬編碼在資料區段
- 目的: 躲避
strings等靜態掃描工具 - 偵測: 必須透過反編譯或反組譯才能發現
🤔 Flag 的幽默
"STACK-STRINGS-ARE-BEST-STRINGS" 意思是「堆疊字串是最好的字串」——因為它們能有效躲避簡單的靜態分析!
Challenge 3: strings3.exe
題目描述
與前兩題相同,找出被計算 MD5 的原始字串。
解題過程
Step 1: Ghidra 反編譯
用 Ghidra 打開 strings3.exe,找到 entry 函數:
void entry(void)
{
CHAR local_4a4;
undefined1 local_4a3 [1027];
char *local_a0;
MD5 local_9c [144];
HRSRC local_c;
undefined4 local_8;
MD5::MD5(local_9c);
local_4a4 = '\0';
memset(local_4a3, 0, 0x3ff);
// 尋找資源
local_c = FindResourceA((HMODULE)0x0, "rc.rc", &DAT_00000006);
// 載入 String ID = 0x110 (272) 的字串資源
local_8 = 0x110;
LoadStringA((HINSTANCE)0x0, 0x110, &local_4a4, 0x3ff);
// 計算 MD5
local_a0 = MD5::digestString(local_9c, &local_4a4);
MessageBoxA((HWND)0x0, local_a0, "We've been compromised!", 0x30);
ExitProcess(0);
}
Step 2: 理解程式邏輯
關鍵觀察:
LoadStringA((HINSTANCE)0x0, 0x110, &local_4a4, 0x3ff);
- 程式使用 Windows API
LoadStringA() - 從資源表載入 String ID = 0x110 (十進制 272) 的字串
- 這個字串被存儲在 PE 檔案的 Resource Section (.rsrc)
Step 3: 在 Ghidra 中定位資源
3.1 開啟 Program Trees
- 選單:Window → Program Trees
- 展開,找到
.rsrcsection - 雙擊進入
.rsrc
3.2 瀏覽 String Tables
在 Listing 視窗中,你會看到類似這樣的結構:
**************************************************************
* Rsrc_StringTable_8_409 Size of resource: 0x55c bytes *
**************************************************************
Rsrc_StringTable_9_409
00408xxx ... p_unicode u"FLAG{...}" Rsrc String ID 128
00408xxx ... p_unicode u"FLAG{...}" Rsrc String ID 129
...
3.3 找到 String ID 272
Windows String Resource 結構:
- 每個 String Table 包含 16 個字串
- String ID 272 = 17 × 16
- 所以在 Rsrc_StringTable_12_409 (0x11 = 17)
找到的內容:
Rsrc_StringTable_12_409 XREF[1]: entry:004022ff(*)
0040aef0 27 00 46 p_unicode u"FLAG{Redacted}"
00 4c 00 Rsrc String ID 272
41 00 47
🎯 找到 flag!
Step 4: 驗證答案
echo -n "FLAG{Redacted}" | md5sum
# 1011cafbd736cdf2ae90964613c911fe
Windows PE 資源表基礎
什麼是 Resource Section?
PE 檔案的 .rsrc 區段可以儲存:
- 🖼️ 圖示 (Icons)
- 📝 字串表 (String Tables)
- 🎵 音效檔
- 📋 對話框定義
- 🗂️ 任意二進制資料 (RCDATA)
為什麼要用 Resource Section?
正常用途:
- 多語言支援(不同語言的字串)
- 分離 UI 資源與程式邏輯
- 方便資源管理與更新
Flag
FLAG{Redacted}
MD5: 1011cafbd736cdf2ae90964613c911fe
學習重點
🎯 Resource Hiding 技術
- 定義: 將敏感資料存放在 PE 資源表中
- 目的: 躲避靜態掃描,支援模組化設計
- 偵測: 需要專門的 PE 分析工具
🤔 Flag 的幽默
"RESOURCES-ARE-POPULAR-FOR-MALWARE" 意思是「資源表在惡意軟體中很受歡迎」——這句話本身就在教你真實的攻擊技術!
經驗分享
技術對比表
| 特性 | strings1 | strings2 | strings3 |
|---|---|---|---|
| 儲存位置 | .rdata (靜態資料) |
Stack (堆疊) | .rsrc (資源表) |
strings 可見性 |
✅ 可見(但有混淆) | ❌ 不可見 | ❌ 不可見 |
| Ghidra 難度 | ⭐⭐ 需追蹤指標 | ⭐ 直接顯示 | ⭐⭐ 需查資源表 |
| 反混淆技術 | 4000+ 假 flag | Stack strings | Resource hiding |
| 真實案例 | 靜態嵌入配置 | API hashing | 多語言/模組化惡意軟體 |
| 完成時間 | ~15 分鐘 | ~5 分鐘 | ~10 分鐘 |
Member discussion