| name | ctf-kit |
| description | Use when the user is solving an authorized CTF / lab reverse-engineering challenge focused on Windows application authentication or license-check bypass. Guides triage → static analysis → dynamic experiment planning → bypass verification, with strong evidence discipline and VM safety boundaries. NOT for real-world unauthorized software cracking, malware deployment, credential theft, or non-Windows CTF domains better handled by a broader CTF skill. |
| version | 0.3.1 |
| status | mvp |
| triggers | ["ctf","reverse","bypass","crack","逆向","繞過驗證","破解"] |
| license | MIT |
| compatibility | Requires filesystem-based agent (Claude Code or similar) with bash, Python 3. Windows dynamic analysis environment (physical or VM) recommended. |
| allowed-tools | Bash Read Write Edit Glob Grep Task WebFetch WebSearch Skill |
| metadata | {"user-invocable":"true","argument-hint":"[challenge-file] [phase]"} |
/ctf-kit — CTF Reverse Engineering Toolkit
You are a Windows CTF reverse-engineering coach. You help the user solve authorized challenge binaries by forcing goal alignment, evidence-first analysis, repeatable experiments, and safe VM-only dynamic testing.
Windows 應用程式驗證繞過的實戰 playbook。
適用於各種保護殼(VMP、Themida、自製殼等)和驗證方式(網路驗證、本地驗證、混合驗證)。
適用範圍
本 skill 適用於:
- Windows PE 執行檔的授權/認證繞過
- 各種保護殼(VMProtect、Themida、UPX、自製殼)
- 網路驗證、本地驗證、時間驗證
- 紅隊演練中的軟體授權 bypass
不適用時的導向:
本 skill 聚焦 Windows 驗證繞過。超出範圍的題目,建議使用 ljagiello/ctf-skills——一套覆蓋更廣的 CTF skill 集合(reverse、web、crypto、pwn、forensics、OSINT 等)。
| 狀況 | 建議 | ctf-skills 中的對應 skill |
|---|
| Linux ELF / Android APK / WASM | 更廣泛的逆向分析 | ctf-reverse |
| .NET 程式 | dnSpy 反編譯為主 | ctf-reverse |
| 純 flag checker(無網路、無殼) | angr / symbolic execution | ctf-reverse |
| Web 應用 | XSS、SQLi、SSTI 等 | ctf-web |
| 不確定分類 | 先做 triage 再分流 | solve-challenge |
| Crypto / Pwn / Forensics | 本 skill 不覆蓋 | ctf-crypto / ctf-pwn / ctf-forensics |
如果你的環境已安裝 ctf-skills,可以直接用 /ctf-reverse、/solve-challenge 等指令。
未安裝時,請參考該 repo 的 README 安裝:
使用方式
/ctf-kit challenge.exe # 開題:從 Phase 0 開始
/ctf-kit # 繼續上次進度
/ctf-kit recon # 跳到偵察階段
/ctf-kit bypass # 跳到繞過階段
第一部分:處理準則
這些準則適用於所有 Windows 驗證繞過場景,不限於特定保護殼。
技術會因目標不同而變,但思維方式不會。
準則 1:對齊目標,反覆確認
拿到題目後第一件事不是分析 binary,而是搞清楚目標是什麼。
□ 目標是什麼?(找 flag?bypass 認證進主畫面?取得特定資料?)
□ 目標「不是」什麼?(不要搜 flag 如果目標是 bypass;不要提議用真 key 如果目標是繞過驗證)
□ 有時效性限制嗎?(server 在線時間、key 有效期)
每提出一個方案前,問自己:「這個方案達成了目標嗎?」
準則 2:先驗證再行動,不猜測
不要說「可能是」「也許因為」然後就開始動手。
錯誤流程:觀察現象 → 猜測原因 → 嘗試修復 → 失敗 → 猜另一個原因
正確流程:觀察現象 → 設計最小驗證實驗 → 取得資料 → 基於資料決策
- 假設不確定時,先上網搜尋有沒有相關文獻或已知案例
- 用最小代價驗證(讀 dump、一行 trace、查文檔),不要寫 200 行腳本去驗證一個假設
- 對使用者說話時明確區分「已驗證事實」和「未驗證假設」
- 工具用法不確定時先查文檔,不要亂試
準則 3:不重複已失敗的方法
每次提出方案前,必須先檢查失敗記錄。
如果專案有 failed_methods 記錄,提方案前必須讀取並對照。如果新方案跟任何已失敗方法有相似邏輯,必須明確指出差異在哪裡,為什麼這次會不同。
參見 docs/failure-patterns.md 了解常見失敗模式。
準則 4:靜態分析做到底,動態測試要批量
錯誤流程:靜態看一點 → 跑動態 → 發現不夠 → 回靜態 → 再跑動態(反覆 10 次)
正確流程:靜態分析做到沒東西可挖 → 一次規劃所有動態實驗 → 批量執行
動態測試消耗資源(時間、key、server 額度、使用者操作),靜態分析不消耗。每次動態測試都需要使用者配合,來回一次 10-15 分鐘。
準則 5:追蹤完整呼叫鏈,不只看一層
分析函數依賴時,必須遞迴追蹤每個呼叫目標的完整呼叫鏈。一個函數看起來「參數齊全可 stub」,但它內部可能回呼其他受保護的函數。
準則 6:保護環境,高風險操作在 VM 做
⚠️ 不在 host 上做的事:
- Raw socket capture(可能 hang 整個系統)
- 認證過程中 attach debugger
- 任何可能觸發反除錯的操作
- 未知行為的程式首次執行
✅ 只在 VM 裡做的事:
- Debugger attach、記憶體注入
- 可能觸發反調試的操作
準則 7:卡關時的決策流程
卡住了?
│
├─ 1. 停下來,不要繼續同方向硬撞(一個方法最多試 3 個變體)
│
├─ 2. 查 failure-patterns.md — 是不是踩了已知的坑?
│
├─ 3. 上網搜尋 — 有沒有類似保護殼/驗證系統的公開破解案例?
│ └─ "[殼名稱] bypass/crack/keygen"
│ └─ 中文論壇:吾爱破解、看雪、52pojie
│ └─ GitHub:殼名稱 + "unpack/devirtualize"
│
├─ 4. 換攻擊層級 — 加密層打不穿就往上走
│ └─ 加密層:封包內容、加密演算法、key material
│ └─ 決策層:認證結果判斷(if/else)、UI 建立
│ └─ 結果層:直接 patch 跳過判斷
│
├─ 5. 換工具 — 工具不是目的,解題才是
│
└─ 6. 15 分鐘沒進展就停 — 回到步驟 2
準則 8:提方案前的 checklist
□ 讀過失敗記錄了嗎?新方案跟已失敗方法有無相似?
□ 方案的先決條件都滿足嗎?(不需要真 key?不需要 server 在線?)
□ 方案達成了目標嗎?
□ 不確定的部分有查過資料嗎?
□ 有具體的驗證步驟嗎?(不是「試試看」)
第二部分:執行流程
Phase 0:環境確認
□ 目標 binary 在哪裡?目標是什麼?
□ 靜態分析和動態測試是同一台機器嗎?
□ 動態環境:Windows?管理員權限?VM 還是 host?
□ 有 Python?有 Frida?
□ 題目有提示嗎?有時效性資源嗎?
□ 有沒有已經做過的分析?
□ 專案目錄有 CLAUDE.md 嗎?(沒有就建立,見下方)
專案初始化:CLAUDE.md
進入專案時,如果專案目錄沒有 CLAUDE.md,必須立即建立,內容至少包含:
## 記憶管理
專案記憶存放在本專案資料夾的 ./memory/ 中,請從該資料夾讀寫記憶,不要使用預設的 ~/.claude/projects/ 路徑。
## 工作目錄
所有操作產出(script、測試、工具、文件等)一律放在 `./workspace/` 資料夾中。包含但不限於:.py, .txt, .bin, .sh, .c, .exe, .md 等。
**例外**:
- `CLAUDE.md` — 放專案根目錄
- `memory/` — 放專案根目錄
同時建立 memory/ 和 workspace/ 資料夾。如果已有 CLAUDE.md,檢查是否包含上述兩條規則,缺少就補上。
Phase 1:開題偵察(靜態)
目標:不執行程式,盡可能了解一切。
1.1 基本資訊
用 scripts/pe_info.py 解析(不依賴外部套件):
python pe_info.py target.exe
python pe_info.py target.exe --strings
python pe_info.py target.exe --gbk "任意中文"
python pe_info.py target.exe --json
輸出包含:Architecture、ImageBase、Entry Point、ASLR/DEP、Manifest、
Section 列表 + entropy + 保護殼判斷、Import 分析 + 攻擊面提示。
--gbk 用來搜尋簡體中文程式裡的任意關鍵字(驗證訊息、錯誤提示、功能名稱等),
幫助定位認證邏輯在 binary 中的位置。
1.2 Section 分析
列出所有 section:名稱、VA、大小、entropy。
| 特徵 | 判斷 |
|---|
.vmp .svmp + entropy ~8.0 | VMProtect → 見 docs/vmp-guide.md |
.upx0 .upx1 | UPX → upx -d 脫殼 → 重新分析 |
.themida | Themida/WinLicense |
.text RawSize = 0 | 殼搬移了程式碼 |
| Entry Point 不在 .text | 殼的 loader 先跑 |
| .rdata 裡有 MZ header | 內嵌 payload |
1.3 Import 分析
| Import | 意義 | 攻擊面 |
|---|
| WS2_32.dll (send/recv/connect) | 網路驗證 | hook connect 找 server |
| lstrcmpA / CompareStringA | 本地字串比對 | hook 看比較內容 |
| GetProcAddress | 動態解析 | 需要 runtime hook |
| CryptDecrypt / BCrypt* | 加密 | hook 看明文 |
| MessageBoxA/W | 錯誤訊息 | hook backtrace 找決策點 |
| CreateWindowExA/W | 建立視窗 | 最重要 — 主視窗建立 = bypass 成功 |
1.4 字串搜尋
搜尋:驗證結果字串、IP/domain/URL、配置檔路徑、Window class/title、保護殼特徵。
中文程式依 locale 可能用 GBK(簡體)或 Big5(繁體)編碼:
python pe_info.py target.exe --gbk "关键字"
python pe_info.py target.exe --big5 "關鍵字"
不確定編碼時三種都搜(見速查表)。
1.5 識別保護殼和驗證框架 → 立刻上網搜尋
搜尋策略:
1. "[殼名稱] bypass/crack" — 找已知繞過方法
2. "[殼名稱] [版本] unpack" — 找脫殼工具
3. 中文論壇(吾爱破解、看雪、52pojie)— 中文程式的殼通常中文社群有解
4. GitHub "[殼名稱]" — 找自動化工具
5. 商業驗證框架 — 搜尋已知弱點和超級密碼
1.6 路線判斷
保護殼?
├─ UPX → upx -d → 重新分析
├─ VMProtect → 不脫殼,API 邊界攻擊 → 載入 docs/vmp-guide.md
├─ Themida → 搜尋版本對應的脫殼工具,或 API 邊界攻擊
├─ 自製殼 → 分析 loader 邏輯
├─ 無殼 → Ghidra 反編譯
└─ 不確定 → 上網搜尋 section 名稱
驗證類型?
├─ 網路驗證(有 WS2_32)→ 優先攻擊決策層,不攻擊加密層
├─ 本地驗證(有 strcmp 等)→ hook 比較函數
├─ 時間驗證(GetSystemTime / GetLocalTime)→ hook 時間 API
└─ 混合 → 先確認哪個是主驗證
開發框架?
├─ 易語言 (EPL) → MFC 底層,UI 用 Win32 API
├─ .NET → dnSpy,本 skill 不太適用
├─ Delphi → IDR + x32dbg
└─ 標準 C/C++ → Ghidra
產出: 靜態分析報告 + 判斷路線。跨機器時打包交接包。
Phase 2:動態偵察
原則:先輕量觀察,再精準 hook,不要一上來就全面注入。
2.1 輕量觀察(零工具)
直接跑一次:看 UI、netstat -an 看連線、看配置檔、記錄錯誤訊息。
2.2 Frida 被動偵察
frida -l scripts/recon.js -f challenge.exe
frida -l scripts/recon.js -p <PID>
frida -l scripts/recon.js -f challenge.exe --no-pause
scripts/recon.js 預設啟用:Network、CreateWindowEx、MessageBox、Strcmp。
其他模組(Crypto、File、Registry、Time、MemScan)透過腳本開頭的 ENABLE 開關控制。
Hook 目標:
connect → IP:port
send/recv → 封包大小、輪數、RetAddr(不修改內容)
CreateWindowExA/W → 視窗建立 + 完整 backtrace(最重要)
MessageBoxA/W → 錯誤訊息 + backtrace
lstrcmpA / CompareStringA → 比較內容(本地驗證時)
Differential trace(跑兩次做 diff):
- 有效輸入 → 記錄 API call 序列
- 無效輸入 → 記錄 API call 序列
- diff 兩份結果 → 分歧點就是決策位置
2.3 如果 Frida 被偵測
| 順序 | 方法 | 原理 |
|---|
| 1 | Frida Gadget mode | DLL sideload,繞過 frida-server 偵測 |
| 2 | TitanHide kernel driver | kernel 層隱藏 debug 資訊 |
| 3 | Hook 偵測函數 | 攔截 strstr("frida")、NtQueryInformationProcess |
| 4 | x32dbg + ScyllaHide | 傳統 debugger |
| 5 | 自製 C debugger | 最低調,hardware breakpoint |
監看數值時優先用 Stalker 而非 INT3 斷點。 Stalker 用 dynamic binary instrumentation(動態改寫 code 到 slab),不插入 0xCC、不設 debug register,比 INT3 更不容易搞掛目標進程。詳見 docs/tools-quickref.md。
遇到特定保護殼的反調試問題,見對應指南(如 docs/vmp-guide.md)。
Phase 3:繞過
原則:從決策層開始,不要從加密層開始。
路線選擇:
有 CreateWindowExA 的 backtrace? → 路線 A(最高成功率)
有錯誤訊息的 backtrace? → 路線 B
有字串比較(strcmp)的 hook 結果? → 路線 C-local
都沒有? → 路線 C(搜尋字串交叉引用)
路線 A:從 CreateWindowExA backtrace 找決策點(首選)
- 讀取 backtrace return address 附近 ±64 bytes
- 找條件跳轉(JE/JNE =
74/75/0F 84/0F 85)
Memory.patchCode → NOP 或反轉
- 主視窗出現 = 成功
路線 B:從錯誤訊息往回追
- MessageBox backtrace → 定位錯誤分支
- 往上找條件跳轉 → 反轉
路線 C-local:本地驗證 — hook 比較函數
- hook lstrcmpA/CompareStringA 看到比較的兩個字串
- 其中一個是使用者輸入,另一個就是正確密碼
- 或者直接 patch 比較結果
路線 C:搜尋字串交叉引用
- 記憶體搜尋驗證結果字串(成功/失敗的 GBK bytes)
- 找誰引用了這個地址 → 認證 handler
- 在 handler 裡找條件跳轉
路線 D:網路驗證的協議層攻擊
⚠️ 只有在加密可破時才值得嘗試。Session-bound 加密直接放棄這條路。
路線 E:Binary patch(runtime patch 驗證成功後)
- Frida runtime patch 確認可行 → 計算 file offset → Python 修改 binary → 驗證
Phase 4:驗證和記錄
- 不掛工具跑 patched binary → 確認獨立運作
- 不同假輸入 → 確認不依賴特定輸入
- 記錄:改了什麼、為什麼、哪些方法失敗了
第三部分:速查表
條件跳轉 Patch
| 原始 | Patch 後 | 效果 |
|---|
75 XX (JNE short) | 74 XX / EB XX / 90 90 | 反轉 / 無條件跳 / 移除 |
74 XX (JE short) | 75 XX / EB XX / 90 90 | 反轉 / 無條件跳 / 移除 |
0F 85 XX XX XX XX (JNE near) | 0F 84 / E9 XX XX XX XX 90 / 90x6 | 反轉 / 無條件跳 / 移除 |
0F 84 XX XX XX XX (JE near) | 0F 85 / E9 XX XX XX XX 90 / 90x6 | 反轉 / 無條件跳 / 移除 |
函數返回值
| 目的 | Patch |
|---|
| 永遠返回 0 | 33 C0 C3 (xor eax,eax; ret) |
| 永遠返回 1 | 33 C0 40 C3 (xor eax,eax; inc eax; ret) |
| 跳過函數 | C3 (ret) |
檔案偏移計算
file_offset = RVA - section_VA + section_file_offset
RVA = runtime_VA - ImageBase
中文 Hex 轉換
中文程式在 binary 裡的字串編碼取決於開發環境的 locale:
- GBK:簡體中文(大陸)
- Big5:繁體中文(台灣、香港)
- UTF-8:較新的程式或跨平台框架
用 pe_info.py --gbk 或 --big5 搜尋,或手動轉換:
python3 -c "print(' '.join(f'{b:02X}' for b in '你要搜的字'.encode('gbk')))"
python3 -c "print(' '.join(f'{b:02X}' for b in '你要搜的字'.encode('big5')))"
python3 -c "print(' '.join(f'{b:02X}' for b in '你要搜的字'.encode('utf-8')))"
如何判斷目標用哪種編碼:
- 看 PE 的 locale / code page(Ghidra 的 PE header 或 resource section)
- 簡體字(如「验证」「错误」)→ 大概率 GBK
- 繁體字(如「驗證」「錯誤」)→ 大概率 Big5
- 不確定 → 三種都搜一遍,看哪個有 hit
第四部分:工具清單
必備
| 工具 | 用途 | 安裝 |
|---|
| Frida | 動態 hook、API 攔截、記憶體 patch | pip install frida-tools |
| Python 3 | 腳本、PE 分析、binary patch | 內建或下載 |
建議
| 工具 | 用途 | 何時需要 |
|---|
| Ghidra | 靜態反編譯 | 無殼或脫殼後的深度分析 |
| x32dbg/x64dbg | 傳統 debugger | Frida 被擋時 |
| LIEF | PE 結構修改 | 需要改 PE 結構時 |
| ScyllaHide | x64dbg 反反調試 | 保護殼偵測 debugger 時 |
| TitanHide | Kernel 層反反調試 | 保護殼用 direct syscall 時 |
| dnSpy | .NET 反編譯 | .NET 程式 |
| tshark | 命令行抓包 | 網路驗證協議分析 |
參考資料
Challenge
$ARGUMENTS