如何检索文件数字签名信息?

我已经search了一种从数字签名的PE文件中检索信息的方法。 我需要发布者,发布者链接,发行者名称和主题名称。 我需要winapi / c / c ++代码(函数),我需要一个快速的方法,我不需要检查签名是否有效。

Microsoft提供了一种在此支持链接中执行此操作的方法: 如何从Authenticode签名的可执行文件获取信息

您可以使用WinVerifyTrust()API来验证Authenticode签名的可执行文件。

虽然签名已被验证,但程序可能还需要执行以下操作:

  • 确定签名可执行文件的证书的详细信息。
  • 确定文件带有时间戳的日期和时间。
  • 检索与该文件关联的URL链接。
  • 检索时间戳证书。

本文演示如何使用CryptQueryObject()API从Authenticode签名的可执行文件中检索详细信息。

这是我为我的一个项目编写的代码,将会这样做。 它在NSIGINFO类型的结构中返回细节。 随意使用它 – 没有必要的归属,但我将不胜感激,如果你会保留版权完好无损。

如果有任何功能缺失(我必须从几个不同的地方巩固东西,所以我可能错过了什么),请让我知道,我会做出必要的调整。

让我知道这是如何工作的。 祝你好运。

头文件NAuthenticode.h

 // NAuthenticode.h: Functions for checking signatures in files // // Copyright (c) 2008-2012, Nikolaos D. Bougalis <nikb@bougalis.net> #ifndef B82FBB5B_C0F8_43A5_9A31_619BB690706C #define B82FBB5B_C0F8_43A5_9A31_619BB690706C #include <wintrust.h> #include <softpub.h> #include <imagehlp.h> struct NSIGINFO { LONG lValidationResult; LPTSTR lpszPublisher; LPTSTR lpszPublisherEmail; LPTSTR lpszPublisherUrl; LPTSTR lpszAuthority; LPTSTR lpszFriendlyName; LPTSTR lpszProgramName; LPTSTR lpszPublisherLink; LPTSTR lpszMoreInfoLink; LPTSTR lpszSignature; LPTSTR lpszSerial; BOOL bHasSigTime; SYSTEMTIME stSigTime; }; VOID NCertFreeSigInfo(NSIGINFO *pSigInfo); BOOL NVerifyFileSignature(LPCTSTR lpszFileName, NSIGINFO *pSigInfo, HANDLE hHandle = INVALID_HANDLE_VALUE); BOOL NCertGetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, LPTSTR *lpszNameString); BOOL NCheckFileCertificates(HANDLE hFile, VOID (*pCallback)(PCCERT_CONTEXT, LPVOID), PVOID pParam); #endif 

实现, NAuthenticode.cpp

 // NAuthenticode.cpp: Various routines related to validating file signatures // // Copyright (c) 2008-2012, Nikolaos D. Bougalis <nikb@bougalis.net> #include "stdafx.h" #include "NAuthenticode.h" ////////////////////////////////////////////////////////////////////////// #pragma comment(lib, "crypt32") #pragma comment(lib, "imagehlp") #pragma comment(lib, "wintrust") ////////////////////////////////////////////////////////////////////////// #define SIG_ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) ////////////////////////////////////////////////////////////////////////// // Some utility functions LPVOID NHeapAlloc(SIZE_T dwBytes) { if(dwBytes == 0) return NULL; return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes); } ////////////////////////////////////////////////////////////////////////// LPVOID NHeapFree(LPVOID lpMem) { if(lpMem != NULL) HeapFree(GetProcessHeap(), 0, lpMem); return NULL; } ////////////////////////////////////////////////////////////////////////// LPSTR NConvertW2A(LPCWSTR lpszString, int nLen, UINT nCodePage) { ASSERT(lpszString != NULL); int ret = WideCharToMultiByte(nCodePage, 0, lpszString, nLen, NULL, 0, NULL, NULL); if(ret <= 0) return NULL; LPSTR lpszOutString = (LPSTR)NHeapAlloc((ret + 1) * sizeof(CHAR)); if(lpszOutString == NULL) return NULL; ret = WideCharToMultiByte(nCodePage, 0, lpszString, nLen, lpszOutString, ret, NULL, NULL); if(ret <= 0) lpszOutString = (LPSTR)NHeapFree(lpszOutString); return lpszOutString; } ////////////////////////////////////////////////////////////////////////// LPWSTR NDupString(LPCWSTR lpszString, int nLen) { if(nLen == -1) nLen = (int)wcslen(lpszString); LPWSTR lpszOutString = (LPWSTR)NHeapAlloc((2 + nLen) * sizeof(WCHAR)); if((lpszOutString != NULL) && (nLen != 0)) wcsncpy(lpszOutString, lpszString, nLen + 1); return lpszOutString; } ////////////////////////////////////////////////////////////////////////// LPTSTR NConvertW2T(LPCWSTR lpszString, int nLen, UINT nCodePage) { ASSERT(lpszString != NULL); #ifndef UNICODE return (LPTSTR)NConvertW2A(lpszString, nLen, nCodePage); #else return (LPTSTR)NDupString(lpszString, nLen); #endif } ////////////////////////////////////////////////////////////////////////// LPWSTR NConvertA2W(LPCSTR lpszString, int nLen, UINT nCodePage) { ASSERT(lpszString != NULL); int ret = MultiByteToWideChar(nCodePage, 0, lpszString, nLen, NULL, 0); if(ret <= 0) return NULL; LPWSTR lpszOutString = (LPWSTR)NHeapAlloc((ret + 1) * sizeof(WCHAR)); if(lpszOutString == NULL) return NULL; ret = MultiByteToWideChar(nCodePage, 0, lpszString, nLen, lpszOutString, ret); if(ret <= 0) lpszOutString = (LPWSTR)NHeapFree(lpszOutString); return lpszOutString; } ////////////////////////////////////////////////////////////////////////// LPWSTR NConvertT2W(LPCTSTR lpszString, int nLen, UINT nCodePage) { ASSERT(lpszString != NULL); #ifndef UNICODE return NConvertA2W((LPCSTR)lpszString, nLen, nCodePage); #else return NDupString((LPWSTR)lpszString, nLen); #endif } ////////////////////////////////////////////////////////////////////////// VOID NCertFreeSigInfo(NSIGINFO *pSigInfo) { if(pSigInfo == NULL) return; __try { // Be extra careful if(pSigInfo->lpszPublisher) pSigInfo->lpszPublisher = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszPublisherEmail) pSigInfo->lpszPublisherEmail = (LPTSTR)NHeapFree(pSigInfo->lpszPublisherEmail); if(pSigInfo->lpszPublisherUrl) pSigInfo->lpszPublisherUrl = (LPTSTR)NHeapFree(pSigInfo->lpszPublisherUrl); if(pSigInfo->lpszAuthority) pSigInfo->lpszAuthority = (LPTSTR)NHeapFree(pSigInfo->lpszAuthority); if(pSigInfo->lpszProgramName) pSigInfo->lpszProgramName = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszPublisherLink) pSigInfo->lpszPublisherLink = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszMoreInfoLink) pSigInfo->lpszMoreInfoLink = (LPTSTR)NHeapFree(pSigInfo->lpszMoreInfoLink); if(pSigInfo->lpszSignature) pSigInfo->lpszSignature = (LPTSTR)NHeapFree(pSigInfo->lpszSignature); if(pSigInfo->lpszSerial) pSigInfo->lpszSerial = (LPTSTR)NHeapFree(pSigInfo->lpszSerial); } __except(EXCEPTION_EXECUTE_HANDLER) { } } ////////////////////////////////////////////////////////////////////////// static BOOL NCertGetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, LPTSTR *lpszNameString) { if(pCertContext == NULL) return FALSE; DWORD dwData = CertGetNameString(pCertContext, dwType, 0, NULL, NULL, 0); if(dwData == 0) return FALSE; *lpszNameString = (LPTSTR)NHeapAlloc((dwData + 1) * sizeof(TCHAR)); if(*lpszNameString == NULL) return FALSE; dwData = CertGetNameString(pCertContext, dwType, dwFlags, NULL, *lpszNameString, dwData); if(dwData == 0) { NHeapFree(*lpszNameString); return FALSE; } return TRUE; } ////////////////////////////////////////////////////////////////////////// static BOOL NCryptDecodeObject(__in LPCSTR lpszObjectId, __in_bcount(cbEncoded) const BYTE *pbEncoded, __in DWORD cbEncoded, __inout DWORD &dwBuffer, __out void *pBuffer = NULL, __in DWORD dwFlags = 0) { if(((pBuffer == NULL) && (dwBuffer != 0)) || ((dwBuffer == 0) && (pBuffer != NULL))) { // What? You're passing a NULL pointer an a non-zero size? You so crazy!!!! ASSERT(FALSE); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } return CryptDecodeObject(SIG_ENCODING, lpszObjectId, pbEncoded, cbEncoded, dwFlags, pBuffer, &dwBuffer); } ////////////////////////////////////////////////////////////////////////// static BOOL NCryptDecodeObject(__in LPCSTR lpszObjectId, __in PCRYPT_ATTR_BLOB pObject, __inout DWORD &dwBuffer, __out void *pBuffer = NULL, __in DWORD dwFlags = 0) { if((pObject == NULL) || ((dwBuffer == 0) && (pBuffer != NULL)) || ((dwBuffer != 0) && (pBuffer == NULL))) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } return CryptDecodeObject(SIG_ENCODING, lpszObjectId, pObject->pbData, pObject->cbData, dwFlags, pBuffer, &dwBuffer); } ////////////////////////////////////////////////////////////////////////// static BOOL WGetSignTimestamp(PCRYPT_ATTRIBUTES pAttributes, SYSTEMTIME &stTime, LPCSTR lpszObjId) { if((pAttributes == NULL) || (pAttributes->cAttr == 0) || (lpszObjId == NULL) || (*lpszObjId == 0)) return FALSE; for(DWORD dwAttr = 0; dwAttr < pAttributes->cAttr; dwAttr++) { if(strcmp(lpszObjId, pAttributes->rgAttr[dwAttr].pszObjId) == 0) { DWORD dwSize = sizeof(FILETIME); FILETIME ftCert; if(NCryptDecodeObject(lpszObjId, &pAttributes->rgAttr[dwAttr].rgValue[0], dwSize, (PVOID)&ftCert)) { FILETIME ftLocal; if(FileTimeToLocalFileTime(&ftCert, &ftLocal) && FileTimeToSystemTime(&ftLocal, &stTime)) return TRUE; } } } return FALSE; } ////////////////////////////////////////////////////////////////////////// static BOOL NVerifyFileSignatureWorker(LPWSTR lpszFileName, WINTRUST_DATA &wtData, NSIGINFO *pSigInfo) { if(pSigInfo != NULL) memset(pSigInfo, 0, sizeof(NSIGINFO)); GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2; BOOL bVerified = FALSE; LONG lRet = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &wtData); if(lRet != 0) { if(pSigInfo != NULL) pSigInfo->lValidationResult = lRet; return FALSE; } if(pSigInfo == NULL) return TRUE; HCERTSTORE hStore = NULL; HCRYPTMSG hMsg = NULL; if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, lpszFileName, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &hStore, &hMsg, NULL)) return FALSE; PCMSG_SIGNER_INFO pSignerInfo = NULL, pCounterSignerInfo = NULL; DWORD dwSignerInfo = 0, dwCounterSignerInfo = 0; if(CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo) && (dwSignerInfo != 0)) pSignerInfo = (PCMSG_SIGNER_INFO)NHeapAlloc(dwSignerInfo); if((pSignerInfo != NULL) && CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo)) { for(DWORD dwAttr = 0; dwAttr < pSignerInfo->AuthAttrs.cAttr; dwAttr++) { if((strcmp(SPC_SP_OPUS_INFO_OBJID, pSignerInfo->AuthAttrs.rgAttr[dwAttr].pszObjId) != 0)) continue; PSPC_SP_OPUS_INFO pOpus = NULL; DWORD dwData = 0; if(NCryptDecodeObject(SPC_SP_OPUS_INFO_OBJID, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData) && (dwData != 0)) pOpus = (PSPC_SP_OPUS_INFO)NHeapAlloc(dwData); if((pOpus != NULL) && NCryptDecodeObject(SPC_SP_OPUS_INFO_OBJID, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData, (PVOID)pOpus)) { pSigInfo->lpszProgramName = NConvertW2T(pOpus->pwszProgramName); if(pOpus->pPublisherInfo != NULL) { switch(pOpus->pPublisherInfo->dwLinkChoice) { case SPC_URL_LINK_CHOICE: pSigInfo->lpszPublisherLink = NConvertW2T(pOpus->pPublisherInfo->pwszUrl); break; case SPC_FILE_LINK_CHOICE: pSigInfo->lpszPublisherLink = NConvertW2T(pOpus->pPublisherInfo->pwszFile); break; } } if(pOpus->pMoreInfo != NULL) { switch (pOpus->pMoreInfo->dwLinkChoice) { case SPC_URL_LINK_CHOICE: pSigInfo->lpszMoreInfoLink = NConvertW2T(pOpus->pMoreInfo->pwszUrl); break; case SPC_FILE_LINK_CHOICE: pSigInfo->lpszMoreInfoLink = NConvertW2T(pOpus->pMoreInfo->pwszFile); break; } } } if(pOpus != NULL) NHeapFree(pOpus); break; } CERT_INFO ci; ci.Issuer = pSignerInfo->Issuer; ci.SerialNumber = pSignerInfo->SerialNumber; PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore, SIG_ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&ci, NULL); if(pCertContext != NULL) { if(pCertContext->pCertInfo->SerialNumber.cbData != 0) { pSigInfo->lpszSerial = (LPTSTR)NHeapAlloc(((pCertContext->pCertInfo->SerialNumber.cbData * 2) + 1) * sizeof(TCHAR)); if(pSigInfo->lpszSerial != NULL) { LPTSTR lpszPointer = pSigInfo->lpszSerial; for(DWORD dwCount = pCertContext->pCertInfo->SerialNumber.cbData; dwCount != 0; dwCount--) lpszPointer += _stprintf(lpszPointer, _T("%02X"), pCertContext->pCertInfo->SerialNumber.pbData[dwCount - 1]); } } if(!NCertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, &pSigInfo->lpszFriendlyName)) pSigInfo->lpszFriendlyName = NULL; if(!NCertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, &pSigInfo->lpszAuthority)) pSigInfo->lpszAuthority = NULL; if(!NCertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &pSigInfo->lpszPublisher)) pSigInfo->lpszPublisher = NULL; if(!NCertGetNameString(pCertContext, CERT_NAME_URL_TYPE, 0, &pSigInfo->lpszPublisherUrl)) pSigInfo->lpszPublisherUrl = NULL; if(!NCertGetNameString(pCertContext, CERT_NAME_EMAIL_TYPE, 0, &pSigInfo->lpszPublisherEmail)) pSigInfo->lpszPublisherEmail = NULL; CertFreeCertificateContext(pCertContext); } for(DWORD dwAttr = 0, dwData; dwAttr < pSignerInfo->AuthAttrs.cAttr; dwAttr++) { if((strcmp(szOID_RSA_signingTime, pSignerInfo->AuthAttrs.rgAttr[dwAttr].pszObjId) == 0) && (pSignerInfo->AuthAttrs.rgAttr[dwAttr].cValue != 0)) { FILETIME ftCert; dwData = sizeof(FILETIME); if(NCryptDecodeObject(szOID_RSA_signingTime, &pSignerInfo->AuthAttrs.rgAttr[dwAttr].rgValue[0], dwData, (PVOID)&ftCert)) { FILETIME ftLocal; if(!FileTimeToLocalFileTime(&ftCert, &ftLocal)) { if(!FileTimeToSystemTime(&ftLocal, &pSigInfo->stSigTime)) memset(&pSigInfo->stSigTime, 0, sizeof(SYSTEMTIME)); } } } } for(DWORD dwAttr = 0; dwAttr < pSignerInfo->UnauthAttrs.cAttr; dwAttr++) { if(strcmp(pSignerInfo->UnauthAttrs.rgAttr[dwAttr].pszObjId, szOID_RSA_counterSign) == 0) { if(NCryptDecodeObject(PKCS7_SIGNER_INFO, &pSignerInfo->UnauthAttrs.rgAttr[dwAttr].rgValue[0], dwCounterSignerInfo) && (dwCounterSignerInfo != 0)) pCounterSignerInfo = (PCMSG_SIGNER_INFO)NHeapAlloc(dwCounterSignerInfo); if((pCounterSignerInfo != NULL) && !NCryptDecodeObject(PKCS7_SIGNER_INFO, &pSignerInfo->UnauthAttrs.rgAttr[dwAttr].rgValue[0], dwCounterSignerInfo, pCounterSignerInfo)) pCounterSignerInfo = (PCMSG_SIGNER_INFO)NHeapFree(pCounterSignerInfo); break; } } if(pCounterSignerInfo != NULL) { pSigInfo->bHasSigTime = WGetSignTimestamp(&pCounterSignerInfo->AuthAttrs, pSigInfo->stSigTime, szOID_RSA_signingTime); if(!pSigInfo->bHasSigTime) memset(&pSigInfo->stSigTime, 0, sizeof(SYSTEMTIME)); } } if(pSignerInfo != NULL) NHeapFree(pSignerInfo); if(pCounterSignerInfo != NULL) NHeapFree(pCounterSignerInfo); if(hStore != NULL) CertCloseStore(hStore, 0); if(hMsg != NULL) CryptMsgClose(hMsg); return TRUE; } ////////////////////////////////////////////////////////////////////////// BOOL NVerifyFileSignature(LPCTSTR lpszFileName, NSIGINFO *pSigInfo, HANDLE hHandle) { if(pSigInfo != NULL) memset(pSigInfo, 0, sizeof(NSIGINFO)); if(lpszFileName == NULL) return FALSE; if((lpszFileName[0] != 0) && (_tcsnicmp(lpszFileName, _T("\\??\\"), 4) == 0)) lpszFileName += 4; if(lpszFileName[0] == 0) return FALSE; LPWSTR lpwszFileName = NConvertT2W(lpszFileName); if(lpwszFileName == NULL) return FALSE; BOOL bOK = FALSE; __try { // be very careful... WINTRUST_FILE_INFO wtFileInfo; memset(&wtFileInfo, 0, sizeof(WINTRUST_FILE_INFO)); wtFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); wtFileInfo.pcwszFilePath = lpwszFileName; if(hHandle != INVALID_HANDLE_VALUE) wtFileInfo.hFile = hHandle; WINTRUST_DATA wtData; memset(&wtData, 0, sizeof(WINTRUST_DATA)); wtData.cbStruct = sizeof(WINTRUST_DATA); wtData.dwUIChoice = WTD_UI_NONE; wtData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; wtData.dwUnionChoice = WTD_CHOICE_FILE; wtData.pFile = &wtFileInfo; if(NVerifyFileSignatureWorker(lpwszFileName, wtData, pSigInfo)) bOK = TRUE; } __except(EXCEPTION_EXECUTE_HANDLER) { if(pSigInfo != NULL) { if(pSigInfo->lpszPublisher) pSigInfo->lpszPublisher = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszAuthority) pSigInfo->lpszAuthority = (LPTSTR)NHeapFree(pSigInfo->lpszAuthority); if(pSigInfo->lpszProgramName) pSigInfo->lpszProgramName = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszPublisherLink) pSigInfo->lpszPublisherLink = (LPTSTR)NHeapFree(pSigInfo->lpszPublisher); if(pSigInfo->lpszMoreInfoLink) pSigInfo->lpszMoreInfoLink = (LPTSTR)NHeapFree(pSigInfo->lpszMoreInfoLink); if(pSigInfo->lpszSignature) pSigInfo->lpszSignature = (LPTSTR)NHeapFree(pSigInfo->lpszSignature); if(pSigInfo->lpszSerial) pSigInfo->lpszSerial = (LPTSTR)NHeapFree(pSigInfo->lpszSerial); } bOK = FALSE; } NHeapFree(lpwszFileName); return bOK; } ////////////////////////////////////////////////////////////////////////// BOOL NCheckFileCertificates(HANDLE hFile, VOID (*pCallback)(PCCERT_CONTEXT, LPVOID), PVOID pParam) { DWORD dwCerts = 0; if(!ImageEnumerateCertificates(hFile, CERT_SECTION_TYPE_ANY, &dwCerts, NULL, 0)) return FALSE; for(DWORD dwCount = 0; dwCount < dwCerts; dwCount++) { WIN_CERTIFICATE wcHdr; memset(&wcHdr, 0, sizeof(WIN_CERTIFICATE)); wcHdr.dwLength = 0; wcHdr.wRevision = WIN_CERT_REVISION_1_0; if(!ImageGetCertificateHeader(hFile, dwCount, &wcHdr)) return FALSE; DWORD dwLen = sizeof(WIN_CERTIFICATE) + wcHdr.dwLength; WIN_CERTIFICATE *pWinCert = (WIN_CERTIFICATE *)NHeapAlloc(dwLen); if(pWinCert == NULL) return FALSE; if(!ImageGetCertificateData(hFile, dwCount, pWinCert, &dwLen)) { // problem getting certificate, return failure NHeapFree(pWinCert); return FALSE; } // extract the PKCS7 signed data CRYPT_VERIFY_MESSAGE_PARA cvmp; memset(&cvmp, 0, sizeof(CRYPT_VERIFY_MESSAGE_PARA)); cvmp.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA); cvmp.dwMsgAndCertEncodingType = SIG_ENCODING; PCCERT_CONTEXT pCertContext = NULL; if(!CryptVerifyMessageSignature(&cvmp, dwCount, pWinCert->bCertificate, pWinCert->dwLength, NULL, NULL, &pCertContext)) { NHeapFree(pWinCert); return FALSE; } // Now, pass this context on to our callback function (if any) if(pCallback != NULL) pCallback(pCertContext, pParam); if(!CertFreeCertificateContext(pCertContext)) { NHeapFree(pWinCert); return FALSE; } NHeapFree(pWinCert); } return TRUE; }