Files
reverse-skill/skills/dotnet-reverse/references/obfuscators.md
2026-08-08 18:32:33 +08:00

5.7 KiB
Raw Permalink Blame History

.NET 混淆器脱混淆详解

主流 .NET 混淆器的识别、脱壳、anti-tamper 绕过。核心工具:de4dot(自动识别大多数壳)+ dnSpyEx(手动 patch)+ dnlib(脚本化)。

总决策表

混淆器 de4dot type 典型特征 自动脱壳 手动要点
ConfuserEx 1.x/2.x cfze anti-tamper、控制流变形、字符串加密、反调试 ✅ 多数自动 新版需先 patch anti-tamper
ConfuserEx 3.x / 私改 cfze 同上 + 自定义 protector ⚠️ 部分 dump 运行时 / dnlib
SmartAssembly sa 字符串编码、资源压缩、方法调用隐藏 ✅ 自动 资源解压
Babel.NET babel 方法体加密、控制流、字符串 ✅ 自动 —
Eazfuscator.NET eaz 字符串/资源加密、表达式混淆 ⚠️ 部分 字符串解密器
.NET Reactor reactor necrobit (代码段加密) + anti-tamper ⚠️ 新版难 dump + 重建 metadata
Themida .NET — 外壳 + 虚拟化 ❌ de4dot 不行 dump 内存,走 native 思路
Agile.NET / CliSecure agile 方法体加密 ✅ 自动 —

de4dot 标准用法

# 自动识别(多数情况够用)
de4dot target.exe -o target-clean.exe

# 显式指定 type(自动识别失败)
de4dot --type cfze target.exe -o target-clean.exe

# 先探测壳类型
de4dot --detect target.exe

# 批量
de4dot *.exe

# 只解字符串,不动控制流(最小干预)
de4dot --strtyp delegate --strtok METHOD_TOKEN target.exe

de4dot 的 --strtyp / strtok 模式:只解字符串解密器(指定解密方法 token),保留原控制流。适合"只想看明文字符串但不想碰 anti-tamper"的场景。


ConfuserEx(最常见)

特征识别

  • 入口模块 <module> 类带 [MethodImpl(NoInlining)] 的 anti-tamper 检查
  • 大量 Dictionary<string, T> 的字符串解密器调用
  • 控制流平坦化(switch dispatch + state 变量)
  • 资源里嵌 .cmp 压缩资源
  • dnSpyEx C# 视图:类名/方法名乱码(\uXXXX 或无意义字符),方法体里满屏 int num = ...; switch(num)

脱壳流程

# 1. 标准脱壳
de4dot target.exe -o target-clean.exe

# 2. 如果 de4dot 报 "unknown" 或脱壳后打不开 → 新版/私改 ConfuserEx
#    先确认 anti-tamper:
dnSpyEx 打开 → 找 Module .cctor 或 Main 里的完整性校验

anti-tamper 绕过(新版 ConfuserEx 常见)

ConfuserEx 的 anti tamper 会在运行时校验方法体哈希,被改就崩。de4dot 通常能处理旧版,新版需手动:

方法 A — dnSpyEx 直接 patch 校验函数:
  1. 找 anti-tamper 校验方法(通常在 <module> 的静态构造里调用)
  2. IL 编辑:把校验方法体改成 ret(直接返回)
  3. 保存 → 再喂给 de4dot

方法 B — 运行时 dump:
  1. 用 MegaDumper / ExtremeDumper 跑起来 dump 内存中的 assembly
  2. dump 出来的已经解密,再用 de4dot 清理残留

控制流还原后

de4dot 会把平坦化的 switch dispatch 还原成正常 if/while。如果没完全还原(看到残留 state 机),可再跑一次 de4dot 或手动跟 IL。


SmartAssembly

de4dot --type sa target.exe -o target-clean.exe

特征:

  • 字符串用 SmartAssembly.Runtime.Strong 系列编码
  • 资源压缩({assembly}.Resources)
  • 方法调用隐藏(ProcessCaller / 间接 call)

de4dot 对 SmartAssembly 兼容性最好,基本一键搞定。


.NET Reactor(necrobit)

.NET Reactor 的 necrobit 把真实方法体加密存到资源,运行时解密注入,原方法体是空壳。de4dot 对老版本有效,新版本(4.x+)常失败。

当 de4dot 失败时:
1. 让程序跑起来(dotnet target.exe 或直接双击)
2. MegaDumper / ExtremeDumper dump 进程内存 → 导出解密后的 assembly
3. 用 de4dot 清理 dump 产物的残留混淆
4. 如果 metadata 损坏,用 dnlib 重建(见 common-workflow.md)

字符串解密器手动提取

混淆器把字符串加密,运行时调用解密方法还原。de4dot 多数能自动识别解密器,识别失败时手动:

1. dnSpyEx 找到解密方法(通常签名固定:static string Decrypt(int) 或 Decrypt(string, int))
   - 特征:被大量调用、参数是数字常量、返回 string
2. 记下方法 token(如 0x06000012)
3. de4dot 指定解密器:
   de4dot --strtyp delegate --strtok 0x06000012 target.exe -o target-clean.exe

如果连解密方法本身也被混淆(控制流平坦化),需要先脱控制流再定位解密器。

anti-debug 常见手法

手法 位置 绕过
Debugger.IsAttached 检查 任意方法 IL 改 ldc.i4.0; ret 或 patch getter
Debugger.IsLogging — 同上
时间检测 (DateTime.Now 差值) 方法入口 patch 掉差值比较
CheckRemoteDebuggerPresent P/Invoke — nop 掉调用
异常驱动控制流(try/catch 路径选择) 主逻辑 不能简单 nop,要分析 catch 块真实路径

.NET anti-debug 比 native 简单 —— 多数是托管 API 调用,dnSpyEx IL 改一行即可。

de4dot 失败时的退路

  1. de4dot --detect 看识别结果,对照上表
  2. 运行时 dump(MegaDumper / ExtremeDumper / Process Hacker 导出模块)
  3. dnlib 脚本 手动解(见 common-workflow.md 的 dnlib 段)
  4. 动态优先:跑起来在解密点下断,直接看明文,不脱壳也能拿情报

社区参考:Washi 博客《misconceptions-about-dotnet》(IL 分析的常见误区)、看雪 .NET 逆向版块、Guided Hacking《Top 5 .NET RE Tools》。