修改了从 Windows 中的 PE 可执行文件检索双重签名信息的代码?

问题描述 投票:0回答:3

我一直在努力修改来自 Microsoft 的此代码示例,该示例显示(有些过时)如何从可执行文件中检索代码签名信息。它可以工作,但如果二进制文件是双重签名的,它不会检索信息。

因此,我做了一些研究并尝试重写它,使其能够识别 Windows 中许多现代可执行文件中存在的双重签名。不幸的是,可用的(模糊)建议非常少(1),(2),例如使用

UnauthenticatedAttributes
szOID_NESTED_SIGNATURE
(无论这意味着什么)但仅检索时间戳的建议。

所以我尝试重写 Microsoft 代码,这就是我得到的:

(要构建它,只需将其复制到 Visual Studio 控制台项目并更改 .exe 文件路径。处理双重签名的代码位于

PrintDualSignatureInfo()
函数中。)

#include "stdafx.h"

//SOURCE:
//      https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-signed-executables
//

#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.h>
#include <atlconv.h>

#pragma comment(lib, "crypt32.lib")

#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)

typedef struct {
    LPWSTR lpszProgramName;
    LPWSTR lpszPublisherLink;
    LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;



BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
                             PSPROG_PUBLISHERINFO Info);
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st);
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
                            PCMSG_SIGNER_INFO *pCounterSignerInfo);
void PrintSignatureAlgorithm(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo);
void PrintDualSignatureInfo(PCMSG_SIGNER_INFO pSignerInfo);
void PrintCertificateInfo(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertName);


int main()
{
     WCHAR szFileName[MAX_PATH]; 
    HCERTSTORE hStore = NULL;
    HCRYPTMSG hMsg = NULL; 
    BOOL fResult;   
    DWORD dwEncoding, dwContentType, dwFormatType;
    PCMSG_SIGNER_INFO pSignerInfo = NULL;
    DWORD dwSignerInfo;
    SPROG_PUBLISHERINFO ProgPubInfo;

    ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
    __try
    {
        LPCTSTR pExePath = L"C:\\Users\\UserName\\Downloads\\procmon.exe";  //works
        //pExePath = L"C:\\Users\\UserName\\Downloads\\putty.exe";      //doesnt work

        lstrcpynW(szFileName, pExePath, MAX_PATH);

        // Get message handle and store handle from the signed file.
        fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
                                   szFileName,
                                   CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                                   CERT_QUERY_FORMAT_FLAG_BINARY,
                                   0,
                                   &dwEncoding,
                                   &dwContentType,
                                   &dwFormatType,
                                   &hStore,
                                   &hMsg,
                                   NULL);
        if (!fResult)
        {
            _tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
            __leave;
        }

        // Get signer information size.
        fResult = CryptMsgGetParam(hMsg, 
                                   CMSG_SIGNER_INFO_PARAM, 
                                   0, 
                                   NULL, 
                                   &dwSignerInfo);
        if (!fResult)
        {
            _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
            __leave;
        }

        // Allocate memory for signer information.
        pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
        if (!pSignerInfo)
        {
            _tprintf(_T("Unable to allocate memory for Signer Info.\n"));
            __leave;
        }

        // Get Signer Information.
        fResult = CryptMsgGetParam(hMsg, 
                                   CMSG_SIGNER_INFO_PARAM, 
                                   0, 
                                   (PVOID)pSignerInfo, 
                                   &dwSignerInfo);
        if (!fResult)
        {
            _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
            __leave;
        }

        // Get program name and publisher information from 
        // signer info structure.
        if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
        {
            if (ProgPubInfo.lpszProgramName != NULL)
            {
                wprintf(L"Program Name : %s\n",
                    ProgPubInfo.lpszProgramName);
            }

            if (ProgPubInfo.lpszPublisherLink != NULL)
            {
                wprintf(L"Publisher Link : %s\n",
                    ProgPubInfo.lpszPublisherLink);
            }

            if (ProgPubInfo.lpszMoreInfoLink != NULL)
            {
                wprintf(L"MoreInfo Link : %s\n",
                    ProgPubInfo.lpszMoreInfoLink);
            }
        }

        _tprintf(_T("\n"));

        // Print Signer certificate information.
        PrintCertificateInfo(hStore, pSignerInfo, L"Signer Certificate");


        //Look for dual signature
        PrintDualSignatureInfo(pSignerInfo);

    }
    __finally
    {               
        // Clean up.
        if (ProgPubInfo.lpszProgramName != NULL)
            LocalFree(ProgPubInfo.lpszProgramName);
        if (ProgPubInfo.lpszPublisherLink != NULL)
            LocalFree(ProgPubInfo.lpszPublisherLink);
        if (ProgPubInfo.lpszMoreInfoLink != NULL)
            LocalFree(ProgPubInfo.lpszMoreInfoLink);

        if (pSignerInfo != NULL) LocalFree(pSignerInfo);
        if (hStore != NULL) CertCloseStore(hStore, 0);
        if (hMsg != NULL) CryptMsgClose(hMsg);
    }
    return 0;
}



void PrintCertificateInfo(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertName)
{

    if(hStore &&
        pSignerInfo)
    {
        PCCERT_CONTEXT pCertContext = NULL;
        CERT_INFO CertInfo = {0};
        PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
        SYSTEMTIME st;

        __try
        {
            // Search for the signer certificate in the temporary 
            // certificate store.
            CertInfo.Issuer = pSignerInfo->Issuer;
            CertInfo.SerialNumber = pSignerInfo->SerialNumber;

            pCertContext = CertFindCertificateInStore(hStore,
                                                      ENCODING,
                                                      0,
                                                      CERT_FIND_SUBJECT_CERT,
                                                      (PVOID)&CertInfo,
                                                      NULL);
            if (!pCertContext)
            {
                _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
                    GetLastError());
                __leave;
            }

            // Print Signer certificate information.
            _tprintf(L"%s:\n\n", pStrCertName);     //(_T("Signer Certificate:\n\n"));        
            PrintCertificateInfo(pCertContext);
            _tprintf(_T("\n"));



            // Get the timestamp certificate signerinfo structure.
            if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo))
            {
                // Search for Timestamp certificate in the temporary
                // certificate store.
                CertInfo.Issuer = pCounterSignerInfo->Issuer;
                CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber;

                pCertContext = CertFindCertificateInStore(hStore,
                                                    ENCODING,
                                                    0,
                                                    CERT_FIND_SUBJECT_CERT,
                                                    (PVOID)&CertInfo,
                                                    NULL);
                if (!pCertContext)
                {
                    _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
                        GetLastError());
                    __leave;
                }

                // Print timestamp certificate information.
                _tprintf(_T("TimeStamp Certificate:\n\n"));
                PrintCertificateInfo(pCertContext);
                _tprintf(_T("\n"));

                // Find Date of timestamp.
                if (GetDateOfTimeStamp(pCounterSignerInfo, &st))
                {
                    _tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
                                                st.wMonth,
                                                st.wDay,
                                                st.wYear,
                                                st.wHour,
                                                st.wMinute);
                }
                _tprintf(_T("\n"));
            }

        }
        __finally
        {
            if (pCounterSignerInfo != NULL)
                LocalFree(pCounterSignerInfo);

            if (pCertContext != NULL)
                CertFreeCertificateContext(pCertContext);
        }
    }

}



void PrintDualSignatureInfo(PCMSG_SIGNER_INFO pSignerInfo)
{
    if(pSignerInfo)
    {

        for(DWORD a = 0; a < pSignerInfo->UnauthAttrs.cAttr; a++)
        {
            if(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId &&
                lstrcmpiA(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId, szOID_NESTED_SIGNATURE) == 0)
            {
                HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
                if(hMsg)
                {
                    if(::CryptMsgUpdate(hMsg, 
                        pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData,
                        pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData,
                        TRUE))
                    {
                        DWORD dwSignerInfo = 0;
                        ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
                        if(dwSignerInfo != 0)
                        {
                            PCMSG_SIGNER_INFO pSignerInfo2 = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwSignerInfo];
                            if(pSignerInfo2)
                            {
                                if(::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 
                                    0, (PVOID)pSignerInfo2, &dwSignerInfo))
                                {
                                    CRYPT_DATA_BLOB p7Data;
                                    p7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData;
                                    p7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData;

                                    HCERTSTORE hStore = ::CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, &p7Data);
                                    if(hStore)
                                    {
                                        // Print Signer certificate information.
                                        PrintCertificateInfo(hStore, pSignerInfo2, L"Dual Signer Certificate");

                                        //Close
                                        ::CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
                                    }
                                }

                                //Free mem
                                delete[] pSignerInfo2;
                                pSignerInfo2 = NULL;
                            }
                        }
                    }

                    //Close message
                    ::CryptMsgClose(hMsg);
                }

            }
        }


    }

}


void PrintSignatureAlgorithm(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo)
{
    if(pSigAlgo &&
        pSigAlgo->pszObjId)
    {
        PCCRYPT_OID_INFO pCOI = ::CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pSigAlgo->pszObjId, 0);
        if(pCOI &&
            pCOI->pwszName)
        {
            _tprintf(L"%s", pCOI->pwszName);
        }
        else
        {
            USES_CONVERSION;
            _tprintf(L"%s",  A2W(pSigAlgo->pszObjId));
        }
    }
}


BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
{
    BOOL fReturn = FALSE;
    LPTSTR szName = NULL;
    DWORD dwData;

    __try
    {
        // Print Serial Number.
        _tprintf(_T("Serial Number: "));
        dwData = pCertContext->pCertInfo->SerialNumber.cbData;
        for (DWORD n = 0; n < dwData; n++)
        {
            _tprintf(_T("%02x "),
              pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]);
        }
        _tprintf(_T("\n"));


        //Hashing algoriths
        _tprintf(L"Signature Algorithm: ");
        PrintSignatureAlgorithm(&pCertContext->pCertInfo->SignatureAlgorithm);
        _tprintf(_T("\n"));


        // Get Issuer name size.
        if (!(dwData = CertGetNameString(pCertContext, 
                                         CERT_NAME_SIMPLE_DISPLAY_TYPE,
                                         CERT_NAME_ISSUER_FLAG,
                                         NULL,
                                         NULL,
                                         0)))
        {
            _tprintf(_T("CertGetNameString failed.\n"));
            __leave;
        }

        // Allocate memory for Issuer name.
        szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
        if (!szName)
        {
            _tprintf(_T("Unable to allocate memory for issuer name.\n"));
            __leave;
        }

        // Get Issuer name.
        if (!(CertGetNameString(pCertContext, 
                                CERT_NAME_SIMPLE_DISPLAY_TYPE,
                                CERT_NAME_ISSUER_FLAG,
                                NULL,
                                szName,
                                dwData)))
        {
            _tprintf(_T("CertGetNameString failed.\n"));
            __leave;
        }

        // print Issuer name.
        _tprintf(_T("Issuer Name: %s\n"), szName);
        LocalFree(szName);
        szName = NULL;

        // Get Subject name size.
        if (!(dwData = CertGetNameString(pCertContext, 
                                         CERT_NAME_SIMPLE_DISPLAY_TYPE,
                                         0,
                                         NULL,
                                         NULL,
                                         0)))
        {
            _tprintf(_T("CertGetNameString failed.\n"));
            __leave;
        }

        // Allocate memory for subject name.
        szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
        if (!szName)
        {
            _tprintf(_T("Unable to allocate memory for subject name.\n"));
            __leave;
        }

        // Get subject name.
        if (!(CertGetNameString(pCertContext, 
                                CERT_NAME_SIMPLE_DISPLAY_TYPE,
                                0,
                                NULL,
                                szName,
                                dwData)))
        {
            _tprintf(_T("CertGetNameString failed.\n"));
            __leave;
        }

        // Print Subject Name.
        _tprintf(_T("Subject Name: %s\n"), szName);


        fReturn = TRUE;
    }
    __finally
    {
        if (szName != NULL) LocalFree(szName);
    }

    return fReturn;
}

LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
    LPWSTR outputString = NULL;

    outputString = (LPWSTR)LocalAlloc(LPTR,
        (wcslen(inputString) + 1) * sizeof(WCHAR));
    if (outputString != NULL)
    {
        lstrcpyW(outputString, inputString);
    }
    return outputString;
}

BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
                             PSPROG_PUBLISHERINFO Info)
{
    BOOL fReturn = FALSE;
    PSPC_SP_OPUS_INFO OpusInfo = NULL;  
    DWORD dwData;
    BOOL fResult;

    __try
    {
        // Loop through authenticated attributes and find
        // SPC_SP_OPUS_INFO_OBJID OID.
        for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
        {           
            if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID, 
                        pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
            {
                // Get Size of SPC_SP_OPUS_INFO structure.
                fResult = CryptDecodeObject(ENCODING,
                            SPC_SP_OPUS_INFO_OBJID,
                            pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
                            pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
                            0,
                            NULL,
                            &dwData);
                if (!fResult)
                {
                    _tprintf(_T("CryptDecodeObject failed with %x\n"),
                        GetLastError());
                    __leave;
                }

                // Allocate memory for SPC_SP_OPUS_INFO structure.
                OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
                if (!OpusInfo)
                {
                    _tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
                    __leave;
                }

                // Decode and get SPC_SP_OPUS_INFO structure.
                fResult = CryptDecodeObject(ENCODING,
                            SPC_SP_OPUS_INFO_OBJID,
                            pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
                            pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
                            0,
                            OpusInfo,
                            &dwData);
                if (!fResult)
                {
                    _tprintf(_T("CryptDecodeObject failed with %x\n"),
                        GetLastError());
                    __leave;
                }

                // Fill in Program Name if present.
                if (OpusInfo->pwszProgramName)
                {
                    Info->lpszProgramName =
                        AllocateAndCopyWideString(OpusInfo->pwszProgramName);
                }
                else
                    Info->lpszProgramName = NULL;

                // Fill in Publisher Information if present.
                if (OpusInfo->pPublisherInfo)
                {

                    switch (OpusInfo->pPublisherInfo->dwLinkChoice)
                    {
                        case SPC_URL_LINK_CHOICE:
                            Info->lpszPublisherLink =
                                AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
                            break;

                        case SPC_FILE_LINK_CHOICE:
                            Info->lpszPublisherLink =
                                AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
                            break;

                        default:
                            Info->lpszPublisherLink = NULL;
                            break;
                    }
                }
                else
                {
                    Info->lpszPublisherLink = NULL;
                }

                // Fill in More Info if present.
                if (OpusInfo->pMoreInfo)
                {
                    switch (OpusInfo->pMoreInfo->dwLinkChoice)
                    {
                        case SPC_URL_LINK_CHOICE:
                            Info->lpszMoreInfoLink =
                                AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
                            break;

                        case SPC_FILE_LINK_CHOICE:
                            Info->lpszMoreInfoLink =
                                AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
                            break;

                        default:
                            Info->lpszMoreInfoLink = NULL;
                            break;
                    }
                }               
                else
                {
                    Info->lpszMoreInfoLink = NULL;
                }

                fReturn = TRUE;

                break; // Break from for loop.
            } // lstrcmp SPC_SP_OPUS_INFO_OBJID                 
        } // for 
    }
    __finally
    {
        if (OpusInfo != NULL) LocalFree(OpusInfo);      
    }

    return fReturn;
}

BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st)
{   
    BOOL fResult;
    FILETIME lft, ft;   
    DWORD dwData;
    BOOL fReturn = FALSE;

    // Loop through authenticated attributes and find
    // szOID_RSA_signingTime OID.
    for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
    {           
        if (lstrcmpA(szOID_RSA_signingTime, 
                    pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
        {               
            // Decode and get FILETIME structure.
            dwData = sizeof(ft);
            fResult = CryptDecodeObject(ENCODING,
                        szOID_RSA_signingTime,
                        pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
                        pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
                        0,
                        (PVOID)&ft,
                        &dwData);
            if (!fResult)
            {
                _tprintf(_T("CryptDecodeObject failed with %x\n"),
                    GetLastError());
                break;
            }

            // Convert to local time.
            FileTimeToLocalFileTime(&ft, &lft);
            FileTimeToSystemTime(&lft, st);

            fReturn = TRUE;

            break; // Break from for loop.

        } //lstrcmp szOID_RSA_signingTime
    } // for 

    return fReturn;
}

BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo)
{   
    PCCERT_CONTEXT pCertContext = NULL;
    BOOL fReturn = FALSE;
    BOOL fResult;       
    DWORD dwSize;   

    __try
    {
        *pCounterSignerInfo = NULL;

        // Loop through unathenticated attributes for
        // szOID_RSA_counterSign OID.
        for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
        {
            if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, 
                         szOID_RSA_counterSign) == 0)
            {
                // Get size of CMSG_SIGNER_INFO structure.
                fResult = CryptDecodeObject(ENCODING,
                           PKCS7_SIGNER_INFO,
                           pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
                           pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
                           0,
                           NULL,
                           &dwSize);
                if (!fResult)
                {
                    _tprintf(_T("CryptDecodeObject failed with %x\n"),
                        GetLastError());
                    __leave;
                }

                // Allocate memory for CMSG_SIGNER_INFO.
                *pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
                if (!*pCounterSignerInfo)
                {
                    _tprintf(_T("Unable to allocate memory for timestamp info.\n"));
                    __leave;
                }

                // Decode and get CMSG_SIGNER_INFO structure
                // for timestamp certificate.
                fResult = CryptDecodeObject(ENCODING,
                           PKCS7_SIGNER_INFO,
                           pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
                           pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
                           0,
                           (PVOID)*pCounterSignerInfo,
                           &dwSize);
                if (!fResult)
                {
                    _tprintf(_T("CryptDecodeObject failed with %x\n"),
                        GetLastError());
                    __leave;
                }

                fReturn = TRUE;

                break; // Break from for loop.
            }           
        }
    }
    __finally
    {
        // Clean up.
        if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
    }

    return fReturn;
}

不幸的是,在处理双重签名时,我想出的方法并不总是能正确工作。

例如,一个工作示例。如果我在 Sysiternal 的 ProcMon 上运行它,它具有双重签名,正如我们从 Windows 资源管理器中看到的那样:

我的代码正确检索

SHA1
SHA256
签名:

但是,这是一个“不工作”的例子。如果我在其他一些双签名文件上运行它,例如 Putty 可执行文件,它也具有双签名:

上面的代码两次检索相同的

SHA256

证书:


知道为什么吗?

PS。这不仅仅发生在 Putty 签名上。还有其他具有相同行为的双签名可执行文件。

c++ winapi digital-signature code-signing authenticode
3个回答
4
投票

+-----------+ +-------------------+ +---------+ | Root Cert | signs | Intermediate Cert | signs | PE Data | |-----------|=========>|-------------------|=========>|---------| | SHA256 | | SHA256 | | SHA1 | +-----------+ +-------------------+ +---------+ ^ ^ | | You are showing But you this want to show this

Authenticode 的工作方式是,首先使用有时(微软)称为“摘要算法”的方法来计算文件摘要。然后使用提供证书的签名密钥对该摘要进行签名。但该证书本身是通过使用所谓的“签名摘要”计算其摘要并使用证书链中更高级别的证书中的密钥对其进行签名等来进行签名的。

可以使用

CertFindCertificateInStore

函数获取证书链中的第一个证书。然后,您应该在 while 循环中继续调用

CertFindCertificateInStore
来获取其他证书。您在代码中所做的就是获取证书链中的第一个证书(带有
CertFindCertificateInStore
)并打印其签名摘要算法。相反,您想要做的是获取并打印文件签名的摘要算法。您可以使用
CryptMsgGetParam
CMSG_SIGNER_INFO_PARAM
标志来做到这一点,并且您确实获得了它,只是不打印它。

思考这个问题的另一种方式是根据
MSG_SIGNER_INFO

CERT_INFO
之间的关系。这不是信息需要匹配的 1-1 关系。它更像是:

+---------------+ +---------------+ | SIGNER_INFO 1 | | SIGNER_INFO 2 | |---------------| |---------------| | SHA1 | | SHA256 | +---------------+ +---------------+ | | | +-------------+ | +-------------+ +---| CERT_INFO 1 | +---| CERT_INFO 3 | |-------------| |-------------| | SHA256 | | SHA256 | +-------------+ +-------------+ | | +-------------+ +-------------+ | CERT_INFO 2 | | CERT_INFO 4 | |-------------| |-------------| | SHA1 | | SHA1 | +-------------+ +-------------+
    

4
投票

这是更新后的代码。使用前请务必检查,如有问题请发表评论:

#include <new> #include <windows.h> #include <wincrypt.h> #include <wintrust.h> #include <stdio.h> #include <tchar.h> #include <atlconv.h> #pragma comment(lib, "crypt32.lib") #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) enum RESULT_FIND_CONTEXT{ RFC_FOUND_CONTEXT, RFC_NO_CONTEXT, }; enum RESULT_FIND_CERT_STORE{ RFCS_ERROR = -1, RFCS_NONE = 0, RFCS_FOUND_ONE = 1, }; void RetrieveDigitalSignatureInfo(const WCHAR* pFilePath); void PrintProgramAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo); RESULT_FIND_CONTEXT PrintCertificateInformation(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc = NULL); void PrintCertContextDetails(PCCERT_CONTEXT pCertContext, DWORD dwNameOutputType, CRYPT_ALGORITHM_IDENTIFIER* pHashAlgo); void PrintDigestAlgorithmName(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo); BOOL PrintSignerDateTime(FILETIME* pftUtc); int PrintSignerTimeStampDateTime(PCMSG_SIGNER_INFO pSignerInfo); RESULT_FIND_CERT_STORE FindCertStoreByIndex(int iIndex, HCERTSTORE& hOutStore, CRYPT_DATA_BLOB* p7Data = NULL); void PrintDualSignatureInformation(PCMSG_SIGNER_INFO pSignerInfo); void FindAppropriateStoreAndPrintCertificateInformation(PCMSG_SIGNER_INFO pSignerInfo, CRYPT_DATA_BLOB* p7Data, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc = NULL); int _tmain(int argc, WCHAR* argv[]) { LPCTSTR pExePath; if(argc <= 1) { pExePath = L"C:\\Users\\UserName\\Downloads\\procmon.exe"; //pExePath = L"C:\\Users\\UserName\\Downloads\\putty.exe"; } else { //Otherwise use first argument from command line pExePath = argv[1]; } _tprintf(L"File: %s\n", pExePath); RetrieveDigitalSignatureInfo(pExePath); return 0; } //The following functions were re-written from the following source to be able to //retrieve dual-signatures from PE binaries: // // https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-signed-executables void RetrieveDigitalSignatureInfo(const WCHAR* pFilePath) { HCERTSTORE hStore = NULL; HCRYPTMSG hMsg = NULL; if(CryptQueryObject(CERT_QUERY_OBJECT_FILE, pFilePath, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &hStore, &hMsg, NULL)) { //We must have at least one signer DWORD dwCountSigners = 0; DWORD dwcbSz = sizeof(dwCountSigners); if(CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwCountSigners, &dwcbSz)) { if(dwCountSigners != 0) { //Get Signer Information dwcbSz = 0; CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwcbSz); if(dwcbSz) { PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwcbSz]; if(pSignerInfo) { DWORD dwcbSz2 = dwcbSz; if(CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwcbSz) && dwcbSz == dwcbSz2) { //Print program publisher info PrintProgramAndPublisherInfo(pSignerInfo); _tprintf(L"\n"); //Print signer certificate info if(PrintCertificateInformation(hStore, pSignerInfo, L"Signer Certificate", FALSE) == RFC_NO_CONTEXT) { _tprintf(L"ERROR: (0x%X) CertFindCertificateInStore(CERT_FIND_SUBJECT_CERT) data failed\n", ::GetLastError()); } //Print dual-signature info PrintDualSignatureInformation(pSignerInfo); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError()); //Free mem delete[] pSignerInfo; pSignerInfo = NULL; } else _tprintf(L"ERROR: (0x%X) new(PCMSG_SIGNER_INFO) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: Must have to least one signer\n"); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_COUNT_PARAM) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptQueryObject(CERT_QUERY_OBJECT_FILE) failed\n", ::GetLastError()); //Clear up if (hStore != NULL) { CertCloseStore(hStore, 0); hStore = NULL; } if (hMsg != NULL) { CryptMsgClose(hMsg); hMsg = NULL; } } void PrintProgramAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo) { // Loop through authenticated attributes and find SPC_SP_OPUS_INFO_OBJID OID. for(DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) { if(pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) { if(lstrcmpA(pSignerInfo->AuthAttrs.rgAttr[n].pszObjId, SPC_SP_OPUS_INFO_OBJID) == 0) { // Get Size of SPC_SP_OPUS_INFO structure. PSPC_SP_OPUS_INFO pInfo = NULL; DWORD dwcbSz = 0; if(CryptDecodeObjectEx(ENCODING, SPC_SP_OPUS_INFO_OBJID, pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &pInfo, &dwcbSz) && pInfo && dwcbSz) { if(pInfo->pwszProgramName) { _tprintf(L"Program Name: %s\n", pInfo->pwszProgramName); } if (pInfo->pPublisherInfo) { switch (pInfo->pPublisherInfo->dwLinkChoice) { case SPC_URL_LINK_CHOICE: _tprintf(L"Publisher Link: %s\n", pInfo->pPublisherInfo->pwszUrl); break; case SPC_FILE_LINK_CHOICE: _tprintf(L"Publisher Link: %s\n", pInfo->pPublisherInfo->pwszFile); break; } } if (pInfo->pMoreInfo) { switch (pInfo->pMoreInfo->dwLinkChoice) { case SPC_URL_LINK_CHOICE: _tprintf(L"MoreInfo Link: %s\n", pInfo->pMoreInfo->pwszUrl); break; case SPC_FILE_LINK_CHOICE: _tprintf(L"MoreInfo Link: %s\n", pInfo->pMoreInfo->pwszFile); break; } } } else _tprintf(L"ERROR: (0x%X) CryptDecodeObjectEx(SPC_SP_OPUS_INFO_OBJID) data failed\n", ::GetLastError()); if(pInfo) { ::LocalFree(pInfo); pInfo = NULL; } } } } } RESULT_FIND_CONTEXT PrintCertificateInformation(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc) { CERT_INFO ci = {0}; ci.Issuer = pSignerInfo->Issuer; ci.SerialNumber = pSignerInfo->SerialNumber; PCCERT_CONTEXT pCertContext = NULL; DWORD dwcbSz; int c = 0; for(;; c++) { //Enumerate and look for needed cert context pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&ci, pCertContext); if(!pCertContext) { break; } if(!c) { //Print Signer certificate information. _tprintf(L"%s:\n", pStrCertDescription); if(!bIsTimeStamp) { _tprintf(L"----------------\n"); } _tprintf(L"\n"); } //In case of a timestamp if(bIsTimeStamp) { //Print time stamp if(!pftTimeStampUtc) { //Retrieve and print it if(PrintSignerTimeStampDateTime(pSignerInfo) == 0) { _tprintf(L"ERROR: (0x%X) Failed to retrieve date/time for TimeStamp\n", ::GetLastError()); } } else { //We have a time-stamp already if(!PrintSignerDateTime(pftTimeStampUtc)) { _tprintf(L"ERROR: (0x%X) Time conversion failed from %I64x\n", ::GetLastError(), *(ULONGLONG*)pftTimeStampUtc); } } } //Print subject name, issuer name, serial, signature algorithm PrintCertContextDetails(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, //Or use CERT_NAME_RDN_TYPE for a more detailed output &pSignerInfo->HashAlgorithm); volatile static char pmsgDoNotCopyAsIs[] = "Please read & verify this code before you " "copy-and-paste it into your production project! " "https://stackoverflow.com/q/50976612/3170929 " "{438EE426-7131-4498-8AF7-9DDCB2508F0C}"; srand(rand()^pmsgDoNotCopyAsIs[0]); _tprintf(L"\n"); #ifndef szOID_RFC3161_counterSign #define szOID_RFC3161_counterSign "1.3.6.1.4.1.311.3.3.1" #endif if(!bIsTimeStamp) { //Get time stamp certificate(s) //Loop through unathenticated attributes and look for specific OIDs for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++) { if(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId) { if(lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, szOID_RSA_counterSign) == 0) { //This is a legacy signature standard PCMSG_SIGNER_INFO pCounterSignerInfo = NULL; dwcbSz = 0; if(CryptDecodeObjectEx(ENCODING, PKCS7_SIGNER_INFO, pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData, pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &pCounterSignerInfo, &dwcbSz) && pCounterSignerInfo && dwcbSz) { //Got one signature if(PrintCertificateInformation(hStore, pCounterSignerInfo, L"TimeStamp Certificate", TRUE) == RFC_NO_CONTEXT) { _tprintf(L"ERROR: (0x%X) CertFindCertificateInStore(CERT_FIND_SUBJECT_CERT) data failed\n", ::GetLastError()); } } else { _tprintf(L"ERROR: (0x%X) CryptDecodeObjectEx(PKCS7_SIGNER_INFO) failed\n", ::GetLastError()); } //Free mem if(pCounterSignerInfo) { ::LocalFree(pCounterSignerInfo); pCounterSignerInfo = NULL; } } else if(lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, szOID_RFC3161_counterSign) == 0) { //Using an RFC3161 time stamp if(pSignerInfo->UnauthAttrs.rgAttr[n].cValue != 0) { HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(ENCODING, 0, 0, NULL, NULL, NULL); if(hMsg) { if(::CryptMsgUpdate(hMsg, pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->pbData, pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->cbData, TRUE)) { dwcbSz = 0; ::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &dwcbSz); if(dwcbSz != 0) { BYTE* pCntData = new (std::nothrow) BYTE[dwcbSz]; if(pCntData) { if(::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pCntData, &dwcbSz)) { //Retrieve time stamp FILETIME ftUtc = {0}; void* pTmData = NULL; DWORD dwcbTmDataSz = 0; struct Microsoft_forgot_to_document_me{ void* something_0[9]; FILETIME ftUtc; }; #ifndef TIMESTAMP_INFO #define TIMESTAMP_INFO ((LPCSTR) 80) #endif if(CryptDecodeObjectEx(ENCODING, //X509_ASN_ENCODING, TIMESTAMP_INFO, pCntData, dwcbSz, CRYPT_DECODE_ALLOC_FLAG, NULL, &pTmData, &dwcbTmDataSz) && pTmData && dwcbTmDataSz >= sizeof(Microsoft_forgot_to_document_me)) { ftUtc = ((Microsoft_forgot_to_document_me*)pTmData)->ftUtc; } else _tprintf(L"ERROR: (0x%X) CryptDecodeObjectEx(RFC3161/TIMESTAMP_INFO) data failed\n", ::GetLastError()); if(pTmData) { ::LocalFree(pTmData); pTmData = NULL; } //Try to get signer info dwcbSz = 0; ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwcbSz); if(dwcbSz != 0) { CMSG_SIGNER_INFO* pTmSignerData = (CMSG_SIGNER_INFO*)new (std::nothrow) BYTE[dwcbSz]; if(pTmSignerData) { if(::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pTmSignerData, &dwcbSz)) { CRYPT_DATA_BLOB c7Data; c7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->pbData; c7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[n].rgValue->cbData; //Try to locate the appropriate store FindAppropriateStoreAndPrintCertificateInformation(pTmSignerData, &c7Data, L"TimeStamp Certificate", TRUE, &ftUtc); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError()); //Free mem delete[] pTmSignerData; pTmSignerData = NULL; } else _tprintf(L"ERROR: (0x%X) new(RFC3161) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_CONTENT_PARAM) data failed\n", ::GetLastError()); //Free mem delete[] pCntData; pCntData = NULL; } else _tprintf(L"ERROR: (0x%X) new(RFC3161) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(RFC3161/CMSG_CONTENT_PARAM) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgUpdate(RFC3161) failed\n", ::GetLastError()); //Free handle ::CryptMsgClose(hMsg); hMsg = NULL; } else _tprintf(L"ERROR: (0x%X) CryptMsgOpenToDecode(ENCODING) failed\n", ::GetLastError()); } } } } } } //Free if(pCertContext) { CertFreeCertificateContext(pCertContext); pCertContext = NULL; } return c != 0 ? RFC_FOUND_CONTEXT : RFC_NO_CONTEXT; } void PrintCertContextDetails(PCCERT_CONTEXT pCertContext, DWORD dwNameOutputType, CRYPT_ALGORITHM_IDENTIFIER* pHashAlgo) { //'dwNameOutputType' = one of: CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_RDN_TYPE, etc. see CertGetNameString() DWORD dwcbSz; WCHAR* pBuff; //Get subject name. dwcbSz = CertGetNameString(pCertContext, dwNameOutputType, 0, NULL, NULL, 0); if(dwcbSz != 0) { pBuff = new (std::nothrow) WCHAR[dwcbSz]; if(pBuff) { if(CertGetNameString(pCertContext, dwNameOutputType, 0, NULL, pBuff, dwcbSz) == dwcbSz) { _tprintf(L"Subject: %s\n", pBuff); } else _tprintf(L"ERROR: (0x%X) CertGetNameString(subject) data failed\n", ::GetLastError()); //Free mem delete[] pBuff; pBuff = NULL; } else _tprintf(L"ERROR: (0x%X) new CertGetNameString(subject) data failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CertGetNameString(subject) failed\n", ::GetLastError()); //Issuer dwcbSz = CertGetNameString(pCertContext, dwNameOutputType, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0); if(dwcbSz != 0) { pBuff = new (std::nothrow) WCHAR[dwcbSz]; if(pBuff) { if(CertGetNameString(pCertContext, dwNameOutputType, CERT_NAME_ISSUER_FLAG, NULL, pBuff, dwcbSz) == dwcbSz) { _tprintf(L"Issuer: %s\n", pBuff); } else _tprintf(L"ERROR: (0x%X) CertGetNameString(issuer) data failed\n", ::GetLastError()); //Free mem delete[] pBuff; pBuff = NULL; } else _tprintf(L"ERROR: (0x%X) new CertGetNameString(issuer) data failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CertGetNameString(issuer) failed\n", ::GetLastError()); //Print Serial Number. _tprintf(_T("Serial Number: ")); dwcbSz = pCertContext->pCertInfo->SerialNumber.cbData; for (DWORD n = 0; n < dwcbSz; n++) { _tprintf(_T("%02x"), pCertContext->pCertInfo->SerialNumber.pbData[dwcbSz - (n + 1)]); } _tprintf(_T("\n")); //Digest algorithm _tprintf(L"Digest Algorithm: "); PrintDigestAlgorithmName(pHashAlgo); _tprintf(_T("\n")); } void PrintDigestAlgorithmName(CRYPT_ALGORITHM_IDENTIFIER* pSigAlgo) { if(pSigAlgo && pSigAlgo->pszObjId) { PCCRYPT_OID_INFO pCOI = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pSigAlgo->pszObjId, 0); if(pCOI && pCOI->pwszName) { _tprintf(L"%s", pCOI->pwszName); } else { USES_CONVERSION; _tprintf(L"%s", A2W(pSigAlgo->pszObjId)); } } } BOOL PrintSignerDateTime(FILETIME* pftUtc) { BOOL bRes = FALSE; if(pftUtc) { //Convert to local time FILETIME ftLoc = {0}; SYSTEMTIME stLoc = {0}; if(FileTimeToLocalFileTime(pftUtc, &ftLoc) && FileTimeToSystemTime(&ftLoc, &stLoc)) { _tprintf(L"Date of TimeStamp : %02d/%02d/%04d %02d:%02d:%02d\n", stLoc.wMonth, stLoc.wDay, stLoc.wYear, stLoc.wHour, stLoc.wMinute, stLoc.wSecond); bRes = TRUE; } } else ::SetLastError(ERROR_INVALID_PARAMETER); return bRes; } int PrintSignerTimeStampDateTime(PCMSG_SIGNER_INFO pSignerInfo) { int nCountTimeStamps = 0; //Loop through authenticated attributes for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) { if (pSignerInfo->AuthAttrs.rgAttr[n].pszObjId && lstrcmpA(pSignerInfo->AuthAttrs.rgAttr[n].pszObjId, szOID_RSA_signingTime) == 0) { // Decode and get FILETIME structure. FILETIME ftUtc = {0}; DWORD dwData = sizeof(ftUtc); if(CryptDecodeObject(ENCODING, PKCS_UTC_TIME, pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, 0, (PVOID)&ftUtc, &dwData)) { //Got time stamp nCountTimeStamps++; //And print it if(!PrintSignerDateTime(&ftUtc)) { _tprintf(L"ERROR: (0x%X) Time conversion failed from %I64x\n", ::GetLastError(), *(ULONGLONG*)&ftUtc); } } else { _tprintf(L"ERROR: (0x%X) CryptDecodeObject(PKCS_UTC_TIME) failed\n", ::GetLastError()); } } } return nCountTimeStamps; } RESULT_FIND_CERT_STORE FindCertStoreByIndex(int iIndex, HCERTSTORE& hOutStore, CRYPT_DATA_BLOB* p7Data) { //'hOutStore' = receives cert store handle. If not NULL, make sure to release it by calling CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG); //'p7Data' = used with index 0 only hOutStore = NULL; switch (iIndex) { case 0: hOutStore = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, p7Data); break; case 1: hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000, // flags = 0x18001 "ROOT"); break; case 2: hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000, // flags = 0x18001 "TRUST"); break; case 3: hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000, // flags = 0x18001 "CA"); break; case 4: hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x10000, // flags = 0x18001 "MY"); break; case 5: hOutStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_READONLY_FLAG | 0x20000, // flags = 0x28001 "SPC"); break; default: return RFCS_NONE; } return hOutStore ? RFCS_FOUND_ONE : RFCS_ERROR; } void FindAppropriateStoreAndPrintCertificateInformation(PCMSG_SIGNER_INFO pSignerInfo, CRYPT_DATA_BLOB* p7Data, LPCTSTR pStrCertDescription, BOOL bIsTimeStamp, FILETIME* pftTimeStampUtc) { HCERTSTORE hStore = NULL; //Try to locate the appropriate store for(int i = 0;; i++) { if(hStore) { CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG); hStore = NULL; } RESULT_FIND_CERT_STORE resFnd = FindCertStoreByIndex(i, hStore, p7Data); if(resFnd == RFCS_FOUND_ONE) { //Try to retrieve info if(PrintCertificateInformation(hStore, pSignerInfo, pStrCertDescription, bIsTimeStamp, pftTimeStampUtc) == RFC_FOUND_CONTEXT) { //All done break; } } else { //Stop the seatch if(resFnd == RFCS_NONE) { //No context _tprintf(L"ERROR: (0x%X) CertOpenStore(no_context) failed\n", ::GetLastError()); } else { //Error _tprintf(L"ERROR: (0x%X) CertOpenStore(%i) data failed\n", ::GetLastError(), i); } break; } } if(hStore) { ::CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG); hStore = NULL; } } void PrintDualSignatureInformation(PCMSG_SIGNER_INFO pSignerInfo) { //Loop through unauthenticated attributes for(DWORD a = 0; a < pSignerInfo->UnauthAttrs.cAttr; a++) { #ifndef szOID_NESTED_SIGNATURE #define szOID_NESTED_SIGNATURE "1.3.6.1.4.1.311.2.4.1" #endif //We need szOID_NESTED_SIGNATURE att if(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId && lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId, szOID_NESTED_SIGNATURE) == 0) { HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL); if(hMsg) { if(::CryptMsgUpdate(hMsg, pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData, pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData, TRUE)) { DWORD dwSignerInfo = 0; ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo); if(dwSignerInfo != 0) { PCMSG_SIGNER_INFO pSignerInfo2 = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwSignerInfo]; if(pSignerInfo2) { if(::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo2, &dwSignerInfo)) { CRYPT_DATA_BLOB c7Data; c7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData; c7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData; //Try to locate the appropriate store & print from it FindAppropriateStoreAndPrintCertificateInformation(pSignerInfo2, &c7Data, L"Dual Signer Certificate", FALSE); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) data failed\n", ::GetLastError()); //Free mem delete[] pSignerInfo2; pSignerInfo2 = NULL; } else _tprintf(L"ERROR: (0x%X) new(PCMSG_SIGNER_INFO) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed\n", ::GetLastError()); } else _tprintf(L"ERROR: (0x%X) CryptMsgUpdate(dual-sig) failed\n", ::GetLastError()); //Close message ::CryptMsgClose(hMsg); } else _tprintf(L"ERROR: (0x%X) CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) failed\n", ::GetLastError()); } } }



0
投票
Microsoft_forgot_to_document_me

使用的 scruct 的人来说,是

CRYPT_TIMESTAMP_INFO
。 它还没有记录,将通过微软文档添加它。
    

© www.soinside.com 2019 - 2024. All rights reserved.