【问题标题】:Get X509 Code Signing Certificate Serial Number of signed EXE in unmanaged C/C++获取非托管 C/C++ 中已签名 EXE 的 X509 代码签名证书序列号
【发布时间】:2019-07-11 00:55:43
【问题描述】:

我知道如何使用 C# DotNet 获取已签名 DLL 或 EXE 的代码签名证书详细信息,包括序列号。例如:

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

但是如何使用非托管 C/C++ 做到这一点?

我确实找到了关于如何在 C/++ 中遍历证书存储的 example,但没有找到如何获取签名的 EXE 或 DLL 的证书详细信息。

【问题讨论】:

    标签: c++ c x509certificate unmanaged code-signing-certificate


    【解决方案1】:

    以下是如何解码可执行文件的 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;
    

    【讨论】:

    • 太棒了,谢谢。这是我遇到的另一个 example 帮助。
    • if(1) - 为什么??
    • 显然没有它就无法编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2013-04-02
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多