我正在寻找正确的方法来验证该可执行文件中当前正在运行的可执行文件。 我已经找到了为当前运行的文件计算(SHA256)哈希的方法。
问题是:我在哪里安全存储此哈希?如果我将它存储在配置文件中,恶意用户可以只计算自己的哈希并替换它。如果我将它存储在可执行文件本身中,它可能会被十六进制编辑器覆盖。
我读到的一个建议是做一个不对称的en-(或者它是de-)加密,但我怎么会这样做呢?
要求是可执行代码在不同的计算机上进行哈希和/解密完全相同,否则我无法正确验证。这些计算机都将运行相同的操作系统,即Windows XP(嵌入式)。
我已经签署了所有程序集,但我需要一些额外的安全性才能成功通过我们的安全目标。
对于那些知道的人,它涉及 FPT_TST.1.3 :TSF应为授权用户提供验证存储的TSF可执行代码完整性的能力。
答案 0 :(得分:4)
所有评论,特别是Marc的评论都是有效的。
我认为最好的办法是查看authenticode签名 - 这就是他们的意思。关键是exe或dll是用证书签名的(将你的组织的信息标记在其中,很像SSL请求)和修改后的版本不能(理论上加上所有正常的安全警告)重新签名证书。
根据要求(我说这是因为这个'安全目标'有点粗糙 - 验证代码完整性的能力就像在Windows资源管理器中检查文件一样容易),这个本身就足够了(Windows具有从证书中显示发布者信息的内置功能),或者您可以编写例程来验证authenticode证书。
请参阅此SO Verify whether an executable is signed or not (signtool used to sign that exe),最常见的答案链接到一篇关于如何以编程方式检查authenticode证书的文章(不可否认的旧版)。
<强>更新强>
继续Marc的建议 - 如果需要进行自我编程检查,即使这样也是不够的。可以修改可执行文件,删除检查,然后在没有证书的情况下进行部署。因此杀了它。
说实话 - 主机应用程序/环境确实应该有自己的检查(例如,需要有效的authenticode证书) - 如果代码没有被修改那么重要那么它应该有自己的步骤所以。我想你可能真的在疯狂追逐。
只要把任何检查代表你做出最少的努力,而不必担心它显然提供的实际安全性 - 因为我认为你是从一个不可能的点开始。如果真的有任何人想要破解你所编写的代码的真正原因,那么它不仅仅是一个试图破解它的男生。因此,任何可用的解决方案(评论中提到的解决方案等)都将被轻易破坏。
租一个引用最后一句 解释我的'野鹅追逐'评论
遵循最薄弱的链接原则 - 可执行文件的完整性仅与运行该可执行文件的主机的安全性要求一样有效。
因此,在启用了UAC并打开所有安全功能的现代Windows机器上;例如,安装或运行未签名的代码非常困难。用户必须想要才能运行它。如果你把所有东西都降到零,那就相对简单了。在扎根的Android手机上,可以轻松运行可以杀死手机的东西。还有很多其他例子。
因此,如果您的代码将被部署到的XP嵌入式环境中没有运行时安全性检查它实际运行的内容(例如,需要所有应用程序的authenticode证书的策略)那么您从一个点开始我们继承了比实际应该提供的更低级别的安全性。没有多少安全原语和例程可以恢复它。
答案 1 :(得分: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 load事件并检查加载到(当前)应用程序域中的每个程序集:
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);
}
当然,有经验的人可以修改你的assemlby中的“检查代码”,或者只是从你的程序集中删除强名称。