Home › Forums › Discussions › General › Verify digital signature of an executable file › Reply To: Verify digital signature of an executable file
May 8, 2007 at 8:14 am
#6227
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…