Reading multiple signatures from executable file

后端 未结 4 1551
余生分开走
余生分开走 2020-12-28 18:43

I am trying to write code that reads signatures (certificates) from DLLs or and EXEs. Most DLLs or EXEs have only one signature, and my code reads all certificates associate

4条回答
  •  醉酒成梦
    2020-12-28 18:47

    Expanding the Dima's answer, I want to provide a sample code which demonstrates how to check all embedded (and nested) leaf (not in the middle of the certificate chain) certificates.

    BOOL CheckCertificateIssuer(HANDLE hWVTStateData, const std::set &stValidIssuers)
    {
        CRYPT_PROVIDER_DATA *pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData);
        CRYPT_PROVIDER_SGNR *pSigner = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0);
        CRYPT_PROVIDER_CERT *pCert = WTHelperGetProvCertFromChain(pSigner, 0);
    
        CString sIssuer;
        int nLength = CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
        if (!nLength)
        {
            ASSERT(FALSE && "Cannot get the length of the Issuer string");
            return FALSE;
        }
    
        if (!CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, sIssuer.GetBuffer(nLength), nLength))
        {
            ASSERT(FALSE && "Cannot get the Issuer string");
            return FALSE;
        }
        sIssuer.ReleaseBuffer(nLength);
        if (stValidIssuers.find(sIssuer) == stValidIssuers.end())
        {
            ASSERT(FALSE && "Certificate issuer is invalid");
            return FALSE;
        }
        return TRUE;
    }
    BOOL CheckCertificate(CString filename)
    {
        std::set stValidIssuers;
        stValidIssuers.insert(L"VeriSign Class 3 Code Signing 2010 CA");
        stValidIssuers.insert(L"Symantec Class 3 SHA256 Code Signing CA");
    
        bool UseStrongSigPolicy = false;
    
        DWORD Error = ERROR_SUCCESS;
        bool WintrustCalled = false;
        GUID GenericActionId = WINTRUST_ACTION_GENERIC_VERIFY_V2;
        WINTRUST_DATA WintrustData = {};
        WINTRUST_FILE_INFO FileInfo = {};
        WINTRUST_SIGNATURE_SETTINGS SignatureSettings = {};
        CERT_STRONG_SIGN_PARA StrongSigPolicy = {};
    
        // Setup data structures for calling WinVerifyTrust
        WintrustData.cbStruct = sizeof(WINTRUST_DATA);
        WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
        WintrustData.dwUIChoice = WTD_UI_NONE;
        WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
        WintrustData.dwUnionChoice = WTD_CHOICE_FILE;
    
        FileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO_);
        FileInfo.pcwszFilePath = filename;
        WintrustData.pFile = &FileInfo;
    
        //
        // First verify the primary signature (index 0) to determine how many secondary signatures
        // are present. We use WSS_VERIFY_SPECIFIC and dwIndex to do this, also setting
        // WSS_GET_SECONDARY_SIG_COUNT to have the number of secondary signatures returned.
        //
        SignatureSettings.cbStruct = sizeof(WINTRUST_SIGNATURE_SETTINGS);
        SignatureSettings.dwFlags = WSS_GET_SECONDARY_SIG_COUNT | WSS_VERIFY_SPECIFIC;
        SignatureSettings.dwIndex = 0;
        WintrustData.pSignatureSettings = &SignatureSettings;
    
        if (UseStrongSigPolicy != false)
        {
            StrongSigPolicy.cbSize = sizeof(CERT_STRONG_SIGN_PARA);
            StrongSigPolicy.dwInfoChoice = CERT_STRONG_SIGN_OID_INFO_CHOICE;
            StrongSigPolicy.pszOID = szOID_CERT_STRONG_SIGN_OS_CURRENT;
            WintrustData.pSignatureSettings->pCryptoPolicy = &StrongSigPolicy;
        }
        BOOL bResult = E_NOT_SET;
        TRACE(L"Verifying primary signature... ");
        Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
        WintrustCalled = true;
        if (Error == ERROR_SUCCESS)
        {
            if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers))
            {
                if (bResult == E_NOT_SET)
                    bResult = TRUE;
            }
            else
            {
                bResult = FALSE;
            }
    
            TRACE(L"Success!\n");
    
            TRACE(L"Found %d secondary signatures\n", WintrustData.pSignatureSettings->cSecondarySigs);
    
            // Now attempt to verify all secondary signatures that were found
            for (DWORD x = 1; x <= WintrustData.pSignatureSettings->cSecondarySigs; x++)
            {
                TRACE(L"Verify secondary signature at index %d... ", x);
    
                // Need to clear the previous state data from the last call to WinVerifyTrust
                WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
                Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
                if (Error != ERROR_SUCCESS)
                {
                    //No need to call WinVerifyTrust again
                    WintrustCalled = false;
                    TRACE(L"%s", utils::error::getText(Error));
                    ASSERT(FALSE);
                    break;
                }
    
                WintrustData.hWVTStateData = NULL;
    
                // Caller must reset dwStateAction as it may have been changed during the last call
                WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
                WintrustData.pSignatureSettings->dwIndex = x;
                Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
                if (Error != ERROR_SUCCESS)
                {
                    TRACE(L"%s", utils::error::getText(Error));
                    ASSERT(FALSE);
                    break;
                }
    
                if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers))
                {
                    if (bResult == E_NOT_SET)
                        bResult = TRUE;
                }
                else
                {
                    bResult = FALSE;
                }
    
    
                TRACE(L"Success!\n");
            }
        }
        else
        {
            TRACE(utils::error::getText(Error));
            ASSERT(FALSE);
        }
    
        //
        // Caller must call WinVerifyTrust with WTD_STATEACTION_CLOSE to free memory
        // allocate by WinVerifyTrust
        //
        if (WintrustCalled != false)
        {
            WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
            WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
        }
    
        return bResult;
    
    }
    

提交回复
热议问题