问题 检查EXE上的数字签名


我的.NET exe是使用signtool签名的。 使用此代码,我可以验证证书本身的有效性:

var cert = X509Certificate.CreateFromSignedFile("application.exe");
var cert2 = new X509Certificate2(cert.Handle);
bool valid = cert2.Verify();

但是,这仅检查证书本身,而不检查EXE的签名。因此,如果EXE被篡改,则此方法不会检测到它。

我该如何查看签名?


7434
2018-06-05 12:16


起源

X509Certificate.CreateFromSignedFile("").Verify() ? - Sinatr
.CreateFromSignedFile返回X509Certificate的实例,并且没有.Verify方法。 - LTR
好吧,那么另一个愚蠢的想法:构建 X509Certificate2 通过使用 X509Certificate不是 Handle。我在猜测: Verify 方法 应该 如果包含exe文件被篡改,那么也检查文件或证书将抛出异常(当实例化时?)也许你必须实现自己的验证 链。 - Sinatr
通过此EXE检查EXE的签名是没有意义的 - 删除签名的人也将删除该检查。 - Eugene Mayevski 'Allied Bits
我发布了一个纯粹的.Net解决方案 这里。 - OSH


答案:


你需要打电话(P / Invoke) WinVerifyTrust() 功能来自 wintrust.dll。 (据我所知)在托管.NET中没有其他选择。

您可以找到此方法的文档 这里

有人已经问过这个问题了。它不被接受,但它应该是正确的(我只滚动)。 看一看。

你也可以看看 本指南 但他们真的这样做。


10
2018-06-05 15:21



谢谢!我想如果你可以从EXE加载签名并使用X590Certificate类验证链,那么必须有一些方法来检查文件的完整性。然后会使用P / Invoke。 - LTR


要验证签名.exe文件的完整性,我们可以使用StrongNameSignatureVerificationEx方法:

[DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
public static extern bool StrongNameSignatureVerificationEx(
        string wszFilePath, bool fForceVerification, ref bool pfWasVerified);    

var assembly = Assembly.GetExecutingAssembly();
bool pfWasVerified = false;
if (!StrongNameSignatureVerificationEx(assembly.Location, true, ref pfWasVerified))
{           
    // it's a patched .exe file!   
}

但这还不够。可以删除签名,然后再次应用/重新创建它! (有很多工具可以做到这一点)在这种情况下,您需要将签名的公钥存储在某处(作为资源),然后将其与新/当前公钥进行比较。 更多信息在这里


1
2018-06-05 14:23



Signtool制作的Authenticode签名和强命名是两回事。 - Eugene Mayevski 'Allied Bits


我搜索了github并找到了Azure Microsoft C#  使用PowerShell对象检查有效的Authenticode签名。

    /// <summary>
    /// Check for Authenticode Signature
    /// </summary>
    /// <param name="providedFilePath"></param>
    /// <returns></returns>
    private bool VerifyAuthenticodeSignature(string providedFilePath)
    {
        bool isSigned = true;
        string fileName = Path.GetFileName(providedFilePath);
        string calculatedFullPath = Path.GetFullPath(providedFilePath);

        if (File.Exists(calculatedFullPath))
        {
            Log.LogMessage(string.Format("Verifying file '{0}'", calculatedFullPath));
            using (PowerShell ps = PowerShell.Create())
            {
                ps.AddCommand("Get-AuthenticodeSignature", true);
                ps.AddParameter("FilePath", calculatedFullPath);
                var cmdLetResults = ps.Invoke();

                foreach (PSObject result in cmdLetResults)
                {
                    Signature s = (Signature)result.BaseObject;
                    isSigned = s.Status.Equals(SignatureStatus.Valid);
                    if (isSigned == false)
                    {
                        ErrorList.Add(string.Format("!!!AuthenticodeSignature status is '{0}' for file '{1}' !!!", s.Status.ToString(), calculatedFullPath));
                    }
                    else
                    {
                        Log.LogMessage(string.Format("!!!AuthenticodeSignature status is '{0}' for file '{1}' !!!", s.Status.ToString(), calculatedFullPath));
                    }
                    break;
                }
            }
        }
        else
        {
            ErrorList.Add(string.Format("File '{0}' does not exist. Unable to verify AuthenticodeSignature", calculatedFullPath));
            isSigned = false;
        }

        return isSigned;
    }

1
2017-10-10 14:28