.NET Core中如何防止DLL被替换?(程序集签名方案)
确保.NET Core应用仅运行指定DLL集合的方案
可以通过以下几种方式实现需求:
1. 程序集签名与验证
- 给所有要限制的DLL做强名称签名,用你自己的密钥对。未经你签名的DLL会因强名称验证失败,无法被应用加载。
- 应用启动时手动校验加载的程序集:遍历当前加载的所有程序集,检查其公钥是否与你指定的匹配。示例代码:
using System.Reflection; using System.Security.Cryptography; public static void ValidateAssemblies() { var allowedPublicKey = Convert.FromBase64String("你的公钥字符串"); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (assembly.IsDynamic) continue; var publicKey = assembly.GetName().GetPublicKey(); if (publicKey != null && !publicKey.SequenceEqual(allowedPublicKey)) { throw new InvalidOperationException($"非法程序集:{assembly.FullName}"); } } }
- 注意:强名称签名能挡住大部分普通用户替换DLL的操作,但存在被专业人士绕过的可能。
2. 打包为单文件应用
- 用.NET Core的单文件发布功能,把所有依赖DLL和应用程序打包成单个可执行文件。客户无法单独替换某一个DLL,因为所有内容都整合在一个文件里。
- 发布命令示例:
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true
- 还可以配合压缩和裁剪功能,进一步缩小体积并强化完整性。
3. 运行时程序集加载限制
- 自定义
AssemblyLoadContext,控制应用只从指定目录加载程序集,且仅加载符合你预先定义的名称和哈希值的文件。 - 加载前先计算文件的SHA256哈希值,和预存的合法哈希值对比,不匹配就拒绝加载。示例代码片段:
using System.IO; using System.Security.Cryptography; public static bool IsValidAssembly(string path, byte[] expectedHash) { using var sha256 = SHA256.Create(); using var stream = File.OpenRead(path); var hash = sha256.ComputeHash(stream); return hash.SequenceEqual(expectedHash); }
4. 代码混淆与保护工具
- 使用商业.NET代码保护工具(比如ConfuserEx、Dotfuscator等),给DLL做混淆和加密。这类工具能阻止反编译和篡改,还能设置加载验证规则,确保只有受保护的程序集才能被加载。
需要说明的是,没有绝对无懈可击的防护方案,以上方法主要是提高篡改门槛,对普通用户或非专业攻击者有效。如果遇到专业逆向工程师,仍可能被绕过,但足以覆盖大部分业务场景的需求。
内容的提问来源于stack exchange,提问作者Florian Boehmak
相关产品推荐
相关产品推荐

