程序签名自校验 ,防止程序被病毒注入

该代码实现了一个用于软件数字签名校验的函数,通过WinVerifyTrust API检查程序是否被篡改。它首先获取文件的签名信息,然后从签名中提取公钥,并与传入的公钥TLV数据进行比较,确保两者一致以验证签名的合法性。
摘要由CSDN通过智能技术生成
/*****************************************************/
/*              软件本身数字签名校验
/*参数:
/*	    unsigned char* pubkeyTLV       公钥TLV数据
/*		unsigned int uiPubKLen         数据长度
/*返回值:
/*		TRUE		签名正常,程序未被改动
/*		FALSE       签名无效,程序被篡改
/*****************************************************/

BOOL CodeSigningCheck(unsigned char* pubkeyTLV, unsigned int uiPubKLen) {
    WCHAR wPath[MAX_PATH] = L"C:\\Users\\hdzblxn\\Downloads\\Signtool GUI\\signInvalid.exe";
    //GetModuleFileNameW(NULL, wPath, MAX_PATH);


    //判断是否有
    GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
    WINTRUST_FILE_INFO FileData;
    memset(&FileData, 0, sizeof(FileData));
    FileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
    FileData.pcwszFilePath = (LPCWSTR)wPath;
    FileData.hFile = NULL;
    FileData.pgKnownSubject = NULL;

    WINTRUST_DATA WinTrustData;
    memset(&WinTrustData, 0, sizeof(WINTRUST_DATA));
    WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
    WinTrustData.pPolicyCallbackData = NULL;
    WinTrustData.pSIPClientData = NULL;
    WinTrustData.dwUIChoice = WTD_UI_NONE;
    WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
    WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
    WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
    WinTrustData.hWVTStateData = NULL;
    WinTrustData.pwszURLReference = NULL;
    WinTrustData.dwProvFlags = WTD_SAFER_FLAG;
    WinTrustData.dwUIContext = 0;
    WinTrustData.pFile = &FileData;

    HRESULT hr = WinVerifyTrust(NULL, &guidAction, &WinTrustData);

    WinTrustData.dwUIChoice = WTD_UI_NONE;
    WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
    WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &WinTrustData);
    if (hr != S_OK) {
        return FALSE;
    }

    HCERTSTORE		  hStore = NULL;
    HCRYPTMSG		  hMsg = NULL;
    PCCERT_CONTEXT    pCertContext = NULL;
    BOOL			  bResult;
    DWORD dwEncoding, dwContentType, dwFormatType;
    PCMSG_SIGNER_INFO pSignerInfo = NULL;
    PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
    DWORD			  dwSignerInfo;
    CERT_INFO		  CertInfo;
    SYSTEMTIME        st;
    LONG              lRet;
    DWORD             dwDataSize = 0;

    char   chTemp[MAX_PATH] = { 0 };

    //从签名文件中获取存储句柄
    bResult = CryptQueryObject(
                            CERT_QUERY_OBJECT_FILE,
                            wPath,
                            CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                            CERT_QUERY_FORMAT_FLAG_BINARY,
                            0,
                            &dwEncoding,
                            &dwContentType,
                            &dwFormatType,
                            &hStore,
                            &hMsg,
                            NULL
                        );

    if (!bResult){
        return FALSE;
    }

    获取签名个数
    //DWORD certNum = 0;
    //DWORD certNumSize = sizeof(certNum);
    //bResult = CryptMsgGetParam(
    //        hMsg,
    //        CMSG_SIGNER_COUNT_PARAM,
    //        0,
    //        &certNum,
    //        &certNumSize
    //    );


    //获取签名信息所需的缓冲区大小
    bResult = CryptMsgGetParam(
                                hMsg,
                                CMSG_SIGNER_INFO_PARAM,
                                0,
                                NULL,
                                &dwSignerInfo
                            );
    if (!bResult){
        return FALSE;
    }

    //分配缓冲区
    pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
    if (pSignerInfo == NULL){
        return FALSE;
    }


    //获取签名信息
    bResult = CryptMsgGetParam(
                                hMsg,
                                CMSG_SIGNER_INFO_PARAM,
                                0,
                                pSignerInfo,
                                &dwSignerInfo
                            );
    if (!bResult){
        LocalFree((HLOCAL)pSignerInfo);
        return FALSE;
    }

    CertInfo.Issuer = pSignerInfo->Issuer;
    CertInfo.SerialNumber = pSignerInfo->SerialNumber;

    //获取签名证书公钥
    pCertContext = CertFindCertificateInStore(
                                            hStore,
                                            dwEncoding,
                                            0,
                                            CERT_FIND_SUBJECT_CERT,
                                            (PVOID)&CertInfo,
                                            NULL
                                        );
    LocalFree((HLOCAL)pSignerInfo);
    if (pCertContext == NULL){
        return FALSE;
    }
    CRYPT_BIT_BLOB& pubkBlob = pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;

    //对比公钥TLV结构
    if (uiPubKLen != pubkBlob.cbData || memcmp(pubkeyTLV, pubkBlob.pbData, uiPubKLen) != 0) {
        CertFreeCertificateContext(pCertContext);
        pCertContext = NULL;
        CertCloseStore(hStore, NULL);
        hStore = NULL;
        return FALSE;
    }
    
    CertFreeCertificateContext(pCertContext);
    pCertContext = NULL;
    CertCloseStore(hStore, NULL);
    hStore = NULL;
    return TRUE;
}

其中入参 pubkeyTLV 是签名的证书公钥数据(TLV)
在这里插入图片描述
入参 uiPubKLen ,对于2048RSA证书来说,是270

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值