/*****************************************************/
/* 软件本身数字签名校验
/*参数:
/* 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