Checking digital signature on EXE

谁说我不能喝 提交于 2019-12-28 12:29:13

问题


My .NET exe is signed using signtool. Using this code, I can verify the validity of the certificate itself:

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

However, this only checks the certificate itself, and not the signature of the EXE. Therefore, if the EXE is tampered with, this method doesn't detect it.

How can I check the signature?


回答1:


You need to call (P/Invoke) WinVerifyTrust() function from wintrust.dll. There is (as far as I know) no alternative in managed .NET.

You can find documentation of this method here.

Someone already asked this question on SO. It was not accepted, but it should be correct (I only scrolled through). Take a look.

You could also take a look at this guide but they really do the same.




回答2:


I searched github and found Azure Microsoft C# code that uses the PowerShell object to check for a valid Authenticode Signature.

    /// <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;
    }



回答3:


To validate the integrity of the signed .exe file, we can use StrongNameSignatureVerificationEx method:

[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!   
}

But it's not enough. It's possible to remove the signature and then apply/re-create it again! (there are a lot of tools to do that) In this case you need to store the public key of your signature somewhere (as a resource) and then compare it with the new/present public key. more info here



来源:https://stackoverflow.com/questions/24060009/checking-digital-signature-on-exe

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!