我是否认为如果我对一个引用几个 dll(非强命名)的 exe 进行代码签名,恶意用户可以替换我的 DLL 并以看起来好像是由我签名但正在运行的方式分发应用程序他们的代码?
是的,如果 DLL 的其余部分仅经过签名而不是强命名,则它们可以被替换,而 .NET 不会引发异常。您可以在 exe 中验证 DLL 是由与 exe 相同的密钥签名的。这些方法都不能阻止某人替换您的 DLL 或 EXE。
假设这是真的,您似乎真的不想在没有强命名整个事情的情况下签署 .NET 应用程序,否则您让人们能够以您编写的应用程序为幌子执行代码?
一般来说,我认为这是“最佳做法”,但同样你并没有阻止任何事情。一旦用户有权更改本地系统上的文件,您就无法阻止他们进行恶意活动。
有几种混淆技术可以将完整的 .NET 项目构建到单个 exe 中,这可能是“最安全”的方法,但仍然可以被篡改。
真正的问题是你试图阻止他们做什么?我的意思是说,为什么有人会对替换您的 dll 感兴趣?他们希望达到什么目标,他们的目标是什么?如果您试图阻止某人从您的过程中读取敏感信息,那么您将面临漫长而艰难的失望之路。假设恶意方可以完全访问您的源代码以及您的进程使用的每条信息,因为他们确实如此。假设他们可以随意替换您的全部或部分代码,因为他们可以。
更新
所以绑定重定向只适用于具有相同密钥的强命名程序集,因此可以保护您免受 DLL 被更改的影响吗?
正确,除了注意到代码注入仍然可以通过多种方式完成的例外。
...回到最初的问题,没有强命名的代码签名会破坏代码签名的意义吗?
并不真地。代码签名(不是强命名)有两个不同的目的:
- 验证。验证软件的作者是谁。
- 正直。验证软件自签名后未被篡改。
通常这仅在安装期间进行身份验证和验证。这就是我们签署 setup.exe 的原因,以确保客户收到我们提供的未经修改的安装程序。系统会提示他们“您信任 XXXX 公司吗”,从而向经过身份验证/签名的安装程序授予授权。然而,一旦安装,操作系统几乎没有内置使用代码签名(驱动程序和其他一些晦涩的情况除外)。
另一方面,强命名的存在目的完全不同。它完全专注于应用程序的“完整性”。没有证书,没有签名授权 (CA) 来验证它,没有用户显示的信息供他们确认,操作系统也无法验证它将运行的可执行文件。
.NET 框架在很多事情上都使用了强名称,所有这些我都松散地归类为应用程序完整性:
- dll/exe 的内容有一个签名的哈希,因此它不能被篡改。
- 在加载依赖项时,每个引用都必须是强命名和验证的。
- 程序集可以在 GAC 中注册,并且可以使用发布者策略。
- 可以对本机映像进行生成以生成程序集 IL 的编译映像。
我敢肯定这里还有其他我遗漏的东西,但这些是我知道的主要用途。
签名和强命名的最佳实践
- 使用签名的安装程序
- 使用代码签名的可执行文件
- 使用强命名的可执行文件
- 强命名所有依赖项和对它们的引用
- 通常不需要代码签名依赖项*
- 考虑 GAC 在安装时注册程序集
*注意:代码签名在某些情况下对 DLL 很有用,例如,标记为“安全”并嵌入到浏览器中的 COM 对象应该像可执行文件一样进行签名和强命名。代码签名也可用于外部验证依赖关系,而无需加载程序集或反映其属性。