2009-08-17 6 views
3

Я пытаюсь найти способ сценария (желательно на Perl) - проверить, есть ли .exe или .dll с цифровой подписью - если у кого есть легкое направление, чтобы указать мне, я был бы признателен.Как проверить цифровую подпись файла .exe или .dll в Perl?

+2

Это в основном "есть модуль для разбора файлов формата х" ... это очень отличается от PLS-отправить меня-в- код, поэтому я был бы склонен удалить этот тег. Это, безусловно, не должно быть закрыто. – ysth

ответ

3

Идея заключается в переводе the sample program on MSDN с использованием Win32::API.

Обновление: Я принял удар по переводу пробной программы из MSDN. По какой-то причине вызов продолжает возвращать 0x800B0001 (=TRUST_E_PROVIDER_UNKNOWN) для файлов, которые правильно проверяют код образца Win32. Я размещаю сценарий здесь, если кто-то может заметить мою ошибку.

Обратите внимание, что я понятия не имею, как memset структур, хотя это не должно иметь значения. Что еще более важно, я думаю, проблема связана с тем, как я создаю GUID для WINTRUST_ACTION_GENERIC_VERIFY_V2 и/или способом, которым я его передаю.

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