Anfield
Anfield

Reputation: 27

Verify Signed PE File

(Sorry for my bad English.) I have some problems in my code.so I will try to explain my problem. I have a simple exe file with signed(pkcs7). I want to verify this file (without an internet connection). I don't want to use WinVerifyTrust() because I want to know how windows verify PE file. I wrote some code that first calls CryptQueryObject() with BLOB_DATA(mapped pe file), and it works fine. Then I can get certificate information: signer, serial, etc. (with CryptGetMsgParam()) and it also works fine; but, when I go to verify it with CertGetCertificateChain() I get and error. So, can you help me to solve this problem, which I think is that I don't use CertGetCertificateChain() correctly?

BOOL bRet = FALSE;
DWORD dwMsgAndCertEncodingType = 0;
DWORD dwContentType = 0;
DWORD dwFormatType = 0;
HCERTSTORE  hStore = NULL;
HCRYPTMSG   hMsg = NULL;
PCCERT_CONTEXT      pCertContext = NULL;
CERT_BLOB   blob_data = { 0 };
// CERT_INFO    CertInfo = { 0 };
DWORD dwSignerInfo = 0;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
CERT_CHAIN_PARA          ChainPara = { 0 };


blob_data.pbData = pBuff;
blob_data.cbData = dwSize;


ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);


bRet = CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
    &blob_data,
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
    CERT_QUERY_FORMAT_FLAG_BINARY,
    0,
    NULL,
    &dwContentType,
    NULL,
    &hStore,
    &hMsg,
    &pCertContext);


if (bRet != TRUE)
{
    printf("Error CryptQueryObject\n");
    return FALSE;
}


if (dwContentType != CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED)
{
    printf("Error type\n");
    return FALSE;
}


CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);

pSignerInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSignerInfo);


CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwSignerInfo);



bRet = CertGetCertificateChain(NULL, (PCCERT_CONTEXT)pCertContext, NULL, NULL, NULL, CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY,
    NULL, &pChainContext);

if (bRet != TRUE)
{
    printf("Error there\n");
}

Upvotes: 1

Views: 600

Answers (1)

Adrian Mole
Adrian Mole

Reputation: 51825

One problem (though maybe not the only one) is the fact that your fifth parameter to CertGetCertificateChain() is NULL? This should point to a CERT_CHAIN_PARA structure. (You have one declared but don't appear to either initialize or use it.)

I don't know exactly what data you should put in this, but here's an example using code taken from a real (working) program (one of my own making) that checks digital certificates:

//...
CERT_CHAIN_PARA ChainPara;  memset(&ChainPara, 0, sizeof(CERT_CHAIN_PARA));
ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
ChainPara.RequestedUsage.Usage.cUsageIdentifier = 0;
//...
bRet = CertGetCertificateChain(NULL, (PCCERT_CONTEXT)pCertContext, NULL, NULL, &ChainPara,
    CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, NULL, &pChainContext);
//...

You can look at the documentation for CERT_CHAIN_PARA to get some hints on what actual data/values you should set.

Hope this helps! (Feel free to ask for further clarification and or suggestions.)

Upvotes: 1

Related Questions