我编写了一个 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 注入的攻击。