reverse-engineering
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReverse Engineering
逆向工程
Purpose
用途
Guide agents through reverse engineering binaries: Ghidra project setup and decompilation, radare2 analysis workflow, Binary Ninja scripting, initial triage with //, identifying C++ patterns (vtables, RAII), analyzing stripped binaries, and diffing with Diaphora or BinDiff.
stringsfilexxd引导 Agent 完成二进制文件逆向工程:设置 Ghidra 项目并反编译、执行 radare2 分析工作流、编写 Binary Ninja 脚本、使用 // 进行初步研判、识别 C++ 模式(vtables、RAII)、分析去除符号的二进制文件,以及使用 Diaphora 或 BinDiff 比较差异。
stringsfilexxdWhen to Use
适用场景
- Analyzing an unknown binary without source code
- Recovering algorithm logic from compiled executables
- Comparing two firmware versions for vulnerability patches
- Understanding malware or CTF challenge binaries
- Recovering symbols from stripped ELF/PE files
- Automating analysis with Ghidra or r2 scripts
- 在没有源代码的情况下分析未知二进制文件
- 从已编译的可执行文件中还原算法逻辑
- 比较两个固件版本中的漏洞补丁
- 理解恶意软件或 CTF 挑战二进制文件
- 从已去除符号的 ELF/PE 文件中恢复符号
- 使用 Ghidra 或 r2 脚本自动化分析
Workflow
工作流
1. Initial triage
1. 初步研判
bash
file suspicious_binary
strings -n 8 suspicious_binary | head -50
strings -el suspicious_binary # UTF-16 LE
xxd suspicious_binary | head -20
readelf -h suspicious_binary # ELF
objdump -d -M intel suspicious_binary | head -40bash
file suspicious_binary
strings -n 8 suspicious_binary | head -50
strings -el suspicious_binary # UTF-16 LE
xxd suspicious_binary | head -20
readelf -h suspicious_binary # ELF
objdump -d -M intel suspicious_binary | head -40Check protections
Check protections
checksec --file=suspicious_binary
| Command | Reveals |
|---------|---------|
| `file` | Architecture, static/dynamic, stripped |
| `strings` | URLs, paths, error messages, keys |
| `readelf -s` | Symbol table (if not stripped) |
| `nm -D` | Dynamic symbols |
| `checksec` | RELRO, NX, PIE, canary |checksec --file=suspicious_binary
| 命令 | 可揭示的信息 |
|---------|---------|
| `file` | 架构、静态/动态链接、是否已去除符号 |
| `strings` | URL、路径、错误消息、密钥 |
| `readelf -s` | 符号表(如果未去除符号) |
| `nm -D` | 动态符号 |
| `checksec` | RELRO、NX、PIE、canary |2. Ghidra workflow
2. Ghidra 工作流
bash
undefinedbash
undefinedHeadless analysis
Headless analysis
analyzeHeadless /tmp/ghidra_projects MyProject
-import suspicious_binary
-postScript ExportDecompile.java
-import suspicious_binary
-postScript ExportDecompile.java
analyzeHeadless /tmp/ghidra_projects MyProject
-import suspicious_binary
-postScript ExportDecompile.java
-import suspicious_binary
-postScript ExportDecompile.java
GUI: File → New Project → Import File → Analyze (Yes)
GUI: File → New Project → Import File → Analyze (Yes)
Key steps:
1. **Auto-analysis** — let Ghidra complete disassembly
2. **Define functions** — `F` at entry points if missed
3. **Decompiler** — Window → Decompiler (C-like output)
4. **Rename** — `L` on variables/functions for clarity
5. **Cross-references** — `Ctrl+Shift+F` on function/data
```java
// Ghidra script (Java) — list functions > 100 bytes
import ghidra.program.model.listing.*;
FunctionManager fm = currentProgram.getFunctionManager();
for (Function f : fm.getFunctions(true)) {
if (f.getBody().getNumAddresses() > 100)
println(f.getName() + " @ " + f.getEntryPoint());
}python
undefined
关键步骤:
1. **自动分析** — 让 Ghidra 完成反汇编
2. **定义函数** — 如果遗漏了入口点处的函数,按 `F`
3. **decompiler** — Window → Decompiler(C-like 输出)
4. **重命名** — 对变量/函数按 `L`,以提高清晰度
5. **交叉引用** — 在函数/数据上按 `Ctrl+Shift+F`
```java
// Ghidra script (Java) — list functions > 100 bytes
import ghidra.program.model.listing.*;
FunctionManager fm = currentProgram.getFunctionManager();
for (Function f : fm.getFunctions(true)) {
if (f.getBody().getNumAddresses() > 100)
println(f.getName() + " @ " + f.getEntryPoint());
}python
undefinedGhidra Python (Jython)
Ghidra Python (Jython)
from ghidra.program.model.listing import FunctionManager
fm = currentProgram.getFunctionManager()
for f in fm.getFunctions(True):
print(f.getName(), f.getEntryPoint())
undefinedfrom ghidra.program.model.listing import FunctionManager
fm = currentProgram.getFunctionManager()
for f in fm.getFunctions(True):
print(f.getName(), f.getEntryPoint())
undefined3. radare2 workflow
3. radare2 工作流
bash
r2 suspicious_binary[0x00001000]> aaa # analyze all
[0x00001000]> afl # list functions
[0x00001000]> pdf @ main # disassemble function
[0x00001000]> VV # visual graph mode
[0x00001000]> iz # strings in data sections
[0x00001000]> s sym.main; pdfPatching:
[0x00001000]> wx 9090 @ 0x401234 # write NOPs
[0x00001000]> wci 0x401234 # insert instruction
[0x00001000]> wt modified_binarybash
undefinedbash
r2 suspicious_binary[0x00001000]> aaa # analyze all
[0x00001000]> afl # list functions
[0x00001000]> pdf @ main # disassemble function
[0x00001000]> VV # visual graph mode
[0x00001000]> iz # strings in data sections
[0x00001000]> s sym.main; pdf补丁处理:
[0x00001000]> wx 9090 @ 0x401234 # write NOPs
[0x00001000]> wci 0x401234 # insert instruction
[0x00001000]> wt modified_binarybash
undefinedr2 scripting
r2 scripting
r2 -qc 'aaa; afl' suspicious_binary
r2 -i analysis.r2 suspicious_binary
undefinedr2 -qc 'aaa; afl' suspicious_binary
r2 -i analysis.r2 suspicious_binary
undefined4. Binary Ninja scripting
4. Binary Ninja 脚本编写
python
undefinedpython
undefinedBN Python API
BN Python API
import binaryninja as bn
bv = bn.load("suspicious_binary")
for func in bv.functions:
if func.name.startswith("sub_"):
hlil = func.hlil
for block in hlil:
print(block)
undefinedimport binaryninja as bn
bv = bn.load("suspicious_binary")
for func in bv.functions:
if func.name.startswith("sub_"):
hlil = func.hlil
for block in hlil:
print(block)
undefined5. C++ pattern recognition
5. C++ 模式识别
cpp
// Vtable pattern in disassembly
// mov rax, [rdi] ; load vtable pointer
// call [rax+0x10] ; virtual call at offset
// Constructor pattern
// mov [obj], offset vtable| Pattern | Indicator |
|---|---|
| Vtable | |
| RAII | paired ctor/dtor calls, exception landing pads |
| Templates | Mangled names |
| std::string | SSO buffer inline or heap pointer at offset 0 |
bash
undefinedcpp
// Vtable pattern in disassembly
// mov rax, [rdi] ; load vtable pointer
// call [rax+0x10] ; virtual call at offset
// Constructor pattern
// mov [obj], offset vtable| 模式 | 指示特征 |
|---|---|
| 虚表(Vtable) | |
| RAII | 成对的 ctor/dtor 调用、异常 landing pad |
| 模板(Templates) | 经过修饰的名称 |
| std::string | 偏移量 0 处的内联 SSO 缓冲区或堆指针 |
bash
undefinedDemangle C++ symbols
Demangle C++ symbols
c++filt _ZN4Math3addEii
undefinedc++filt _ZN4Math3addEii
undefined6. Stripped binary recovery
6. 恢复去除符号的二进制文件
bash
undefinedbash
undefinedFind main via __libc_start_main
Find main via __libc_start_main
readelf -s binary | grep -E 'main|start'
readelf -s binary | grep -E 'main|start'
Or r2: afl~entry
Or r2: afl~entry
FLIRT signatures (Ghidra/BN) — match libc patterns
FLIRT signatures (Ghidra/BN) — match libc patterns
Stack string analysis in Ghidra decompiler
Stack string analysis in Ghidra decompiler
Strategies:
- Identify `main` via libc init or entry point
- Find syscalls (`syscall` insn on Linux)
- String xref to locate error handlers
- Entropy analysis for encrypted sections
策略:
- 通过 libc 初始化或入口点识别 `main`
- 查找 syscall(Linux 上的 `syscall` 指令)
- 对字符串执行 xref 定位错误处理例程
- 对加密段进行熵分析7. Binary diffing
7. 二进制差异分析
bash
undefinedbash
undefinedDiaphora (Ghidra/IDA plugin)
Diaphora (Ghidra/IDA plugin)
Export from both binaries, run diff
Export from both binaries, run diff
BinDiff (commercial, IDA/Ghidra)
BinDiff (commercial, IDA/Ghidra)
bindiff old.i64 new.i64
bindiff old.i64 new.i64
Simple hash diff
Simple hash diff
sha256sum firmware_v1 firmware_v2
diff <(objdump -d v1) <(objdump -d v2) | head
Use diffing to find patched vulnerability functions after updates.sha256sum firmware_v1 firmware_v2
diff <(objdump -d v1) | head
通过差异分析找出更新后已修补的漏洞函数。8. RE decision tree
8. RE 决策树
Binary type?
├── ELF/Linux → Ghidra + r2 + readelf
├── PE/Windows → Ghidra + PE-bear + x64dbg reference
├── Firmware → binwalk extract → Ghidra on architecture
└── Obfuscated → dynamic analysis (gdb/ltrace) firstBinary type?
├── ELF/Linux → Ghidra + r2 + readelf
├── PE/Windows → Ghidra + PE-bear + x64dbg reference
├── Firmware → binwalk extract → Ghidra on architecture
└── Obfuscated → dynamic analysis (gdb/ltrace) firstCommon Problems
常见问题
| Symptom | Cause | Fix |
|---|---|---|
| Ghidra decompiler fails | Indirect jumps, bad types | Fix function signature; define struct |
| r2 analysis incomplete | Large binary | |
| Wrong architecture | ARM vs Thumb, MIPS | Set |
| Anti-debug trap | ptrace check | Patch or use |
| Packed binary | UPX/etc. | |
| No xrefs to string | PIE/RELRO | Follow GOT; runtime analysis |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| Ghidra decompiler 失败 | 间接跳转、类型错误 | 修复函数签名;定义结构体 |
| r2 分析不完整 | 二进制文件较大 | 执行 |
| 架构错误 | ARM 与 Thumb、MIPS | 设置 |
| 反调试检测陷阱 | ptrace 检查 | 修改补丁,或在 QEMU 中使用 |
| 加壳的二进制文件 | UPX 等 | |
| 字符串无交叉引用 | PIE/RELRO | 跟踪 GOT;进行运行时分析 |
Related Skills
相关 Skill
- — ELF structure analysis
skills/binaries/elf-inspection - — dynamic analysis complement
skills/debuggers/gdb - — understanding mitigations being bypassed
skills/runtimes/binary-hardening - — kernel RE and CVE analysis
skills/security/kernel-security - — reading disassembly
skills/low-level-programming/assembly-x86 - — ARM binary analysis
skills/low-level-programming/assembly-arm
- — ELF 结构分析
skills/binaries/elf-inspection - — 动态分析补充
skills/debuggers/gdb - — 理解被绕过的安全缓解机制
skills/runtimes/binary-hardening - — 内核 RE 与 CVE 分析
skills/security/kernel-security - — 阅读反汇编
skills/low-level-programming/assembly-x86 - — ARM 二进制文件分析
skills/low-level-programming/assembly-arm