.NET 程序保护实战系列01-流水线架构与保护引擎总览

📅 2026/7/10 12:37:45 👁️ 阅读次数 📝 编程学习
.NET 程序保护实战系列01-流水线架构与保护引擎总览

.NET 程序保护实战系列
本系列文章基于 TWSoft.AssemblyProtector 保护引擎,系统讲解 .NET 程序集的防护技术,从流水线架构到每一层保护的实现原理。

文章列表

标题 核心内容

01 流水线架构与保护引擎总览 三阶段流水线、ProtectOptions、多模块编排
02 字符串加密:让反编译器的搜索功能失效 Ldstr HOOK、XOR 块加密、xorshift32、不可见 Unicode
03 符号混淆:名称就是第一道防线 VTable 感知重命名、跨模块同步、6 种命名模式
04 控制流混淆:打乱逻辑让分析者绕路 基本块拆分、JumpMangler、不透明谓词
05 代码虚拟化:把 IL 变成只有你能懂的字节码 自定义 VM、栈式解释器、Token 名称反射
06 方法体加密:密钥在手才能执行的代码 DynamicMethod 解密、ILGenerator 重建 IL
07 JIT Hook 保护:在编译时刻解密 clrjit.dll Hook、Trampoline、哨兵 IL
08 防篡改校验:任何修改都会触发自毁 FNV-1a 方法体哈希、Environment.FailFast
09 反调试与反转储:让调试器无处下手 IsDebuggerPresent、PE 头归零、元数据销毁
10 资源加密:把 DLL 藏进保险箱 SPN 三阶段加密、xorshift128、AssemblyResolve
11 类型注入:无 DLL 依赖的运行时交付 InjectHelper 深度克隆、框架外观程序集重定向
12 授权保护集成:从保护到变现的闭环 验证器编译、入口点注入、多点验证、HMAC 签名
适用读者
.NET 开发者,了解 IL 基本指令
安全研究员,对逆向工程有兴趣
商业软件开发者,需要保护知识产权
技术栈
dnlib — .NET 程序集读写库
CIL — 通用中间语言指令
C# Expression Trees / ILGenerator — 运行时代码生成
本系列文章由 TWSoft.AssemblyProtector 保护引擎驱动。工具在全部完成后部分开源,欢迎在 GitHub 关注。文章内容仅供技术学习,请勿用于非法用途。

01 · 流水线架构与保护引擎总览
目录
为什么要保护 .NET 程序?
保护引擎的核心设计理念
三阶段流水线架构
保护步骤注册与执行顺序
ProtectOptions:一个配置控制所有层
ProtectionContext:步骤间的共享数据总线
ProtectionSession:多模块协同保护
AssemblyProtectorService:顶层编排器
从命令行到 GUI:三种使用入口
结语

  1. 为什么要保护 .NET 程序?
    .NET 程序编译为 IL(中间语言),附带完整的元数据——类名、方法签名、字段类型一览无余。使用 dnSpy、ILSpy 等工具可以几乎完整还原源代码。对于商业软件,这意味着核心算法暴露、授权验证逻辑可被绕过、通信协议和 API 密钥泄露。

我们的保护引擎提供了 全链条防护——从字符串加密到方法体加密、从反调试到代码虚拟化,层层设防。

  1. 保护引擎的核心设计理念
    2.1 无独立 DLL 依赖
    所有运行时助手类型在保护时通过 InjectHelper 深度克隆到目标程序集中。用户分发的受保护程序是完全自包含的,没有任何额外的 .dll 文件。

2.2 共享上下文
多个保护步骤共享 ProtectionContext,其中包含模块引用、随机数生成器、运行时类型服务、注入的用户类型等。这确保了步骤之间可以无缝协作。

2.3 基于 dnlib
使用 dnlib 库读写 .NET 程序集。dnlib 是 Mono.Cecil 的替代品,在 ConfuserEx 等知名保护工具中广泛使用。

  1. 三阶段流水线架构
    每个保护步骤实现 IProtectionStep 接口,包含三个可选方法:

public interface IProtectionStep
{
string Name { get; } // 步骤名称
int Order { get; } // 执行顺序(数值越小越先执行)
bool IsEnabled(ProtectOptions options); // 是否启用

void Inject(ProtectionContext context) { } // 阶段1:注入运行时类型 void Execute(ProtectionContext context); // 阶段2:执行 IL 修改 void ConfigureWriter(ProtectionContext context, // 阶段3:配置写入器 ModuleWriterOptions options) { }

}
三阶段执行流程
// 阶段1:Inject(注入运行时)— 所有启用步骤先集体执行
foreach (var ctx in contexts)
{
foreach (var step in steps.Where(s => s.IsEnabled(ctx.Options)))
step.Inject(ctx);
}

// 阶段2:Execute(IL 修改)— 按 Order 从小到大顺序执行
foreach (var step in steps.Where(s => s.IsEnabled(ctx.Options))
.OrderBy(s => s.Order))
{
if (step.Order >= 90) break; // StrongName 跳过 Execute
foreach (var ctx in contexts)
step.Execute(ctx);
}

// 阶段3:ConfigureWriter(写入器配置)
foreach (var ctx in contexts)
{
foreach (var step in steps.Where(s => s.IsEnabled(ctx.Options)))
step.ConfigureWriter(ctx, writerOptions);
}
为什么要分三个阶段? 因为 Order 靠前的步骤注入的运行时类型,可以被 Order 靠后的步骤保护。例如授权验证器(Order=5 注入)在后续的字符串加密(Order=10)和防篡改(Order=60)中会被自动保护。

  1. 保护步骤注册与执行顺序
    ProtectionPipeline 构造函数中注册了全部 10 个保护步骤:

public ProtectionPipeline()
{
_steps = new List
{
new LicenseInjectionStep(), // Order=5: 授权注入(最先执行)
new StringEncryptionStep(), // Order=10: 字符串加密
new ObfuscationStep(), // Order=20: 符号混淆
new LogicObfuscationStep(), // Order=30: 控制流混淆
new VirtualizationStep(), // Order=35: 代码虚拟化
new MethodEncryptionStep(), // Order=50: 方法体加密
new JitHookStep(), // Order=55: JIT Hook
new AntiTamperStep(), // Order=60: 防篡改校验
new AdditionalProtectionsStep(), // Order=40: 附加保护(反调试/反转储/资源加密/元数据混淆)
new StrongNameStep(), // Order=90 写入阶段: 强名称签名
};
}
每个步骤通过 IsEnabled(opts) 决定是否启用:

// 字符串加密:由 EncryptStrings 开关控制
public bool IsEnabled(ProtectOptions options) => options.EncryptStrings;

// 混淆:由 Obfuscate 开关控制
public bool IsEnabled(ProtectOptions options) => options.Obfuscate;
5. ProtectOptions:一个配置控制所有层
ProtectOptions 是所有保护步骤的控制中心:

public class ProtectOptions
{
// === 字符串加密 ===
public bool EncryptStrings { get; set; } // 总开关
public string StringMode { get; set; } = “DelegateProxy”; // 编码模式

// === 混淆 === public bool Obfuscate { get; set; } public string RenameMode { get; set; } = "Unicode"; public bool RenameNamespaces { get; set; } public bool RenameTypes { get; set; } public bool RenameMethods { get; set; } public bool RenameProperties { get; set; } public bool RenameFields { get; set; } public bool RenameParameters { get; set; } public bool RenamePublic { get; set; } public bool RenamePrivate { get; set; } public bool FlattenNamespaces { get; set; } // === 控制流 === public bool ObfuscateLogic { get; set; } // === 方法保护(三选一,互斥) === public bool EncryptMethods { get; set; } // DynamicMethod 解密 public bool VirtualizeMethods { get; set; } // 虚拟化 public bool JitHook { get; set; } // JIT Hook // === 授权 === public bool LicenseProtection { get; set; } public LicenseOptions License { get; set; } // === 其他 === public bool AntiTamper { get; set; } public bool Additional { get; set; } // 总开关 public bool AntiDebug { get; set; } public bool AntiDump { get; set; } public bool EncryptResources { get; set; } public bool MetadataConfusion { get; set; } public string? SnkPath { get; set; } // 强签名密钥路径

}
6. ProtectionContext:步骤间的共享数据总线
public class ProtectionContext
{
public required ModuleDefMD Module { get; init; } // dnlib 模块引用
public required ProtectOptions Options { get; init; } // 保护选项
public required string SourcePath { get; init; } // 源文件路径
public required string OutputPath { get; init; } // 输出路径
public string TargetFramework { get; init; } // “net48”, “net8.0” 等
public bool IsNetCore { get; init; } // .NET Core 标志
public bool IsExecutable { get; init; } // EXE vs DLL
public required RuntimeService Runtime { get; init; } // 运行时类型加载
public RandomService Random { get; set; } = new(); // 共享随机数
public ProtectionSession? Session { get; set; } // 多模块会话

// 用户注入的类型(如授权验证器),会被后续步骤自动保护 public HashSet<TypeDef> UserTypes { get; } = new(); // 执行日志 public List<string> Logs { get; } = new();

}
7. ProtectionSession:多模块协同保护
public class ProtectionSession
{
public IList Contexts { get; } // 所有模块上下文
public NameService? NameService { get; } // 跨模块共享名称服务
public RandomService Random { get; } // 跨模块共享随机数

// 在所有模块 Execute 之后统一重命名 public void RunRename() { // AnalyzeAll: 收集所有模块可重命名成员 + 构建 VTable // RenameAll: 统一分配新名称 + 更新所有引用 NameService?.AnalyzeAll(); NameService?.RenameAll(); }

}
8. AssemblyProtectorService:顶层编排器
public class AssemblyProtectorService
{
private IList ProtectMultipleCore(
List inputs, string outputDir, ProtectOptions options)
{
// 1. 加载所有模块 → 创建 ProtectionContext
var contexts = new List();
foreach (var input in inputs)
{
var module = ModuleDefMD.Load(input);
var ctx = new ProtectionContext { Module = module, Options = options, … };
contexts.Add(ctx);
}

// 2. 创建会话(共享 NameService + RandomService) var session = new ProtectionSession(contexts, options); var pipeline = new ProtectionPipeline(); // 3. 阶段1:注入运行时 foreach (var ctx in contexts) pipeline.Inject(ctx); // 4. 阶段2:执行 IL 修改(按 Order 排序) foreach (var ctx in contexts) pipeline.Execute(ctx); // 5. 跨模块重命名 session.RunRename(); // 6. 阶段3:写入器配置 + 保存 foreach (var ctx in contexts) { var writeOptions = new ModuleWriterOptions(ctx.Module); pipeline.ConfigureWriter(ctx, writeOptions); ctx.Module.Write(ctx.OutputPath, writeOptions); } }

}
9. 从命令行到 GUI:三种使用入口
入口 类型 技术 适用场景
TWProtector.CLI 命令行 .NET 10 Console CI/CD 自动化
TWProtector (GUI) 桌面 Avalonia 12 跨平台可视化
TWProtector (WPF) 桌面 WPF Windows 原生体验
命令行示例:

TWProtector.CLI --input MyApp.exe --output ./protected
–preset all --encrypt-strings --obfuscate
–license --online --api-url http://server:5159
–software-key YOUR_KEY
10. 结语
本文概述了保护引擎的流水线架构。后续文章将逐层深入每一类保护的具体实现。下一篇将详细讲解字符串加密——这是最基础但最有效的第一道防线。