reverse-engineering

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Reverse Engineering

逆向工程

Purpose

用途

Guide agents through reverse engineering binaries: Ghidra project setup and decompilation, radare2 analysis workflow, Binary Ninja scripting, initial triage with
strings
/
file
/
xxd
, identifying C++ patterns (vtables, RAII), analyzing stripped binaries, and diffing with Diaphora or BinDiff.
引导 Agent 完成二进制文件逆向工程:设置 Ghidra 项目并反编译、执行 radare2 分析工作流、编写 Binary Ninja 脚本、使用
strings
/
file
/
xxd
进行初步研判、识别 C++ 模式(vtables、RAII)、分析去除符号的二进制文件,以及使用 Diaphora 或 BinDiff 比较差异。

When 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 -40
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 -40

Check 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
undefined
bash
undefined

Headless analysis

Headless analysis

analyzeHeadless /tmp/ghidra_projects MyProject
-import suspicious_binary
-postScript ExportDecompile.java
analyzeHeadless /tmp/ghidra_projects MyProject
-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
undefined

Ghidra 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())
undefined
from ghidra.program.model.listing import FunctionManager fm = currentProgram.getFunctionManager() for f in fm.getFunctions(True): print(f.getName(), f.getEntryPoint())
undefined

3. 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; pdf
Patching:
[0x00001000]> wx 9090 @ 0x401234   # write NOPs
[0x00001000]> wci 0x401234         # insert instruction
[0x00001000]> wt modified_binary
bash
undefined
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; pdf
补丁处理:
[0x00001000]> wx 9090 @ 0x401234   # write NOPs
[0x00001000]> wci 0x401234         # insert instruction
[0x00001000]> wt modified_binary
bash
undefined

r2 scripting

r2 scripting

r2 -qc 'aaa; afl' suspicious_binary r2 -i analysis.r2 suspicious_binary
undefined
r2 -qc 'aaa; afl' suspicious_binary r2 -i analysis.r2 suspicious_binary
undefined

4. Binary Ninja scripting

4. Binary Ninja 脚本编写

python
undefined
python
undefined

BN 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)
undefined
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)
undefined

5. 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
PatternIndicator
Vtable
.data.rel.ro
section, array of function pointers
RAIIpaired ctor/dtor calls, exception landing pads
TemplatesMangled names
_Z...
, duplicate logic per type
std::stringSSO buffer inline or heap pointer at offset 0
bash
undefined
cpp
// Vtable pattern in disassembly
// mov rax, [rdi]      ; load vtable pointer
// call [rax+0x10]     ; virtual call at offset

// Constructor pattern
// mov [obj], offset vtable
模式指示特征
虚表(Vtable)
.data.rel.ro
段、函数指针数组
RAII成对的 ctor/dtor 调用、异常 landing pad
模板(Templates)经过修饰的名称
_Z...
、每种类型重复的逻辑
std::string偏移量 0 处的内联 SSO 缓冲区或堆指针
bash
undefined

Demangle C++ symbols

Demangle C++ symbols

c++filt _ZN4Math3addEii
undefined
c++filt _ZN4Math3addEii
undefined

6. Stripped binary recovery

6. 恢复去除符号的二进制文件

bash
undefined
bash
undefined

Find 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
undefined
bash
undefined

Diaphora (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) first
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) first

Common Problems

常见问题

SymptomCauseFix
Ghidra decompiler failsIndirect jumps, bad typesFix function signature; define struct
r2 analysis incompleteLarge binary
aaa
then
aac
; increase analysis depth
Wrong architectureARM vs Thumb, MIPSSet
-a arm
or correct Ghidra language
Anti-debug trapptrace checkPatch or use
-gdb
in QEMU
Packed binaryUPX/etc.
upx -d
or manual unpack
No xrefs to stringPIE/RELROFollow GOT; runtime analysis
症状原因解决方法
Ghidra decompiler 失败间接跳转、类型错误修复函数签名;定义结构体
r2 分析不完整二进制文件较大执行
aaa
后再执行
aac
;提高分析深度
架构错误ARM 与 Thumb、MIPS设置
-a arm
或选择正确的 Ghidra 语言
反调试检测陷阱ptrace 检查修改补丁,或在 QEMU 中使用
-gdb
加壳的二进制文件UPX 等
upx -d
或手动脱壳
字符串无交叉引用PIE/RELRO跟踪 GOT;进行运行时分析

Related Skills

相关 Skill

  • skills/binaries/elf-inspection
    — ELF structure analysis
  • skills/debuggers/gdb
    — dynamic analysis complement
  • skills/runtimes/binary-hardening
    — understanding mitigations being bypassed
  • skills/security/kernel-security
    — kernel RE and CVE analysis
  • skills/low-level-programming/assembly-x86
    — reading disassembly
  • skills/low-level-programming/assembly-arm
    — ARM binary analysis
  • skills/binaries/elf-inspection
    — ELF 结构分析
  • skills/debuggers/gdb
    — 动态分析补充
  • skills/runtimes/binary-hardening
    — 理解被绕过的安全缓解机制
  • skills/security/kernel-security
    — 内核 RE 与 CVE 分析
  • skills/low-level-programming/assembly-x86
    — 阅读反汇编
  • skills/low-level-programming/assembly-arm
    — ARM 二进制文件分析