我编写了一个 C# .NET 应用程序,它使用流行的非托管 DLL 文件来实现其部分功能。 DLL 是使用来自 System.Runtime.InteropServices 的标准 DllImport 导入的。
但是,不幸的是,我的应用程序(以及大多数使用 DllImport 的 .NET 应用程序)容易受到 DLL 劫持。 IE。攻击者可以将导入的 DLL 的恶意副本放置在与我的应用程序打开的任何文件相同的目录中。 这可能会让攻击者完全控制用户的机器。
为了缓解此漏洞,我想在导入 DLL 文件之前验证它是否已正确签名(使用默认 Authenticode)。 我知道可以使用 sigcheck.exe 等工具验证签名,但这对我来说不是一个可行的解决方案,因为我需要在我的 C# 代码中执行此操作。
所以我的问题很简单:在加载 DLL 之前,如何从我的托管 C# 代码中验证 DLL 是否具有有效的 Authenticode 签名?
限制:
- 导入的 DLL 不是我开发的,它来自外部公司。
- DLL 未随我的应用程序分发,预计在运行我的应用程序之前已安装。
- 导入的 DLL 有很多不同的版本(以后还会有更多),所以我不能简单地 verify an MD5 checksum of the DLL在导入之前。
失败的方法:
- Microsoft 在 preventing "DLL preloading attacks" 上有一篇很好的文章, 但是,此信息不适用于 .NET 的 DllImport。
- 我看到有人建议使用 Wintrust.dll 中的非托管函数 WinVerifyTrust。 这当然是一个愚蠢的解决方案,因为这反而会使我的应用程序容易受到通过 Wintrust.dll 进行的 DLL 注入(inject)攻击。
最佳答案
您需要使用 Authenticode 验证程序。 this question的答案提供使用 P/Invoke 如果您需要托管解决方案,您可能会对我们的 SecureBlackbox 感兴趣库,除其他功能外,还提供 Authenticode 签名和签名验证。
但是,虽然您可以保护自己免受加载虚假 DLL 的侵害,但您无法保护应用程序本身免遭破解。因此,签名验证当然只能保护您免受一种攻击。
让我指出,替换 WinTrust.dll 取决于需要访问计算机的不同攻击媒介。在这种情况下,攻击者可以完全修补您的应用程序。
关于c# - 如何在 .NET 中验证 DLL 的数字签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17766592/