2014-06-05 17 views
11

我的.NET exe文件使用signtool進行簽名。使用此代碼 ,我可以驗證證書本身的有效性:在EXE上檢查數字簽名

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

然而,這僅檢查證書本身和EXE的未簽名。因此,如果EXE被篡改,該方法不會檢測到它。

我該如何檢查簽名?

+0

'X509Certificate.CreateFromSignedFile(「」)。Verify()'? – Sinatr

+0

.CreateFromSignedFile返回X509Certificate的一個實例,但沒有.Verify方法。 – LTR

+0

好吧,那麼另一個愚蠢的想法:通過使用'X509Certificate',而不是'Handle'構造'X509Certificate2'。我猜測:'Verify'方法*應該*檢查文件,否則證書會在包含exe文件被篡改時拋出異常(當實例化時)。也許你必須實現自己的驗證[鏈接](http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx)。 – Sinatr

回答

9

您需要致電(P/Invoke)WinVerifyTrust()功能wintrust.dll。有(據我所知)在託管的.NET中沒有其他選擇。

你可以找到這種方法的文件here

有人已經在SO上提過這個問題。它沒有被接受,但它應該是正確的(我只是滾動瀏覽)。 Take a look.

你也可以看看this guide,但他們確實也這樣做。

+0

謝謝!我想如果你可以從EXE加載簽名並使用X590Certificate類驗證鏈,那麼也必須有一些方法來檢查文件的完整性。將隨P/Invoke一起去。 – LTR

1

爲了驗證簽名的.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! 
} 

但是這還不夠。可以刪除簽名,然後重新應用/重新創建! (有很多工具可以這樣做)在這種情況下,您需要將簽名的公鑰存儲在某處(作爲資源),然後將其與新/當前公鑰進行比較。 more info here

+6

由Signtool和強名稱進行的Authenticode簽名是兩回事。 –

1

我搜索了github,發現Azure Microsoft C#code使用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; 
    }