Проверить подписанный PE-файл - PullRequest
0 голосов
/ 24 сентября 2019

(Извините за мой плохой английский.) У меня есть некоторые проблемы в моем коде. Поэтому я попытаюсь объяснить мою проблему.У меня есть простой исполняемый файл с подписью (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");
}

1 Ответ

1 голос
/ 24 сентября 2019

Одна проблема (хотя, возможно, не единственная) заключается в том, что ваш пятый параметр для 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, чтобы получить некоторые подсказки о том, какие фактические данные / значения вы должны установить.

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

...