CTF Reverse(逆向)题目类型全景图:从 🟢 签到 到 ⚫ 地狱
一句话本质:逆向不是"看懂每一行汇编",而是——确认程序类型/保护 → 定位关键逻辑(验证/加密/计算)→ 把它翻译成你能重放的逆运算(或干脆 Patch 跳过它)。
🧰 前置准备(先把环境焊死)
类别 | 工具 | 什么时候用 |
|---|
查壳/查文件类型 | file、Detect It Easy(DIE)、ExeinfoPE
| 第一件事:什么平台?多少位?有没有壳/混淆? |
静态分析主力 | IDA Pro(F5伪代码)、Ghidra(免费全能)、Radare2/Cutter | 不运行程序,先"看结构/流程/字符串/交叉引用" |
动态调试 | x64dbg / OllyDbg(Windows)、GDB + pwndbg/gef(Linux)、WinDbg | 运行时看寄存器/内存/跳转,验证你的静态猜测 |
辅助/编辑 | 010 Editor / HxD、Binwalk、Strings、objdump/readelf | 看文件格式、提取嵌在数据段的东西 |
脚本还原 | Python(struct / z3 / cryptography)+ Capstone/Keystone(进阶) | 把"正向加密/变换"写成逆向脚本算 flag |
动态插桩(中后期) | Frida、QBDI(偏高级) | 当静态看不清/反调试恶心时,直接 Hook 取值 |
新手最短路径:IDA(或Ghidra)静态看伪代码 + x64dbg/GDB动态验证,两个配合就够打到大量入门~中级题。
🟢 Level 1 — 签到 / 信息收集逆向(最快拿分,先做这些)
和 Web 一样,逆向也有"根本不用真·逆向"的送分题:
题型 | 为什么简单 | 你该怎么做 |
|---|
字符串里直接藏 flag | flag{...}明文躺在 .rodata/ 资源段
| IDA → Shift+F12 字符串窗口 → 搜 flag{/ correct/ wrong/ good |
无壳、逻辑一眼看完 | 主函数里就是把输入和固定数组逐字节比对 | 把数组抄出来 → 按伪代码里的变换(±//xor/位移)逆着算一遍*就行 |
Patch 过校验(打补丁) | 关键跳转 jnz/je决定成败 | x64dbg:找到 je/jne→ 改成 jmp(或直接改 ZF)→ 让它走到成功分支,程序自己吐 flag |
资源/常量泄漏 | flag 编进图标、对话框资源、字符串表、甚至图片资源 | ResourceHacker、strings、binwalk 扫一遍 |
📚 练手平台:Bugku Reverse 新手区 / CTFshow Reverse / 攻防世界「新手 Reverse」/ 简单 crackme on Crackmes.one
🟡 Level 2 — 经典"加密/变换还原"题(新手→初级核心,⭐⭐)
CTF Wiki 与多数 WriteUp 的共识:新手 Reverse 里最大头就是"字符串异或/移位/替换 + 简单算法逆向"
① 异或 / 加减 / 位移 / 查表替换(出现率极高)
典型伪代码模式:
// 正向
enc[i] = (input[i] ^ key[i]) + 3;
// 或
enc[i] = input[i] + key[i];
// 或替换表: out[i] = table[ input[i] ]
你要做的只有一件事:把正向公式写反。
模式 | 逆向操作 |
|---|
enc[i] = input[i] ^ k
| input[i] = enc[i] ^ k(xor 自逆)
|
enc[i] = input[i] + k
| input[i] = enc[i] - k
|
`enc[i] = (input[i] << 1) | (input[i] >> 7)` |
替换表 | 建反查表:orig = inv_table[enc[i]] |
✅ 关键训练:看到 for+ ^/ +/ <</ 数组下标 → 先假设"逐字节可逆",直接抄目标密文数组 + key 写 Python 还原。
② Base64 / Hex / 自定义编码链
考法 | 对策 |
|---|
标准 Base64 后再比较 | 直接 Base64-decode 目标串,再看剩下是什么 |
魔改 Base64 表 | 从代码里把 alphabet 抄出来,换表解码 |
多层编码:hex → b64 → xor | 顺着伪代码从外往里拆(或从后往前逆) |
③ 简单"算法验证":CRC/哈希咆哮、查表校验和
📚 靶场:CTFHub 逆向入门 / BUUCTF 搜"reverse 签到/ XOR / easy" / ReversingHero
🟠 Level 3 — 中级:加壳·脱壳·反调试·混淆·跨语言(初级→中级分水岭,⭐⭐⭐)
④ 加壳与脱壳(这里开始"程序不能直接 F5")
第一反应永远一样:DIE/ExeinfoPE 先看壳 → 再决定要不要脱。
壳/压缩 | 国赛/常规赛出现率 | 处理方式 |
|---|
UPX(最常见) | ⭐ 占大头 | 直接 upx -d xxx一键脱;失败就用 ESP 定律/内存 dump + IAT修复 手动脱 |
ASPack / FSG | 中等(尤其 64 位压轴爱出) | 专用脱壳脚本/手动定位 OEP → dump → 修 IAT |
VMProtect / Themida(强壳) | 偏高分题 / AWD 风格 | 一般不指望"完美脱壳",更多靠 动态Trace、符号执行、Hook、差分分析 抠关键比较值 |
通用口诀:壳 ≠ 不可做。很多题的"加壳"只是压缩壳(UPX),一脱完里面就是 Level 2 的异或/比对题。
⑤ 反调试 / 反-VM / 花指令
技术 | 你怎么认出来 | 怎么对付 |
|---|
IsDebuggerPresent/ PEB.BeingDebugged
| 调用一目了然 | Patch 返回值 AL=0 / 用 ScyllaHide / x64dbg 插件 |
时间差 rdtsc | 连续 rdtsc 差值判断 | 断点跳过或 nop 掉检测块 |
硬件断点检测 / 代码校验和 | 在关键区段扫 hash | 找准检测函数 → retn 直接跳过(Patch) |
花指令(junk bytes 让反汇编错位) | IDA 里满屏 db ??、控制流碎 | 手动 C(code)/U(undefined) 修正;更狠的用反混淆脚本/插件 |
⑥ 控制流平坦化(OLLVM 等)
⑦ 跨语言/跨架构入门
类型 | 为什么突然变烦 | 要点 |
|---|
Python 打包(PyInstaller / pyc) | 拿到的不是原生 ELF/PE,而是 Python bytecode | pycdc/uncompyle6 反编译 .pyc→ 读源码更直接 |
Go 二进制 | 符号多但名字奇怪、runtime 噪音大 | r2 -A/ Ghidra 的 Go 辅助脚本;重点搜字符串 + 看 main.*
|
.NET (C#) | IL 而不是 native asm | dnSpy / ILSpy 直接反编译到 C#(往往是最快的逆向之一) |
ARM/ARM64(Android 相关) | 指令集变了 | 先抓:ELF 结构不变,只是汇编是 ARM;重点学 BL/LDR/STR/调用约定 |
📚 此阶段刷题:BUUCTF Reverse 2~4星 / CTFshow 进阶 / Flare-On(偏真实 malware 风格但极练本事)/ picoCTF Reverse 中高
🔴 Level 4 — 进阶:VM·算法识别·符号约束·移动端(中级→进阶,⭐⭐⭐⭐)
⑧ 自定义 VM(字节码解释器)
题目会写一个小型"虚拟机":自己定义 opcode → fetch-decode-execute 循环。
解法是:
把 opcode 含义 翻译成人类语言(add/sub/xor/load/store…)
把 bytecode 提取出来
要么:手写解释器正向跑你的输入候选,要么:直接模拟 VM 反推(通常等价"解一个约束系统")
标志:你看到 while(opcode != HALT)+ 一个大 switch+ 一堆 mem[rIP++]— 就高度怀疑 VM。
⑨ 算法识别:TEA/XTEA/RC4/AES/MD5-SHA 变种
场景 | 识别点 | 处理 |
|---|
TEA 系 | 魔数 0x9E3779B9、(v0+=...)双变量循环 | 抄密钥/轮数,写 逆 TEA |
RC4 | S[i] = i初始化 + swap KSA
| 如果只做了 KSA+PRGA 输出与 flag 异或:RC4 也自逆(key 未知就另说) |
AES | 大量查表 / SubBytes/ShiftRows/MixColumns 特征 | 先确认 key 是不是硬编码;很多题 key 就在 data 段 |
MD5/SHA 变种 | 初态常量 0x67452301... | 多半是:MD5(input) == target_md5 → 你只需要 识别它是 MD5,然后换思路(爆破/已知明文/长度短) |
⑩ 约束求解 / 符号执行(angr / z3)
当你懒得手推公式,但可以精确描述"输入满足条件"时:
注意:angr 不是万能锤,遇到复杂反调试/系统调用交互会翻车;但对"纯计算验证"的题中非常好用。
⚫ Level 5 — 高阶:Android/iOS·强壳·对抗性题目·AWD 逆向(⭐⭐⭐⭐⭐)
类型 | 关键点 |
|---|
Android Reverse | APK → dex→ jadx/grok smali;native so → IDA 继续;Frida Hook 直接截返回值/绕过校验 |
iOS Reverse | Mach-O、Hopper/IDA、Objective-C msgSend 模式、dyld 共享缓存 |
强壳 VMProtect/Themida | 目标通常不是"完美脱壳",而是:定位关键比较点/输入变换出口,用差分/插桩把 flag 抠出来 |
AWD 逆向 | 你既要解(拿 flag),也可能要 快速 Patch 出后门维持访问 / 修洞防别人打(偏攻防赛制) |
🗺️ 通用解题框架(任何 Reverse 题都照这个顺序走)
这个 5 步在多篇 CTF 总结里反复出现,照做就不会乱:
程序初判:file/ DIE — 平台?位数?语言?壳?有什么字符串?
静态粗定位:IDA/Ghidra → 字符串窗口(Shift+F12)→ 交叉引用(X)→ 追到验证函数
看伪代码(F5):把主逻辑读成"输入 → 变换A → 变换B → cmp 与 target"
关键信息提取:target 数组 / key / 表 / 比较函数地址
脚本还原 OR Patch:Python 逆运算 → 得 flag;或调试器 Patch 跳转直接走成功分支
口诀:一看(工具)二猜(这是什么变换/算法家族)三验证(动态调试确认你的猜测)
📅 推荐刷题路线(按周/月可落地)
阶段 | 时长(大致) | 目标 | 去哪练 |
|---|
第1~2周 | 装环境 + 吃透汇编最小集(mov/push/pop/call/ret/cmp/test/jcc) | 能把简单 C 程序反汇编后对应回源码逻辑 | 自己写几个 C 小程序:strcmp校验 / xor / 循环 → 用 IDA 读伪代码 |
第1个月 | Level 1+Level 2 主循环 | 无壳题能稳定拿:字符串题/异或还原/base64链/Patch跳转 | Bugku、CTFshow Reverse、攻防世界新手区、Crackmes.one(easy) |
第2~3月 | 加壳入门 + 动态调试成型 | UPX 一键脱壳→再分析;会用 x64dbg/GDB 下断点追关键比较;懂基本反调试 Patch | CTFHub 技能树 Reverse / BUUCTF 搜"UPX/easy_reverse" |
第3~6月 | Level 3 主体打完 | 能处理:ASPack类壳/花指令/控制流混乱题/PyInstaller/Go/.NET;开始碰 TEA/RC4/VM-lite | BUUCTF 2~4星 / picoCTF / Flare-On 早期 / CTFtime 找 WriteUp 对照 |
之后 | Level 4+ | 自定义 VM、z3/angr、Android smali+Frida、强混淆对抗 | 高质量杯赛真题、Flare-On 后半段、看雪/论坛里的深度 WriteUp |
🧠 一句老选手经验(比 Payload 更重要)
逆向题 70% 的时间花在"定位与确认",30% 才是"算"。
你最强的习惯应该是:
先看字符串窗口(最少五秒钟)
再看 main → 找 cmp / memcmp / strcmp / 成功/失败分支
把 target bytes 抄准(差一个字节就全错)
能用 Python 逆的就别手算,能 Patch 跳过的就别死磕公式