2014-06-05 15 views
11

Mój. NET exe jest podpisany przy użyciu signtool. Za pomocą tego kodu, mogę sprawdzić ważność certyfikatu samego:Sprawdzanie podpisu cyfrowego na EXE

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

Jednak ta sprawdza tylko samego certyfikatu, a nie podpisania EXE. Dlatego, jeśli plik EXE jest modyfikowany, ta metoda go nie wykrywa.

Jak mogę sprawdzić podpis?

+0

'X509Certificate.CreateFromSignedFile (" "). Zweryfikować()'? – Sinatr

+0

.CreateFromSignedFile zwraca instancję certyfikatu X509, która nie ma metody .Verify. – LTR

+0

OK, to kolejny głupi pomysł: skonstruuj 'X509Certificate2' za pomocą' X509Certificate', a nie 'Handle'. Zgaduję: metoda "weryfikująca" * powinna * również sprawdzać plik lub certyfikat wyrzuci wyjątek (podczas tworzenia instancji?), Jeśli plik exe zostanie zmodyfikowany. Być może musisz zaimplementować własną walidację [łańcuch] (http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx). – Sinatr

Odpowiedz

9

Musisz zadzwonić (P/Invoke) WinVerifyTrust() funkcja z wintrust.dll. Nie ma (o ile mi wiadomo) żadnej alternatywy w zarządzanym .NET.

Możesz znaleźć dokumentację tej metody here.

Ktoś już zadał to pytanie na SO. Nie zostało zaakceptowane, ale powinno być poprawne (przewinąłem tylko). Take a look.

Można również rzucić okiem na this guide, ale oni naprawdę robią to samo.

+0

Dziękujemy! Pomyślałem, że jeśli możesz załadować sygnaturę z EXE i zweryfikować łańcuch za pomocą klasy X590Certificate, musi być jakiś sposób na sprawdzenie integralności pliku. Pójdzie z P/Invoke następnie. – LTR

1

Aby sprawdzić integralność podpisanego pliku .exe, możemy użyć metody 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! 
} 

Ale to nie wystarczy. Możliwe jest usunięcie podpisu, a następnie ponowne zastosowanie/ponowne utworzenie! (jest na to dużo narzędzi) W tym przypadku musisz przechowywać klucz publiczny swojego podpisu (jako zasób), a następnie porównać go z nowym/obecnym kluczem publicznym. more info here

+6

Podpis Authenticode autorstwa Signtool i silna nazwa to dwie różne rzeczy. –

1

Szukałem github i znalazłem Azure Microsoft C# code, który używa obiektu PowerShell, aby sprawdzić poprawny podpis 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; 
    }