2014-06-05 27 views
11

My .NET exe è stato firmato utilizzando signtool. Utilizzando questo codice, posso verificare la validità del certificato stesso:Controllo firma digitale su EXE

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

Tuttavia, questo controlla solo il certificato stesso, e non la firma del file EXE. Pertanto, se l'EXE viene manomesso, questo metodo non lo rileva.

Come posso verificare la firma?

+0

'X509Certificate.CreateFromSignedFile (""). Verificare()'? – Sinatr

+0

.CreateFromSignedFile restituisce un'istanza di X509Certificate e non ha un metodo .Verify. – LTR

+0

Ok, allora un'altra stupida idea: costruire 'X509Certificate2' usando' X509Certificate', non 'Handle'. Sto indovinando: il metodo 'Verify' * dovrebbe * controllare anche il file o il certificato genererà un'eccezione (in caso di istanziazione?) Se il file exe è stato manomesso. Forse è necessario implementare la propria convalida [catena] (http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx). – Sinatr

risposta

9

È necessario chiamare (P/Invoke) la funzione WinVerifyTrust() da wintrust.dll. C'è (per quanto ne so) nessuna alternativa in .NET gestito.

È possibile trovare la documentazione di questo metodo here.

Qualcuno ha già fatto questa domanda su SO. Non è stato accettato, ma dovrebbe essere corretto (ho solo sfogliato). Take a look.

Si potrebbe anche dare un'occhiata a this guide ma fanno davvero lo stesso.

+0

Grazie! Ho pensato che se è possibile caricare la firma dal file EXE e verificare la catena utilizzando la classe X590Certificate, ci deve essere un modo per controllare anche l'integrità del file. Andrà con P/Invoke quindi. – LTR

1

per convalidare l'integrità del file exe firmato, siamo in grado di utilizzare il metodo 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! 
} 

Ma non è abbastanza. È possibile rimuovere la firma e quindi applicarla/ricrearla di nuovo! (ci sono molti strumenti per farlo) In questo caso è necessario memorizzare la chiave pubblica della firma da qualche parte (come risorsa) e quindi confrontarla con la nuova/pubblica chiave pubblica. more info here

+6

La firma Authenticode fatta da Signtool e i nomi forti sono due cose diverse. –

1

Ho cercato github e ho trovato Azure Microsoft C# code che utilizza l'oggetto PowerShell per verificare una firma Authenticode valida.

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