Reply To: Verify digital signature of an executable file

Home Forums Discussions General Verify digital signature of an executable file Reply To: Verify digital signature of an executable file

#6227
Vadim Smirnov
Keymaster

    If you look inside sigcheck.exe you will find that it works through wintrust.dll exported functions.

    .text:00402260 sub_402260      proc near               ; CODE XREF: _wmain:loc_402016p
    .text:00402260                 mov     al, byte_425860
    .text:00402265                 push    ebx
    .text:00402266                 test    al, al
    .text:00402268                 push    esi
    .text:00402269                 jnz     loc_402339
    .text:0040226F                 mov     ebx, ds:LoadLibraryW
    .text:00402275                 push    offset aWintrust_dll ; "Wintrust.dll"
    .text:0040227A                 mov     byte_425860, 1
    .text:00402281                 call    ebx ; LoadLibraryW
    .text:00402283                 mov     esi, eax
    .text:00402285                 test    esi, esi
    .text:00402287                 jnz     short loc_40228E
    .text:00402289                 pop     esi
    .text:0040228A                 xor     al, al
    .text:0040228C                 pop     ebx
    .text:0040228D                 retn
    .text:0040228E ;
    <hr class="bbcode_rule" />
    .text:0040228E
    .text:0040228E loc_40228E:                             ; CODE XREF: sub_402260+27j
    .text:0040228E                 push    edi
    .text:0040228F                 mov     edi, ds:GetProcAddress
    .text:00402295                 push    offset aWinverifytrust ; "WinVerifyTrust"
    .text:0040229A                 push    esi             ; hModule
    .text:0040229B                 call    edi ; GetProcAddress
    .text:0040229D                 push    offset aWthelpergetpro ; "WTHelperGetProvSignerFromChain"
    .text:004022A2                 push    esi             ; hModule
    .text:004022A3                 mov     WinVerifyTrustPtr, eax
    .text:004022A8                 call    edi ; GetProcAddress
    .text:004022AA                 push    offset aWthelperprovda ; "WTHelperProvDataFromStateData"
    .text:004022AF                 push    esi             ; hModule
    .text:004022B0                 mov     dword_425834, eax
    .text:004022B5                 call    edi ; GetProcAddress
    .text:004022B7                 push    offset aCryptcatadminr ; "CryptCATAdminReleaseContext"
    .text:004022BC                 push    esi             ; hModule
    .text:004022BD                 mov     dword_425838, eax
    .text:004022C2                 call    edi ; GetProcAddress
    .text:004022C4                 push    offset aCryptcatadmi_0 ; "CryptCATAdminReleaseCatalogContext"
    .text:004022C9                 push    esi             ; hModule
    .text:004022CA                 mov     dword_42583C, eax
    .text:004022CF                 call    edi ; GetProcAddress
    .text:004022D1                 push    offset aCryptcatcatalo ; "CryptCATCatalogInfoFromContext"
    .text:004022D6                 push    esi             ; hModule
    .text:004022D7                 mov     dword_42585C, eax
    .text:004022DC                 call    edi ; GetProcAddress
    .text:004022DE                 push    offset aCryptcatadmine ; "CryptCATAdminEnumCatalogFromHash"
    .text:004022E3                 push    esi             ; hModule
    .text:004022E4                 mov     dword_425854, eax
    .text:004022E9                 call    edi ; GetProcAddress
    .text:004022EB                 push    offset aCryptcatadminc ; "CryptCATAdminCalcHashFromFileHandle"
    .text:004022F0                 push    esi             ; hModule
    .text:004022F1                 mov     dword_425848, eax
    .text:004022F6                 call    edi ; GetProcAddress
    .text:004022F8                 push    offset aCryptcatadmina ; "CryptCATAdminAcquireContext"
    .text:004022FD                 push    esi             ; hModule
    .text:004022FE                 mov     dword_425840, eax
    .text:00402303                 call    edi ; GetProcAddress
    .text:00402305                 push    offset aCryptcatadmi_1 ; "CryptCATAdminAddCatalog"
    .text:0040230A                 push    esi             ; hModule
    .text:0040230B                 mov     dword_42584C, eax
    .text:00402310                 call    edi ; GetProcAddress
    .text:00402312                 push    offset aWinverifytrust ; "WinVerifyTrust"
    .text:00402317                 push    esi             ; hModule
    .text:00402318                 mov     dword_425844, eax
    .text:0040231D                 call    edi ; GetProcAddress
    .text:0040231F                 push    offset aCertnametostrw ; "CertNameToStrW"
    .text:00402324                 push    offset aCrypt32_dll ; "crypt32.dll"
    .text:00402329                 mov     WinVerifyTrustPtr, eax
    .text:0040232E                 call    ebx ; LoadLibraryW
    .text:00402330                 push    eax             ; hModule
    .text:00402331                 call    edi ; GetProcAddress
    .text:00402333                 mov     dword_425858, eax
    .text:00402338                 pop     edi
    .text:00402339
    .text:00402339 loc_402339:                             ; CODE XREF: sub_402260+9j
    .text:00402339                 mov     ecx, dword_42584C
    .text:0040233F                 xor     eax, eax
    .text:00402341                 test    ecx, ecx
    .text:00402343                 pop     esi
    .text:00402344                 pop     ebx
    .text:00402345                 setnz   al
    .text:00402348                 retn
    .text:00402348 sub_402260      endp

    WinVerifyTrust is called with WINTRUST_ACTION_GENERIC_VERIFY_V2 action ID.

    A piece of code which demonstrates usage of WinVerifyTrust can be found in the Platform SDK samples (vertrust.cpp):

    <br />
    /////////////////////////////////////////////////////////////////////////////<br />
    // IsFileTrusted<br />
    //<br />
    itvEnum IsFileTrusted(LPCWSTR lpwFile, HWND hwndParent, DWORD dwUIChoice, bool *pfIsSigned, PCCERT_CONTEXT *ppcSigner)<br />
    {<br />
    char szDebugOutput[MAX_STR_LENGTH] = {0};<br />
    <br />
    itvEnum itv = itvUnTrusted;<br />
    <br />
    if (pfIsSigned)<br />
    *pfIsSigned = false;<br />
    if (ppcSigner)<br />
    *ppcSigner  = 0;<br />
    <br />
    GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;<br />
    <br />
    WINTRUST_FILE_INFO sWintrustFileInfo;<br />
    WINTRUST_DATA      sWintrustData;<br />
    HRESULT            hr;<br />
    <br />
    memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO)); // zero out<br />
    memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA)); // zero out<br />
    <br />
    sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);<br />
    sWintrustFileInfo.pcwszFilePath = lpwFile;<br />
    sWintrustFileInfo.hFile = NULL;<br />
    <br />
    sWintrustData.cbStruct            = sizeof(WINTRUST_DATA);<br />
    sWintrustData.dwUIChoice          = dwUIChoice;<br />
    sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;<br />
    sWintrustData.dwUnionChoice       = WTD_CHOICE_FILE;<br />
    sWintrustData.pFile               = &sWintrustFileInfo;<br />
    sWintrustData.dwStateAction       = (ppcSigner) ? WTD_STATEACTION_VERIFY : 0;<br />
    <br />
    HMODULE hWinTrust = LoadLibrary(WINTRUST_DLL);<br />
    if (!hWinTrust)<br />
    {<br />
    // WinTrust is unavailable on the machine<br />
    return itvWintrustNotOnMachine;<br />
    }<br />
    PFnWinVerifyTrust pfnWinVerifyTrust = (PFnWinVerifyTrust)GetProcAddress(hWinTrust, WINTRUSTAPI_WinVerifyTrust);<br />
    PFnWTHelperProvDataFromStateData pfnWTHelperProvDataFromStateData= (PFnWTHelperProvDataFromStateData)GetProcAddress(hWinTrust, WINTRUSTAPI_WTHelperProvDataFromStateData);<br />
    PFnWTHelperGetProvSignerFromChain pfnWTHelperGetProvSignerFromChain = (PFnWTHelperGetProvSignerFromChain)GetProcAddress(hWinTrust, WINTRUSTAPI_WTHelperGetProvSignerFromChain);<br />
    PFnWTHelperGetProvCertFromChain pfnWTHelperGetProvCertFromChain = (PFnWTHelperGetProvCertFromChain)GetProcAddress(hWinTrust, WINTRUSTAPI_WTHelperGetProvCertFromChain);<br />
    if (!pfnWinVerifyTrust || !pfnWTHelperProvDataFromStateData || !pfnWTHelperGetProvSignerFromChain || !pfnWTHelperGetProvCertFromChain)<br />
    {<br />
    // WinTrust is unavailable on the machine<br />
    FreeLibrary(hWinTrust);<br />
    return itvWintrustNotOnMachine;<br />
    }<br />
    <br />
    hr = pfnWinVerifyTrust(/* UI Window Handle */ (dwUIChoice == WTD_UI_NONE) ? (HWND)INVALID_HANDLE_VALUE : hwndParent, &guidAction, &sWintrustData);<br />
    DebugMsg("[WVT] WVT returned 0x%Xn", hr);<br />
    <br />
    itv = (TRUST_E_PROVIDER_UNKNOWN == hr) ? itvWintrustNotOnMachine : ((S_OK == hr) ? itvTrusted : itvUnTrusted);<br />
    <br />
    if (itvWintrustNotOnMachine == itv)<br />
    {<br />
    // release state data<br />
    sWintrustData.dwUIChoice = WTD_UI_NONE;<br />
    sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;<br />
    pfnWinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);<br />
    <br />
    FreeLibrary(hWinTrust);<br />
    return itv; // return immediately<br />
    }<br />
    <br />
    if (pfIsSigned)<br />
    *pfIsSigned = (TRUST_E_NOSIGNATURE == hr) ? false : true;<br />
    <br />
    if (TRUST_E_NOSIGNATURE == hr)<br />
    {<br />
    // release state data<br />
    sWintrustData.dwUIChoice = WTD_UI_NONE;<br />
    sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;<br />
    pfnWinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);<br />
    <br />
    FreeLibrary(hWinTrust);<br />
    return itv;<br />
    }<br />
    <br />
    if (ppcSigner)<br />
    {<br />
    CRYPT_PROVIDER_DATA const *psProvData     = NULL;<br />
    CRYPT_PROVIDER_SGNR       *psProvSigner   = NULL;<br />
    CRYPT_PROVIDER_CERT       *psProvCert     = NULL;<br />
    <br />
    // grab the provider data<br />
    psProvData = pfnWTHelperProvDataFromStateData(sWintrustData.hWVTStateData);<br />
    if (psProvData)<br />
    {<br />
    // grab the signer data from the CRYPT_PROV_DATA<br />
    psProvSigner = pfnWTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0 /*first signer*/, FALSE /* not a counter signer */, 0);<br />
    if (psProvSigner)<br />
    {<br />
    // grab the signer cert from CRYPT_PROV_SGNR (pos 0 = signer cert; pos csCertChain-1 = root cert)<br />
    psProvCert = pfnWTHelperGetProvCertFromChain(psProvSigner, 0);<br />
    }<br />
    }<br />
    <br />
    if (!psProvCert)<br />
    {<br />
    // some failure in obtaining the signer cert data<br />
    *ppcSigner = 0;<br />
    }<br />
    else<br />
    {<br />
    // duplicate the cert<br />
    HMODULE hCrypt32 = LoadLibrary(CRYPT32_DLL);<br />
    if (hCrypt32)<br />
    {<br />
    PFnCertDuplicateCertificateContext pfnCertDuplicateCertificateContext = (PFnCertDuplicateCertificateContext)GetProcAddress(hCrypt32, CRYPTOAPI_CertDuplicateCertificateContext);<br />
    if (pfnCertDuplicateCertificateContext)<br />
    *ppcSigner = pfnCertDuplicateCertificateContext(psProvCert->pCert);<br />
    FreeLibrary(hCrypt32);<br />
    }<br />
    }<br />
    <br />
    // release state data<br />
    sWintrustData.dwUIChoice = WTD_UI_NONE;<br />
    sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;<br />
    pfnWinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);<br />
    }<br />
    <br />
    FreeLibrary(hWinTrust);<br />
    return itv;<br />
    }<br />
    

    Hope it helps…