11

我编写了一个 C# .NET 应用程序,它使用流行的非托管 DLL 文件来实现其部分功能。DLL 是使用 System.Runtime.InteropServices 中的标准 DllImport 导入的。

然而,不幸的是,我的应用程序(以及大多数使用 DllImport 的 .NET 应用程序)容易受到 DLL 劫持。即,攻击者可以将导入的 DLL 的恶意副本放置在与我的应用程序打开的任何文件相同的目录中。这可以让攻击者完全控制用户的机器。

为了缓解这个漏洞,我想在导入之前验证 DLL 文件是否已正确签名(使用默认 Authenticode)。我知道可以使用 sigcheck.exe 等工具验证签名,但这对我来说不是一个可行的解决方案,因为我需要在我的 C# 代码中进行验证。

所以我的问题很简单:在加载 DLL 之前,如何从我的托管 C# 代码中验证 DLL 是否具有有效的 Authenticode 签名?

限制:

  • 导入的 DLL 不是我开发的,它来自外部公司。
  • DLL 没有随我的应用程序一起分发,预计在运行我的应用程序之前已经安装。
  • 导入的 DLL 存在许多不同的版本(甚至会出现更多版本),所以我不能 在导入之前简单地验证 DLL 的 MD5 校验和。

失败的方法:

  • Microsoft 有一篇关于防止“DLL 预加载攻击”的精彩文章,但是,此信息不适用于 .NET 的 DllImport。
  • 我看到有人建议使用 Wintrust.dll 中的非托管函数 WinVerifyTrust。这当然是一个愚蠢的解决方案,因为那样会使我的应用程序容易受到通过 Wintrust.dll 进行 DLL 注入的攻击。
4

1 回答 1

1

您需要使用 Authenticode 验证器。此问题的答案提供使用 P/Invoke,如果您需要托管解决方案,您可能会对我们的SecureBlackbox库感兴趣,该库提供 Authenticode 签名和签名验证等功能。

然而,虽然您可以保护自己免受加载虚假 DLL 的侵害,但您无法保护应用程序本身不被破解。因此,签名验证当然只能保护您免受一种攻击媒介的侵害。

让我指出,替换 WinTrust.dll 取决于需要访问计算机的不同攻击向量。在这种情况下,攻击者可以完全修补您的应用程序。

于 2013-07-21T05:50:28.553 回答