mcpField
C
code-obfuscation-deobfuscation

code-obfuscation-deobfuscation

github.com/yaklang安全2.6k4.1k 次安装6 周前更新
代码仓库

关于 code-obfuscation-deobfuscation

code-obfuscation-deobfuscation 是面向逆向分析人员的原生二进制混淆分析手册,帮助识别混淆模式,并选择静态、动态、符号执行或模拟方法还原程序结构与行为。

主要功能

  1. 01混淆模式分类
  2. 02不透明谓词与垃圾代码分析
  3. 03自修改代码检查
  4. 04控制流平坦化还原
  5. 05虚拟机保护与字符串分析
  6. 06反反汇编分析

适用场景

  1. 01还原控制流平坦化二进制
  2. 02检查运行时解密的代码
  3. 03分析虚拟机保护的二进制
  4. 04识别隐藏字符串和导入项

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill code-obfuscation-deobfuscation

安装后在 Claude Code 中输入/code-obfuscation-deobfuscation确认已加载。

详细介绍

技能:代码混淆与反混淆——专家分析手册

AI 加载指令:识别、分类并破解原生二进制文件中代码混淆的专家技巧。涵盖垃圾代码、不透明谓词、自修改代码(SMC)、控制流扁平化、movfuscator、虚拟机保护器(VMProtect/Themida/Code Virtualizer)、字符串加密、导入隐藏和反反汇编技巧。基础模型通常会混淆加壳与代码混淆,并忽略静态和动态反混淆策略之间的区别。

0. 相关路由

快速识别指南
IDA/Ghidra 中的症状可能的混淆类型从这里开始
CFG 扁平化,只有一个巨型 switch控制流扁平化使用符号执行恢复 CFG
只有 mov 指令movfuscator反 movfuscation/基于跟踪的提升
pushad/pushfd → 虚拟机入口虚拟机保护器提取处理程序表
执行代码前出现 XOR 循环SMC/字符串加密动态分析,在解码后设置断点
不可能成立的条件(不透明谓词)插入垃圾代码基于模式移除
所有字符串都不可读字符串加密Hook 解密例程,或进行模拟
IAT 中没有导入项导入隐藏跟踪 GetProcAddress/哈希解析

1. 垃圾代码与不透明谓词

1.1 插入垃圾代码

不会影响程序输出的死代码,用于增加分析所需时间。

识别方法:

  • 写入寄存器/内存、但之后从未读取的指令
  • 返回值被丢弃且没有副作用的函数调用
  • 循环边界不变、计算结果未被使用的循环

移除策略:

  1. 计算定义-使用链(IDA/Ghidra 数据流分析)
  2. 将没有后续用途的指令标记为死代码
  3. 验证移除不会改变程序行为(比较跟踪结果)
1.2 不透明谓词

条件分支中的条件始终为真或始终为假,但这一点并不明显。

类型示例始终求值为
算术x² ≥ 0真
数论x*(x+1) % 2 == 0真(两个连续整数的乘积)
基于指针别名处理后 ptr == ptr真
基于哈希CRC32(constant) == known_value真

反混淆:

  • 抽象解释:证明条件为常量
  • 符号执行:Z3 证明 ∀x: predicate(x) = True
  • 模式匹配:识别已知的不透明谓词类型
  • 动态分析:跟踪并观察分支始终不被执行/始终被执行
import z3
x = z3.BitVec('x', 32)
s = z3.Solver()
s.add(x * (x + 1) % 2 != 0)
print(s.check())  # unsat → always true

2. 自修改代码(SMC)

运行时修补代码:加密代码会在执行前立即解密。

2.1 XOR 解密循环(最常见)
lea esi, [encrypted_code]
mov ecx, code_length
mov al, xor_key
decrypt_loop:
    xor byte [esi], al
    inc esi
    loop decrypt_loop
    jmp encrypted_code  ; now decrypted
2.2 分析策略
1. Identify the decryption routine (look for XOR/ADD/SUB in loops writing to .text)
2. Set breakpoint AFTER the loop completes
3. At breakpoint: dump the decrypted memory region
4. Re-analyze the dumped code in IDA/Ghidra
5. For multi-layer: repeat for each decryption stage
2.3 通过模拟自动脱壳
from unicorn import *
from unicorn.x86_const import *

mu = Uc(UC_ARCH_X86, UC_MODE_32)
mu.mem_map(0x400000, 0x10000)
mu.mem_write(0x400000, binary_code)
mu.emu_start(decrypt_entry, decrypt_end)
decrypted = mu.mem_read(code_start, code_length)

3. 控制流扁平化(CFF)

3.1 结构

原本顺序执行的代码块会被转换为一个分发器循环:

Original:      A → B → C → D

Flattened:     ┌──────────────────┐
               │   dispatcher     │
               │   switch(state)  │◄─────┐
               ├──────────────────┤      │
               │ case 1: block A  │──────┤
               │ case 2: block B  │──────┤
               │ case 3: block C  │──────┤
               │ case 4: block D  │──────┘
               └──────────────────┘

每个代码块都会在跳回分发器之前设置 state = next_state。

3.2 恢复技术
技术工具有效性
符号执行angr、Triton、miasm高——跟踪所有状态转换
基于跟踪的恢复Pin/DynamoRIO 跟踪 → 重建 CFG中——仅覆盖已执行的路径
模式匹配自定义 IDA/Ghidra 脚本中——适用于已知的扁平化工具
D-810(IDA 插件)IDA Pro高——专为 CFF 设计
3.3 符号执行反扁平化(angr 方法)
import angr, claripy

proj = angr.Project('./obfuscated')
cfg = proj.analyses.CFGFast()

# Find dispatcher block (highest in-degree basic block)
dispatcher = max(cfg.graph.nodes(), key=lambda n: cfg.graph.in_degree(n))

# For each case block, symbolically determine successor
for block in case_blocks:
    state = proj.factory.blank_state(addr=block.addr)
    # ... solve state variable to find real successor

4. MOVFUSCATOR

4.1 概念

所有计算都被简化为仅使用 mov 指令(通过内存映射计算表实现图灵完备)。由 Christopher Domas 创建。

4.2 识别
  • 函数只包含 mov 指令(没有 add、sub、xor、jmp、call)
  • 数据段中有大型查找表
  • 内存映射的标志寄存器
4.3 去混淆
方法描述
demovfuscator(工具)静态分析,根据 mov 模式还原原始操作
跟踪 + 污点分析使用 Pin/DynamoRIO 运行,对输入进行污点标记并观察计算过程
符号执行将整个函数视为约束系统

5. VM 保护(VMProtect / Themida / Code Virtualizer)

5.1 VM 架构
Protected code → bytecode compiler → custom bytecode
Runtime: VM entry (pushad/pushfd) → fetch → decode → execute → VM exit (popad/popfd)
5.2 VM 入口点识别
; Typical VMProtect entry
pushad                    ; save all registers
pushfd                    ; save flags
mov ebp, esp              ; VM stack frame
sub esp, VM_LOCALS_SIZE   ; allocate VM context
mov esi, bytecode_addr    ; bytecode instruction pointer
jmp vm_dispatcher         ; enter VM loop
5.3 处理程序表提取
1. Find dispatcher (large switch or indirect jump via table)
2. Each case/entry = one VM handler (implements one VM opcode)
3. Map handler addresses to operations by analyzing each handler:
   - Handler reads operand from bytecode stream (esi)
   - Performs operation on VM registers/stack
   - Advances bytecode pointer
   - Returns to dispatcher
5.4 去虚拟化方法
方法描述工具
手动映射处理程序逆向分析每个处理程序,构建 ISA 规范IDA + 脚本
记录跟踪记录所有处理程序的执行情况,重建程序REVEN、Pin
符号提升对处理程序进行符号执行,提升为 IRTriton、miasm
模式匹配将处理程序模式与已知 VM 系列进行匹配自定义脚本
5.5 VMProtect 特性
  • 在分派器中使用不透明谓词
  • 处理程序变异:相同操作码在不同构建版本中对应不同的处理程序代码
  • 多个 VM 层(VM 中嵌套 VM)
  • 集成反调试和完整性检查

6. 字符串加密

6.1 常见模式
模式示例恢复方法
XOR 循环for (i=0; i<len; i++) s[i] ^= key;Hook 或模拟 XOR 函数
栈字符串mov [esp+0], 'H'; mov [esp+1], 'e'; ...使用 IDA FLIRT / Ghidra 脚本重新组装
RC4 加密加密数据块 + 二进制文件中的 RC4 密钥提取密钥,离线解密
AES 加密加密数据块 + 运行时派生的 AES 密钥在解密后 Hook
自定义编码Base64 + XOR + 反转跟踪解码函数并复现
6.2 自动字符串解密
# Ghidra script: find XOR decryption calls, emulate them
from ghidra.program.model.symbol import SourceType

decrypt_func = getFunction("decrypt_string")
refs = getReferencesTo(decrypt_func.getEntryPoint())

for ref in refs:
    call_addr = ref.getFromAddress()
    # extract arguments (encrypted buffer ptr, key, length)
    # emulate decryption, add comment with plaintext

7. 导入隐藏

7.1 GetProcAddress + 哈希查找
FARPROC resolve(DWORD hash) {
    // Walk PEB → LDR → InMemoryOrderModuleList
    // For each DLL, walk export table
    // Hash each export name, compare with target hash
    // Return matching function pointer
}
7.2 恢复
  1. 识别哈希算法(常见算法:CRC32、djb2、ROR13+ADD)
  2. 计算所有已知 API 名称的哈希值
  3. 构建哈希 → API 名称查找表
  4. 在 IDA/Ghidra 中标注已解析的调用
7.3 常见哈希算法
名称算法使用者
ROR13hash = (hash >> 13 | hash << 19) + charMetasploit shellcode
djb2hash = hash * 33 + char各类恶意软件
CRC32函数名称的标准 CRC32高级加壳工具
FNV-1ahash = (hash ^ char) * 0x01000193现代恶意软件

8. 反反汇编技巧

8.1 技术
技巧机制修复方法
指令重叠jmp $+2; db 0xE8(伪造的调用前缀)从正确偏移处手动重新分析
跳转未对齐跳入多字节指令的中间位置强制 IDA 从目标位置重新分析
条件跳转对jz $+5; jnz $+3(始终跳转,迷惑线性反汇编)转换为无条件 jmp
返回地址操纵使用 push addr; ret 代替 jmp addr将 push+ret 识别为跳转
基于异常的流程触发异常,真正的代码位于处理程序中分析异常处理程序链
Call + add [esp]call $+5; add [esp], N; ret(计算跳转)计算实际目标
8.2 IDA 修复
Right-click → Undefine (U)
Right-click → Code (C) at correct offset
Edit → Patch → Assemble (for permanent fix)

9. 决策树

Obfuscated binary — how to approach?
│
├─ Can you run it?
│  ├─ Yes → Dynamic analysis first
│  │  ├─ Set BP on interesting APIs (file, network, crypto)
│  │  ├─ Trace execution to understand real behavior
│  │  └─ Dump decrypted code/strings at runtime
│  │
│  └─ No (embedded/firmware/exotic arch) → Static only
│     └─ Identify obfuscation type from patterns below
│
├─ What does the code look like?
│  │
│  ├─ Giant flat switch/dispatcher loop?
│  │  ├─ State variable drives control flow → CFF
│  │  │  └─ Use D-810 or symbolic deflattening
│  │  └─ Bytecode fetch-decode-execute → VM protection
│  │     └─ Extract handlers, build disassembler
│  │
│  ├─ Only mov instructions?
│  │  └─ movfuscator → demovfuscator tool
│  │
│  ├─ XOR/ADD loop writing to .text section?
│  │  └─ SMC → breakpoint after decode, dump
│  │
│  ├─ Impossible conditions in branches?
│  │  └─ Opaque predicates → Z3 proving or pattern removal
│  │
│  ├─ Disassembly looks wrong / functions overlap?
│  │  └─ Anti-disassembly → manual re-analysis at correct offsets
│  │
│  ├─ No readable strings?
│  │  └─ String encryption → hook decrypt function or emulate
│  │
│  ├─ No imports in IAT?
│  │  └─ Import hiding → identify hash, build lookup table
│  │
│  └─ pushad/pushfd → complex code → popad/popfd?
│     └─ VM protector entry/exit → full VM analysis
│
└─ What tool to use?
   ├─ Known protector (VMProtect/Themida) → specific deprotection guide
   ├─ Custom obfuscation → combine: IDA scripting + Triton + manual
   ├─ CTF challenge → angr symbolic execution often fastest
   └─ Malware analysis → dynamic (debugger + API monitor) first

10. 工具箱

工具用途最适合
IDA Pro + Hex-Rays反汇编、反编译、脚本编写全方位分析
Ghidra支持脚本编写(Java/Python)的免费替代方案预算有限的逆向工程
D-810 (IDA plugin)自动化 CFF 去扁平化OLLVM 风格的混淆
miasm基于 IR 的分析框架符号化去混淆
Triton动态符号执行不透明谓词求解、CFF
REVEN全系统跟踪记录与回放VM 保护器分析
demovfuscator还原 movfuscator仅含 mov 指令的二进制文件
x64dbg + plugins支持脚本编写的动态分析Windows 逆向工程
Unicorn EngineCPU 仿真SMC 脱壳、shellcode
Capstone反汇编库定制工具
IDA FLIRT函数特征匹配识别剥离二进制文件中的库代码
Binary Ninja采用 MLIL/HLIL 的替代反汇编器自动化分析

评论

支持 Markdown