2014-06-05 2 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

Хорошо, тогда еще одна глупая идея: постройте 'X509Certificate2', используя' X509Certificate', а не 'Handle'. Я предполагаю: метод '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

Подпись Authenticode, сделанная Signtool и сильным названием, - это две разные вещи. –

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; 
    } 
Смежные вопросы