4

我正在寻找正确的方法来从该可执行文件中验证当前正在运行的可执行文件。我已经找到了一种为当前正在运行的文件计算(SHA256)哈希的方法。

问题是:我在哪里安全地存储这个哈希?如果我将它存储在配置文件中,恶意用户可以计算自己的哈希并替换它。如果我将它存储在可执行文件本身中,它可能会被十六进制编辑器覆盖。

我读到的一个建议是进行非对称加密(或者是去加密),但是我该怎么做呢?

要求是可执行代码在不同计算机上的哈希和加密/解密完全相同,否则我无法正确验证。这些计算机都将运行相同的操作系统,即 Windows XP(嵌入式)。

我已经签署了我所有的程序集,但我需要一些额外的安全性才能成功通过我们的安全目标。

对于那些知道的人,它涉及FPT_TST.1.3:TSF 应为授权用户提供验证存储的 TSF 可执行代码完整性的能力。

4

2 回答 2

4

所有评论,尤其是 Marc 的评论,都是有效的。

我认为你最好的选择是查看验证码签名——这就是它们的目的。关键是 exe 或 dll 使用证书进行签名(将您的组织信息印入其中,就像 SSL 请求一样)并且修改后的版本不能(理论上加上所有正常的安全警告)用相同的证书重新签名证书。

根据要求(我这样说是因为这个“安全目标”有点模糊——验证代码完整性的能力可以很容易地成为如何在 Windows 资源管理器中检查文件的演练),这要么就足够了本身(Windows 具有从证书显示发布者信息的内置功能),或者您可以编写例程来验证身份验证码证书。

请参阅此 SO验证可执行文件是否已签名(signtool used to sign that exe),最佳答案链接到一篇(诚然旧的)关于如何以编程方式检查身份验证证书的文章。

更新

按照 Marc 的建议进行 - 如果需要自编程检查,即使这样也不够。可执行文件可以被修改,删除检查,然后在没有证书的情况下部署。从而杀死它。

老实说 - 主机应用程序/环境确实应该有自己的检查(例如,需要有效的身份验证证书) - 如果不修改代码非常重要,那么它应该有自己的步骤。我想你可能真的是在疯狂追逐。

只需代表您进行任何检查将花费最少的精力,而不必过多担心它显然提供的实际安全性 - 因为我认为您是从一个不可能的点开始的。如果真的有人想要破解您编写的代码的任何真正原因,那么试图破解它的将不仅仅是一个小学生。因此,您可以使用的任何解决方案(评论等中提到的那些)都将很容易被颠覆。

Rent-a-quote 最后一句话 解释了我的“野鹅追逐”评论

遵循最弱链接原则 - 可执行文件的完整性仅与运行该可执行文件的主机的安全要求一样有效。

因此,在打开 UAC 并打开所有安全功能的现代 Windows 机器上;例如,安装或运行未签名的代码非常困难。用户必须真的想要运行它。如果你把所有这些东西都降为零,那么它就相对简单了。在有根的 Android 手机上,很容易运行可以杀死手机的东西。这方面还有很多其他的例子。

因此,如果您的代码将被部署到的 XP Embedded 环境首先没有对其实际运行的内容进行运行时安全检查(例如,要求所有应用程序的身份验证码证书的策略),那么您将从继承的点开始比您实际应该提供的安全级别低。没有多少安全原语和例程可以恢复它。

于 2013-01-04T09:09:25.387 回答
2

从 .NET 3.5 SP1 开始,运行时不检查强名称签名。当您的程序集是强命名时,我建议通过代码检查签名。将本机mscoree.dll与 p/Invoke 一起使用。

private static class NativeMethods
{
      [DllImport("mscoree.dll")]
      public static extern bool StrongNameSignatureVerificationEx([MarshalAs(UnmanagedType.LPWStr)] string wszFilePath, byte dwInFlags, ref byte pdwOutFlags);
}

您可以使用 assemlby 加载事件并检查加载到您的(当前)应用程序域中的每个程序集:

AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;

private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
    Assembly loadedAssembly = args.LoadedAssembly;

    if (!VerifytrongNameSignature(loadedAssembly))
        // Do whatever you want when the signature is broken.
}

private static bool VerifytrongNameSignature(Assembly assembly)
{
     byte wasVerified = 0;

     return NativeMethods.StrongNameSignatureVerificationEx(assembly.Location, 1, ref wasVerified);
}

当然,有足够经验的人可以从你的程序集中修补“检查代码”,或者干脆从你的程序集中去掉强名称。

于 2013-01-04T10:59:02.697 回答