Read and validate certificate from executable
The WinVerifyTrust function performs a trust verification action on a specified object. The function passes the inquiry to a trust provider that supports the action identifier, if one exists.
For certificate verification, use the CertGetCertificateChain and CertVerifyCertificateChainPolicy functions.
There are many API and approaches how you can get and verify the signature of the executable and how you can get other additional information which you need. The problem is which level you choose (high level like WinVerifyTrust
)
The easiest first API which can be used to get cryptography context from the CAT or EXE file is CryptQueryObject function. The code example from the KB323809 could get you the main idea how to decode information what you need. the main difference if you work with CAT files is that you should modify the some parameters of CryptQueryObject. I recommend you just to use CERT_QUERY_CONTENT_FLAG_ALL
and CERT_QUERY_FORMAT_FLAG_ALL
and CryptQueryObject
will do all what you needs internally:
BOOL bIsSuccess;
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PVOID pvContext = NULL;
// fill szFileName
...
// Get message handle and store handle from the signed file.
bIsSuccess = CryptQueryObject (CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_ALL,
CERT_QUERY_FORMAT_FLAG_ALL,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
&pvContext);
The value dwContentType
set by the CryptQueryObject
will get you the base information about the type of the file szFileName
. The pvContext
will be PCCERT_CONTEXT
for the most cases which you need, but it can be also PCCRL_CONTEXT
or PCCTL_CONTEXT
if you use .ctl or .crl file as the input. You will receive the hStore
filled with all certificates from the file szFileName
. So with respect of pvContext
and hStore
you can examine the file contain with CryptoAPI. If you do prefer
low-level massages API you can use hMsg
which will be additionally set in case of some dwContentType
(at least for for CERT_QUERY_CONTENT_PKCS7_SIGNED
, CERT_QUERY_CONTENT_PKCS7_UNSIGNED
, CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
).
To verify the signature of the file I would recommend you to use CertGetCertificateChain and CertVerifyCertificateChainPolicy to verify not only that the certificate is valid in general, but that it (or all its parents) is valid for authenticode (szOID_PKIX_KP_CODE_SIGNING
). CertGetCertificateChain can be used for different revocation scenarios. You should do two separate calls with CERT_CHAIN_POLICY_AUTHENTICODE
and CERT_CHAIN_POLICY_AUTHENTICODE_TS
to verify that both Authenticode chain policy and Authenticode Time Stamp chain policy are valid.
UPDATED: I reread your current question (the Updated part). Your current problem is how to get the signer/publisher of the file. So I answer only on the question.
If you use the code from sysinternal for the signature verification you should just search for the line
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
The statement sill set the fields of the InfoStruct
in case that that file is system windows file which signature is verified with respect of some .cat file. The field InfoStruct.wszCatalogFile will get you the name of the .cat file.
For example on my Windows 7 if I try to verify the digital signature of the C:\Windows\explorer.exe
file, the .cat where its hash could be found is C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat
.
If you would use code from KB323809 with described above parameters of CryptQueryObject
you will decode the SPC_SP_OPUS_INFO_OBJID
("1.3.6.1.4.1.311.2.1.12") attribute of the C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat
(see the function GetProgAndPublisherInfo
) and you will know
pwszProgramName: "Windows Express Security Catalogs"
pPublisherInfo: NULL
pMoreInfo->dwLinkChoice: SPC_URL_LINK_CHOICE
pMoreInfo->pwszUrl "http://www.microsoft.com"
So no special publisher information are included for the file. If you examine the signer of the the catalog you will find out that:
The signer of the .cat file: "Microsoft Windows"
The signer signed it with the certificate:
Serial Number: 0x6115230F00000000000A
Issuer Name: Microsoft Windows Verification PCA
Full Issuer Name:
CN = Microsoft Windows Verification PCA
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
Subject Name: Microsoft Windows
Full Subject Name:
CN = Microsoft Windows
OU = MOPR
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
The Date of TimeStamp : 28.02.2011 21:16:36
TimeStamp Certificate:
Serial Number: 0x6103DCF600000000000C
Issuer Name: Microsoft Time-Stamp PCA
Subject Name: Microsoft Time-Stamp Service
So you should use just the signer of the .cat file, because there are no other signer of explorer.exe
.
@Davita I read the above problem thoroughly and tried to solve it.
My suggestion is to try CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
instead of CERT_QUERY_CONTENT_FLAG_ALL
in the third parameter of CryptQueryObject()