> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# TryHackMe Basic Malware RE (zh-TW)
- URL: https://taiwanding.com/tryhackme-basic-malware-re-zh-tw/
- Published: 2025-10-14T08:00:09.000Z
- Updated: 2026-07-15T02:49:58.000Z
- Author: Kevin Chen
- Tags: tryhackme, reverse

## 題目資訊

- **平台**: TryHackMe
- **房間名稱**: Basic Malware RE
- **分類**: Malware Analysis / Reverse Engineering
- **房間連結**: [https://tryhackme.com/room/basicmalwarere](https://tryhackme.com/room/basicmalwarere?ref=taiwanding.com)
- **難度**: 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: 基礎偵察

首先檢查檔案類型：

```bash
file strings1.exe_
# strings1.exe_: PE32 executable (GUI) Intel 80386, for MS Windows, 6 sections

md5sum strings1.exe_
# 76b58619d2834419e82e0f6a605c8811

```

### Step 2: 字串掃描（遇到陷阱）

```bash
strings strings1.exe_ | head -50

```

**發現**：

- ⚠️ 千個 `FLAG{...}` 格式的假 flag
- 可疑字串: `"We've been compromised!"`
- API 呼叫: `MessageBoxA`, `sprintf`, `%02x`

**陷阱識別**: 大量假 flag 是典型的**反分析技術**，用來混淆一般的字串方法。

### Step 3: Ghidra 反編譯分析

#### 3.1 導入與分析

1. 開啟 Ghidra，建立新專案
2. 導入 `strings1.exe_`
3. 執行自動分析（Analysis → Auto Analyze）

#### 3.2 定位 entry 函數

在 **Symbol Tree** → **Functions** 中找到 `entry` 函數：

```c
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);
}

```

**程式邏輯**：

1. 對某個字串呼叫 `md5_hash()` 函數
2. 將 MD5 結果透過 MessageBox 顯示
3. 標題是 `"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: 驗證答案

```bash
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` 函數：

```c
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: 驗證

```bash
echo -n "FLAG{Redacted}" | md5sum
# e80782d8c30671eb61acc63c5dca914e

```

### 為什麼這題反而更簡單？

原本的設計意圖  
根據 MalwareTech 的教學設計，strings2 應該讓學習者：

1. 查看**組合語言**中的 stack 操作
2. 手動解析每個 byte 的 hex 值
3. 將 hex 轉換成 ASCII 字元重建字串

原本應該看到類似這樣：

```assembly
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 工具驗證

```bash
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` 函數：

```c
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: 理解程式邏輯

**關鍵觀察**：

```c
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

1. 選單：**Window** → **Program Trees**
2. 展開，找到 `.rsrc` section
3. 雙擊進入 `.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: 驗證答案

```bash
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 分鐘         |