.NET 程序保护实战系列01-流水线架构与保护引擎总览
.NET 程序保护实战系列本系列文章基于 TWSoft.AssemblyProtector 保护引擎系统讲解 .NET 程序集的防护技术从流水线架构到每一层保护的实现原理。文章列表标题 核心内容01 流水线架构与保护引擎总览 三阶段流水线、ProtectOptions、多模块编排02 字符串加密让反编译器的搜索功能失效 Ldstr HOOK、XOR 块加密、xorshift32、不可见 Unicode03 符号混淆名称就是第一道防线 VTable 感知重命名、跨模块同步、6 种命名模式04 控制流混淆打乱逻辑让分析者绕路 基本块拆分、JumpMangler、不透明谓词05 代码虚拟化把 IL 变成只有你能懂的字节码 自定义 VM、栈式解释器、Token 名称反射06 方法体加密密钥在手才能执行的代码 DynamicMethod 解密、ILGenerator 重建 IL07 JIT Hook 保护在编译时刻解密 clrjit.dll Hook、Trampoline、哨兵 IL08 防篡改校验任何修改都会触发自毁 FNV-1a 方法体哈希、Environment.FailFast09 反调试与反转储让调试器无处下手 IsDebuggerPresent、PE 头归零、元数据销毁10 资源加密把 DLL 藏进保险箱 SPN 三阶段加密、xorshift128、AssemblyResolve11 类型注入无 DLL 依赖的运行时交付 InjectHelper 深度克隆、框架外观程序集重定向12 授权保护集成从保护到变现的闭环 验证器编译、入口点注入、多点验证、HMAC 签名适用读者.NET 开发者了解 IL 基本指令安全研究员对逆向工程有兴趣商业软件开发者需要保护知识产权技术栈dnlib — .NET 程序集读写库CIL — 通用中间语言指令C# Expression Trees / ILGenerator — 运行时代码生成本系列文章由 TWSoft.AssemblyProtector 保护引擎驱动。工具在全部完成后部分开源欢迎在 GitHub 关注。文章内容仅供技术学习请勿用于非法用途。01 · 流水线架构与保护引擎总览目录为什么要保护 .NET 程序保护引擎的核心设计理念三阶段流水线架构保护步骤注册与执行顺序ProtectOptions一个配置控制所有层ProtectionContext步骤间的共享数据总线ProtectionSession多模块协同保护AssemblyProtectorService顶层编排器从命令行到 GUI三种使用入口结语为什么要保护 .NET 程序.NET 程序编译为 IL中间语言附带完整的元数据——类名、方法签名、字段类型一览无余。使用 dnSpy、ILSpy 等工具可以几乎完整还原源代码。对于商业软件这意味着核心算法暴露、授权验证逻辑可被绕过、通信协议和 API 密钥泄露。我们的保护引擎提供了 全链条防护——从字符串加密到方法体加密、从反调试到代码虚拟化层层设防。保护引擎的核心设计理念2.1 无独立 DLL 依赖所有运行时助手类型在保护时通过 InjectHelper 深度克隆到目标程序集中。用户分发的受保护程序是完全自包含的没有任何额外的 .dll 文件。2.2 共享上下文多个保护步骤共享 ProtectionContext其中包含模块引用、随机数生成器、运行时类型服务、注入的用户类型等。这确保了步骤之间可以无缝协作。2.3 基于 dnlib使用 dnlib 库读写 .NET 程序集。dnlib 是 Mono.Cecil 的替代品在 ConfuserEx 等知名保护工具中广泛使用。三阶段流水线架构每个保护步骤实现 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) { }}三阶段执行流程// 阶段1Inject注入运行时— 所有启用步骤先集体执行foreach (var ctx in contexts){foreach (var step in steps.Where(s s.IsEnabled(ctx.Options)))step.Inject(ctx);}// 阶段2ExecuteIL 修改— 按 Order 从小到大顺序执行foreach (var step in steps.Where(s s.IsEnabled(ctx.Options)).OrderBy(s s.Order)){if (step.Order 90) break; // StrongName 跳过 Executeforeach (var ctx in contexts)step.Execute(ctx);}// 阶段3ConfigureWriter写入器配置foreach (var ctx in contexts){foreach (var step in steps.Where(s s.IsEnabled(ctx.Options)))step.ConfigureWriter(ctx, writerOptions);}为什么要分三个阶段 因为 Order 靠前的步骤注入的运行时类型可以被 Order 靠后的步骤保护。例如授权验证器Order5 注入在后续的字符串加密Order10和防篡改Order60中会被自动保护。保护步骤注册与执行顺序ProtectionPipeline 构造函数中注册了全部 10 个保护步骤public ProtectionPipeline(){_steps new List{new LicenseInjectionStep(), // Order5: 授权注入最先执行new StringEncryptionStep(), // Order10: 字符串加密new ObfuscationStep(), // Order20: 符号混淆new LogicObfuscationStep(), // Order30: 控制流混淆new VirtualizationStep(), // Order35: 代码虚拟化new MethodEncryptionStep(), // Order50: 方法体加密new JitHookStep(), // Order55: JIT Hooknew AntiTamperStep(), // Order60: 防篡改校验new AdditionalProtectionsStep(), // Order40: 附加保护反调试/反转储/资源加密/元数据混淆new StrongNameStep(), // Order90 写入阶段: 强名称签名};}每个步骤通过 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 DLLpublic required RuntimeService Runtime { get; init; } // 运行时类型加载public RandomService Random { get; set; } new(); // 共享随机数public ProtectionSession? Session { get; set; } // 多模块会话// 用户注入的类型如授权验证器会被后续步骤自动保护 public HashSetTypeDef UserTypes { get; } new(); // 执行日志 public Liststring 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. 加载所有模块 → 创建 ProtectionContextvar 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_KEY10. 结语本文概述了保护引擎的流水线架构。后续文章将逐层深入每一类保护的具体实现。下一篇将详细讲解字符串加密——这是最基础但最有效的第一道防线。