Reply To: Verify digital signature of an executable file

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

#6227

Vadim Smirnov
Moderator

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…