1. 为什么要保护 .NET 程序?
.NET 程序编译为 IL(中间语言),附带完整的元数据——类名、方法签名、字段类型一览无余。使用 dnSpy、ILSpy 等工具可以几乎完整还原源代码。对于商业软件,这意味着核心算法暴露、授权验证逻辑可被绕过、通信协议和 API 密钥泄露。
我们的保护引擎提供了 全链条防护——从字符串加密到方法体加密、从反调试到代码虚拟化,层层设防。
2. 保护引擎的核心设计理念
2.1 无独立 DLL 依赖
所有运行时助手类型在保护时通过 InjectHelper 深度克隆到目标程序集中。用户分发的受保护程序是完全自包含的,没有任何额外的 .dll 文件。
2.2 共享上下文
多个保护步骤共享 ProtectionContext,其中包含模块引用、随机数生成器、运行时类型服务、注入的用户类型等。这确保了步骤之间可以无缝协作。
2.3 基于 dnlib
使用 dnlib 库读写 .NET 程序集。dnlib 是 Mono.Cecil 的替代品,在 ConfuserEx 等知名保护工具中广泛使用。
3. 三阶段流水线架构
每个保护步骤实现 IProtectionStep 接口,包含三个可选方法:
public interface IProtectionStep
{
string Name { get; }
int Order { get; }
bool IsEnabled(ProtectOptions options);
void Inject(ProtectionContext context) { }
void Execute(ProtectionContext context);
void ConfigureWriter(ProtectionContext context, // 阶段3:配置写入器
ModuleWriterOptions options) { }
}
三阶段执行流程
foreach (var ctx in contexts)
{
foreach (var step in steps.Where(s => s.IsEnabled(ctx.Options)))
step.Inject(ctx);
}
foreach (var step in steps.Where(s => s.IsEnabled(ctx.Options))
.OrderBy(s => s.Order))
{
if (step.Order >= 90) break;
foreach (var ctx in contexts)
step.Execute(ctx);
}
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)中会被自动保护。
4. 保护步骤注册与执行顺序
ProtectionPipeline 构造函数中注册了全部 10 个保护步骤:
public ProtectionPipeline()
{
_steps = new List<IProtectionStep>
{
new LicenseInjectionStep(),
new StringEncryptionStep(),
new ObfuscationStep(),
new LogicObfuscationStep(),
new VirtualizationStep(),
new MethodEncryptionStep(),
new JitHookStep(),
new AntiTamperStep(),
new AdditionalProtectionsStep(),
new StrongNameStep(),
};
}
每个步骤通过 IsEnabled(opts) 决定是否启用:
public bool IsEnabled(ProtectOptions options) => options.EncryptStrings;
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; }
public bool VirtualizeMethods { get; set; }
public bool JitHook { get; set; }
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; }
public required ProtectOptions Options { get; init; }
public required string SourcePath { get; init; }
public required string OutputPath { get; init; }
public string TargetFramework { get; init; }
public bool IsNetCore { get; init; }
public bool IsExecutable { get; init; }
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<ProtectionContext> Contexts { get; }
public NameService? NameService { get; }
public RandomService Random { get; }
public void RunRename()
{
NameService?.AnalyzeAll();
NameService?.RenameAll();
}
}
8. AssemblyProtectorService:顶层编排器
public class AssemblyProtectorService
{
private IList<ProtectResult> ProtectMultipleCore(
List<string> inputs, string outputDir, ProtectOptions options)
{
var contexts = new List<ProtectionContext>();
foreach (var input in inputs)
{
var module = ModuleDefMD.Load(input);
var ctx = new ProtectionContext { Module = module, Options = options, ... };
contexts.Add(ctx);
}
var session = new ProtectionSession(contexts, options);
var pipeline = new ProtectionPipeline();
foreach (var ctx in contexts)
pipeline.Inject(ctx);
foreach (var ctx in contexts)
pipeline.Execute(ctx);
session.RunRename();
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. 结语
本文概述了保护引擎的流水线架构。后续文章将逐层深入每一类保护的具体实现。下一篇将详细讲解字符串加密——这是最基础但最有效的第一道防线。
本文由 TWSoft.AssemblyProtector 驱动。完整源码和工具请访问项目主页。
转自https://www.cnblogs.com/gsyifan/p/21161614
该文章在 2026/7/10 8:21:32 编辑过