Получить сертификат подписи кода X509 Серийный номер подписанного EXE в неуправляемом C / C ++ - PullRequest
0 голосов
/ 17 февраля 2019

Я знаю, как получить информацию о сертификате подписи кода, включая серийный номер, подписанной DLL или EXE-файла, используя C # DotNet.Например:

using System.Security.Cryptography.X509Certificates;
...
X509Certificate certinfo = X509Certificate.CreateFromSignedFile(filename);
byte[] serialno = certinfo.GetSerialNumber();

Но как я могу это сделать с помощью неуправляемого C / C ++?

Я нашел пример о том, как просмотреть хранилище сертификатов в C / ++, но не о том, как получить сведения о сертификате подписанного EXE или DLL.

1 Ответ

0 голосов
/ 17 февраля 2019

Вот пример того, как декодировать данные исполняемого файла PKCS7 (CMS).

DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;

// Get PKCS7 data

if(1)
{
    // Must be an absolute path.
    const wchar_t *filePath = L"C:\\Windows\\System32\\ntdll.dll";

    if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, filePath,
                         CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                         CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
                         &dwContentType, &dwFormatType, &hStore,
                         &hMsg, NULL))
        return 1;
}
else
{
/*  Or do this if you want more control:

    - load exe into memory
    - find the certificate directory (WIN_CERTIFICATE)

    WIN_CERTIFICATE &winCert = ...

    CERT_BLOB certBlob = { winCert.dwLength, winCert.bCertificate };
    if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &certBlob, 
                         CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
                         CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
                         &dwContentType, &dwFormatType, &hStore,
                         &hMsg, NULL))
        return 1;
*/
}

// Get signers information

DWORD dwSignerCount = 0;
DWORD dwSignerCountSize = sizeof(dwSignerCount);
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwSignerCount, &dwSignerCountSize))
    return 1;

// The signer count seems to always be 1.
// Subsequent certificates can be retrieved like this:
// https://stackoverflow.com/q/36931928/2682312

for(DWORD i = 0; i < dwSignerCount; ++i)
{
    DWORD cbSignerInfo;
    if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, NULL, &cbSignerInfo))
        return 1;

    PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)malloc(cbSignerInfo);
    if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, pSignerInfo, &cbSignerInfo))
        return 1;

    // Do something with pSignerInfo->SerialNumber

    // Enumerate nested certificates...

    free(pSignerInfo);
}

return 0;
...