2009-08-17 6 views
3

Ich versuche, einen Weg zu finden, Skript (vorzugsweise in Perl) - eine Überprüfung, ob eine. Exe oder .dll digital signiert ist - wenn jemand eine einfache Richtung hat, um mich zu zeigen, würde ich es begrüßen.Wie kann ich die digitale Signatur einer .exe oder .dll in Perl überprüfen?

+2

Dies ist im Grunde "ist ein Modul-Dateiformat x zu analysieren" ... das ist sehr verschieden von einem pls-send-me-the- Codes Frage, also würde ich geneigt sein, dieses Tag zu entfernen. Es sollte sicherlich nicht geschlossen werden. – ysth

Antwort

3

Eine Idee ist, the sample program on MSDN mit Win32::API zu übersetzen.

Update: Ich habe einen Stich bei der Übersetzung des Beispielprogramms von MSDN. Aus irgendeinem Grund gibt der Aufruf 0x800B0001 (=TRUST_E_PROVIDER_UNKNOWN) für Dateien, die ordnungsgemäß mit dem Win32-Beispielcode überprüfen, zurück. Ich schreibe das Skript hier, falls jemand meinen Fehler entdecken könnte.

Beachten Sie, dass ich keine Ahnung habe, wie memset die Strukturen, obwohl es nicht wichtig sein sollte. Noch wichtiger ist, ich denke, das Problem ist mit der Art, wie ich die GUID für WINTRUST_ACTION_GENERIC_VERIFY_V2 und/oder die Art, wie ich es übertrage.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Win32; # for GetLastError 
use Win32::API; 
use Win32::API::Struct; 
use Win32::API::Type; 

use Readonly; 

Readonly::Hash my %TRUST_E => (
    NOSIGNATURE   => sprintf('%8.8X', 0x800B0100), 
    SUBJECT_FORM_UNKNOWN => sprintf('%8.8X', 0x800B0003), 
    PROVIDER_UNKNOWN  => sprintf('%8.8X', 0x800B0001), 
    EXPLICIT_DISTRUST => sprintf('%8.8X', 0x800B0111), 
    SUBJECT_NOT_TRUSTED => sprintf('%8.8X', 0x800B0004), 
    ACTION_UNKNOWN  => sprintf('%8.8X', 0x800B0002), 
); 

Readonly::Hash my %WTD => (
    UI_ALL => 1, 
    UI_NONE => 2, 
    UI_NOBAD => 3, 
    UI_NOGOOD => 4, 

    REVOKE_NONE  => 0x00000000, 
    REVOKE_WHOLECHAIN => 0x00000001, 

    CHOICE_FILE => 1, 
    CHOICE_CATALOG => 2, 
    CHOICE_BLOB => 3, 
    CHOICE_SIGNER => 4, 
    CHOICE_CERT => 5, 

    PROV_FLAGS_MASK      => 0x0000FFFF, 
    USE_IE4_TRUST_FLAG     => 0x00000001, 
    NO_IE4_CHAIN_FLAG     => 0x00000002, 
    NO_POLICY_USAGE_FLAG     => 0x00000004, 
    REVOCATION_CHECK_NONE    => 0x00000010, 
    REVOCATION_CHECK_END_CERT   => 0x00000020, 
    REVOCATION_CHECK_CHAIN    => 0x00000040, 
    REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT => 0x00000080, 
    SAFER_FLAG       => 0x00000100, 
    HASH_ONLY_FLAG      => 0x00000200, 
    USE_DEFAULT_OSVER_CHECK    => 0x00000400, 
    LIFETIME_SIGNING_FLAG    => 0x00000800, 
    CACHE_ONLY_URL_RETRIEVAL    => 0x00001000, 

    STATEACTION_IGNORE   => 0x00000000, 
    STATEACTION_VERIFY   => 0x00000001, 
    STATEACTION_CLOSE   => 0x00000002, 
    STATEACTION_AUTO_CACHE  => 0x00000003, 
    STATEACTION_AUTO_CACHE_FLUSH => 0x00000004, 

    UICONTEXT_EXECUTE => 0, 
    UICONTEXT_INSTALL => 1, 
); 

typedef Win32::API::Struct GUID => qw{ 
    DWORD Data1; 
    WORD Data2; 
    WORD Data3; 
    BYTE Data4[8]; 
}; 

typedef Win32::API::Struct WINTRUST_FILE_INFO => qw{ 
     DWORD cbStruct; 
     LPCWSTR pcwszFilePath; 
     HANDLE hFile; 
     GUID *pgKnownSubject; 
}; 

typedef Win32::API::Struct WINTRUST_DATA_FILE_INFO => qw{ 
    DWORD cbStruct; 
    LPVOID pPolicyCallbackData; 
    LPVOID pSIPClientData; 
    DWORD dwUIChoice; 
    DWORD fdwRevocationChecks; 
    DWORD dwUnionChoice; 
    PWINTRUST_FILE_INFO pFile; 
    DWORD dwStateAction; 
    HANDLE hWVTStateData; 
    PWCHAR pwszURLReference; 
    DWORD dwProvFlags; 
    DWORD dwUIContext; 
}; 

for my $file (@ARGV) { 
    printf "%s: %s\n", $file, VerifyEmbeddedSignature($file); 
} 

sub VerifyEmbeddedSignature { 
    my ($file) = @_; 

    # From SoftPub.h '00AAC56B-CD44-11d0-8CC2-00C04FC295EE' 
    # 0xaac56b 0xcd44 0x11d0 0x8c 0xc2 0x0 0xc0 0x4f 0xc2 0x95 0xee 

    my $WINTRUST_ACTION_GENERIC_VERIFY_V2 
     = Win32::API::Struct->new('GUID'); 
    $WINTRUST_ACTION_GENERIC_VERIFY_V2->{Data1} = 0xaac56b; 
    $WINTRUST_ACTION_GENERIC_VERIFY_V2->{Data2} = 0xcd44; 
    $WINTRUST_ACTION_GENERIC_VERIFY_V2->{Data3} = 0x11d0; 
    $WINTRUST_ACTION_GENERIC_VERIFY_V2->{Data4} = [ 
     0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee, 
    ]; 

    my $FileData = Win32::API::Struct->new('WINTRUST_FILE_INFO'); 

    $FileData->{cbStruct} = $FileData->sizeof; 
    $FileData->{pcwszFilePath} = $file; 
    $FileData->{hFile}   = undef; 
    $FileData->{pgKnownSubject} = undef; 

    my $WinTrustData = Win32::API::Struct->new(
     'WINTRUST_DATA_FILE_INFO'); 

    $WinTrustData->{cbStruct} = $WinTrustData->sizeof; 
    $WinTrustData->{pPolicyCallbackData} = undef; 
    $WinTrustData->{pSIPClientData}  = undef; 
    $WinTrustData->{dwUIChoice}   = $WTD{UI_NONE}; 
    $WinTrustData->{fdwRevocationChecks} = $WTD{REVOKE_NONE}; 
    $WinTrustData->{dwUnionChoice}  = $WTD{CHOICE_FILE}; 
    $WinTrustData->{dwStateAction}  = 0; 
    $WinTrustData->{hWVTStateData}  = undef; 
    $WinTrustData->{pwszURLReference} = undef; 
    $WinTrustData->{dwProvFlags}   = $WTD{SAFER_FLAG}; 
    $WinTrustData->{dwUIContext}   = 0; 
    $WinTrustData->{pFile}    = $FileData; 

    my $WinVerifyTrust = Win32::API->new(
     wintrust => q{LONG WinVerifyTrust(
      HWND hWnd, 
      GUID *pgActionID, 
      LPVOID pWVTData) 
     } 
    ); 

    my $status = sprintf('0x%8.8X', $WinVerifyTrust->Call(
     -1, 
     $WINTRUST_ACTION_GENERIC_VERIFY_V2, 
     $WinTrustData, 
    )); 

    warn "$status\n"; 

    if ($status eq sprintf '0x%8.8X', 0) { 
     return 'signed and the signature was verified'; 
    } 
    elsif ($status eq $TRUST_E{SUBJECT_NOT_TRUSTED}) { 
     return 'The subject failed the specified verification action'; 
    } 
    elsif ($status eq $TRUST_E{PROVIDER_UNKNOWN}) { 
     return 'The trust provider is not recognized on this system'; 
    } 
    elsif ($status eq $TRUST_E{ACTION_UNKNOWN}) { 
     return 'The trust provider does not support the specified action'; 
    } 
    elsif ($status eq $TRUST_E{SUBJECT_FORM_UNKNOWN}) { 
     return 
     'The trust provider does not support the form ' . 
     'specified for the subject'; 
    } 
    else { 
     return "Error code: $status"; 
    } 

    return; 
} 
Verwandte Themen