Проверить подписанный PE-файл

(Извините за мой плохой английский.) У меня есть некоторые проблемы в моем коде, поэтому я попытаюсь объяснить свою проблему. У меня есть простой исполняемый файл с подписью (pkcs7). Я хочу проверить этот файл (без подключения к Интернету). Я не хочу использовать WinVerifyTrust(), потому что хочу знать, как Windows проверяет PE-файл. Я написал некоторый код, который сначала вызывает CryptQueryObject() с BLOB_DATA (сопоставленный PE-файл), и он отлично работает. Затем я могу получить информацию о сертификате: подписавший, серийный номер и т. д. (с CryptGetMsgParam()), и это также работает нормально; но когда я иду, чтобы проверить это с помощью CertGetCertificateChain(), я получаю сообщение об ошибке. Итак, можете ли вы помочь мне решить эту проблему, которая, я думаю, заключается в том, что я неправильно использую CertGetCertificateChain()?

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");
}

person Anfield    schedule 24.09.2019    source источник
comment
Спасибо за ответ. Да, это может быть проблемой, но я на самом деле не знаю, как ее использовать, потому что нет хорошей информации и сети, а также я не вижу хороших примеров (   -  person Anfield    schedule 24.09.2019
comment
ОК, комментарий теперь перемещен в ответ с некоторым (надеюсь, полезным) примером кода.   -  person Adrian Mole    schedule 24.09.2019
comment
привет, Amfield Лучше включить в свой вопрос самое основное сообщение об ошибке. Теперь, когда вы вызываете CertGetCertificateChain и возникает ошибка, согласно document, чтобы получить расширенную информацию об ошибке, позвоните по номеру GetLastError.   -  person Strive Sun    schedule 25.09.2019


Ответы (1)


Одна проблема (хотя, возможно, не единственная) заключается в том, что ваш пятый параметр CertGetCertificateChain() — это NULL? Это должно указывать на структуру CERT_CHAIN_PARA. (У вас есть один объявленный, но, похоже, он не инициализируется и не используется.)

Я не знаю точно, какие данные вы должны указать в этом, но вот пример использования кода, взятого из реальной (работающей) программы (одна из моих собственных), которая проверяет цифровые сертификаты:

//...
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);
//...

Вы можете посмотреть документацию для CERT_CHAIN_PARA, чтобы получить некоторые подсказки о том, какие фактические данные/значения вы должны установить.

Надеюсь это поможет! (Не стесняйтесь обращаться за дальнейшими разъяснениями и/или предложениями.)

person Adrian Mole    schedule 24.09.2019
comment
Спасибо, Адриан, но это не помогает. Я пробую файлы каталога, может быть, это поможет - person Anfield; 24.09.2019