可执行程序Exe数字签名获取 以及认证

主要函数说明: 

验证文件数字签名是否有效可以使用函数 WinVerifyTrust
取得文件数字签名证书信息需要使用函数 CryptQueryObject。

一、数字签名获取

// FileSign.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.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);
int _tmain(int argc, TCHAR *argv[])
{
	WCHAR szFileName[MAX_PATH];
	HCERTSTORE hStore = NULL;
	HCRYPTMSG hMsg = NULL;
	PCCERT_CONTEXT pCertContext = NULL;
	BOOL fResult;
	DWORD dwEncoding, dwContentType, dwFormatType;
	PCMSG_SIGNER_INFO pSignerInfo = NULL;
	PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
	DWORD dwSignerInfo;
	CERT_INFO CertInfo;
	SPROG_PUBLISHERINFO ProgPubInfo;
	SYSTEMTIME st;
	ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
	__try
	{
		if (argc != 2)
		{
			_tprintf(_T("Usage: SignedFileInfo <filename>\n"));
			//return 0;
		}
#ifdef UNICODE
		lstrcpynW(szFileName, argv[1], MAX_PATH);
#else
		if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1)
		{
			printf("Unable to convert to unicode.\n");
			__leave;
		}
#endif
		// 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"));
		// 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(_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
	{
		// 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 (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
		if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
		if (hStore != NULL) CertCloseStore(hStore, 0);
		if (hMsg != NULL) CryptMsgClose(hMsg);
	}
	return 0;
}
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"));
		// 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;
}

二、数字签名认证

转载: https://blog.csdn.net/a33445621/article/details/54969846

// FileSign.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#define _WIN32_WINNT 0x0500
#define WINVER       0x0500

#include <windows.h>
#include <Softpub.h>
#include <Wincrypt.h>
#include <tchar.h>
#include <stdlib.h>

#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "Wintrust.lib")

LPTSTR GetCertificateDescription(PCCERT_CONTEXT pCertCtx)
{
	DWORD dwStrType;
	DWORD dwCount;
	LPTSTR szSubjectRDN = NULL;

	dwStrType = CERT_X500_NAME_STR;
	dwCount = CertGetNameString(pCertCtx,
		CERT_NAME_RDN_TYPE,
		0,
		&dwStrType,
		NULL,
		0);
	if (dwCount)
	{
		szSubjectRDN = (LPTSTR)LocalAlloc(0, dwCount * sizeof(TCHAR));
		CertGetNameString(pCertCtx,
			CERT_NAME_RDN_TYPE,
			0,
			&dwStrType,
			szSubjectRDN,
			dwCount);
	}

	return szSubjectRDN;
}


int _tmain(int argc, _TCHAR* argv[])
{
	GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
	WINTRUST_FILE_INFO sWintrustFileInfo;
	WINTRUST_DATA      sWintrustData;
	HRESULT            hr;

	if (argc != 2)
	{
		_tprintf(_T("Usage: VerifyExeSignature file_name\n"));
		return -1;
	}

	memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO));
	memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA));

	sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
	sWintrustFileInfo.pcwszFilePath = argv[1];
	sWintrustFileInfo.hFile = NULL;

	sWintrustData.cbStruct = sizeof(WINTRUST_DATA);
	sWintrustData.dwUIChoice = WTD_UI_NONE;
	sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
	sWintrustData.dwUnionChoice = WTD_CHOICE_FILE;
	sWintrustData.pFile = &sWintrustFileInfo;
	sWintrustData.dwStateAction = WTD_STATEACTION_VERIFY;

	hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);

	if (TRUST_E_NOSIGNATURE == hr)
	{
		_tprintf(_T("No signature found on the file.\n"));
	}
	else if (TRUST_E_BAD_DIGEST == hr)
	{
		_tprintf(_T("The signature of the file is invalid\n"));
	}
	else if (TRUST_E_PROVIDER_UNKNOWN == hr)
	{
		_tprintf(_T("No trust provider on this machine can verify this type of files.\n"));
	}
	else if (S_OK != hr)
	{
		_tprintf(_T("WinVerifyTrust failed with error 0x%.8X\n"), hr);
	}
	else
	{
		_tprintf(_T("File signature is OK.\n"));

		// retreive the signer certificate and display its information
		CRYPT_PROVIDER_DATA const *psProvData = NULL;
		CRYPT_PROVIDER_SGNR       *psProvSigner = NULL;
		CRYPT_PROVIDER_CERT       *psProvCert = NULL;
		FILETIME                   localFt;
		SYSTEMTIME                 sysTime;

		psProvData = WTHelperProvDataFromStateData(sWintrustData.hWVTStateData);
		if (psProvData)
		{
			psProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0, FALSE, 0);
			if (psProvSigner)
			{
				FileTimeToLocalFileTime(&psProvSigner->sftVerifyAsOf, &localFt);
				FileTimeToSystemTime(&localFt, &sysTime);

				_tprintf(_T("Signature Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);

				psProvCert = WTHelperGetProvCertFromChain(psProvSigner, 0);
				if (psProvCert)
				{
					LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
					if (szCertDesc)
					{
						_tprintf(_T("File Signer = %s\n"), szCertDesc);
						LocalFree(szCertDesc);
					}
				}

				if (psProvSigner->csCounterSigners)
				{
					_tprintf(_T("\n"));
					// Timestamp information
					FileTimeToLocalFileTime(&psProvSigner->pasCounterSigners[0].sftVerifyAsOf, &localFt);
					FileTimeToSystemTime(&localFt, &sysTime);

					_tprintf(_T("Timestamp Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
					psProvCert = WTHelperGetProvCertFromChain(&psProvSigner->pasCounterSigners[0], 0);
					if (psProvCert)
					{
						LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
						if (szCertDesc)
						{
							_tprintf(_T("Timestamp Signer = %s\n"), szCertDesc);
							LocalFree(szCertDesc);
						}
					}
				}
			}
		}
	}

	sWintrustData.dwUIChoice = WTD_UI_NONE;
	sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
	WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);

	return 0;
}

方法二、


#include <windows.h>
#include <Softpub.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <mscat.h>
#include <wchar.h>
 
#pragma comment(lib, "wintrust")
 
BOOLEAN IsFileDigitallySigned(PWCHAR FilePath)
{
	//Author: AD, 2009
	PVOID Context;
	HANDLE FileHandle;
	DWORD HashSize = 0;
	PBYTE Buffer;
	PVOID CatalogContext;
	CATALOG_INFO InfoStruct;
	WINTRUST_DATA WintrustStructure;
	WINTRUST_CATALOG_INFO WintrustCatalogStructure;
	WINTRUST_FILE_INFO WintrustFileStructure;
	PWCHAR MemberTag;
	BOOLEAN ReturnFlag = FALSE;
	ULONG ReturnVal;
	GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
 
	//Zero our structures.
	memset(&InfoStruct, 0, sizeof(CATALOG_INFO));
	InfoStruct.cbStruct = sizeof(CATALOG_INFO);
	memset(&WintrustCatalogStructure, 0, sizeof(WINTRUST_CATALOG_INFO));
	WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
	memset(&WintrustFileStructure, 0, sizeof(WINTRUST_FILE_INFO));
	WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
 
	//Get a context for signature verification.
	if (!CryptCATAdminAcquireContext(&Context, NULL, 0))
	{
		return FALSE;
	}
 
	//Open file.
	FileHandle = CreateFileW(FilePath, GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL);
	if (INVALID_HANDLE_VALUE == FileHandle)
	{
		CryptCATAdminReleaseContext(Context, 0);
		return FALSE;
	}
 
	//Get the size we need for our hash.
	CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, NULL, 0);
	if (HashSize == 0)
	{
		//0-sized has means error!
		CryptCATAdminReleaseContext(Context, 0);
		CloseHandle(FileHandle);
		return FALSE;
	}
 
	//Allocate memory.
	Buffer = (PBYTE)calloc(HashSize, 1);
 
	//Actually calculate the hash
	if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, Buffer, 0))
	{
		CryptCATAdminReleaseContext(Context, 0);
		free(Buffer);
		CloseHandle(FileHandle);
		return FALSE;
	}
 
	//Convert the hash to a string.
	MemberTag = (PWCHAR)calloc((HashSize * 2) + 1, sizeof(WCHAR));
	for (unsigned int i = 0; i < HashSize; i++)
	{
		swprintf(&MemberTag[i * 2],100, L"%02X", Buffer[i]);
	}
 
	//Get catalog for our context.
	CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, Buffer, HashSize, 0, NULL);
	if (CatalogContext)
	{
		//If we couldn't get information
		if (!CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0))
		{
			//Release the context and set the context to null so it gets picked up below.
			CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
			CatalogContext = NULL;
		}
	}
 
	//If we have a valid context, we got our info.  
	//Otherwise, we attempt to verify the internal signature.
	if (!CatalogContext)
	{
		WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
		WintrustFileStructure.pcwszFilePath = FilePath;
		WintrustFileStructure.hFile = NULL;
		WintrustFileStructure.pgKnownSubject = NULL;
 
		WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
		WintrustStructure.dwUnionChoice = WTD_CHOICE_FILE;
		WintrustStructure.pFile = &WintrustFileStructure;
		WintrustStructure.dwUIChoice = WTD_UI_NONE;
		WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
		WintrustStructure.dwStateAction = WTD_STATEACTION_IGNORE;
		WintrustStructure.dwProvFlags = WTD_SAFER_FLAG;
		WintrustStructure.hWVTStateData = NULL;
		WintrustStructure.pwszURLReference = NULL;
	}
	else
	{
		//If we get here, we have catalog info!  Verify it.
		WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
		WintrustStructure.pPolicyCallbackData = 0;
		WintrustStructure.pSIPClientData = 0;
		WintrustStructure.dwUIChoice = WTD_UI_NONE;
		WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
		WintrustStructure.dwUnionChoice = WTD_CHOICE_CATALOG;
		WintrustStructure.pCatalog = &WintrustCatalogStructure;
		WintrustStructure.dwStateAction = WTD_STATEACTION_VERIFY;
		WintrustStructure.hWVTStateData = NULL;
		WintrustStructure.pwszURLReference = NULL;
		WintrustStructure.dwProvFlags = 0;
		WintrustStructure.dwUIContext = WTD_UICONTEXT_EXECUTE;
 
		//Fill in catalog info structure.
		WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
		WintrustCatalogStructure.dwCatalogVersion = 0;
		WintrustCatalogStructure.pcwszCatalogFilePath = InfoStruct.wszCatalogFile;
		WintrustCatalogStructure.pcwszMemberTag = MemberTag;
		WintrustCatalogStructure.pcwszMemberFilePath = FilePath;
		WintrustCatalogStructure.hMemberFile = NULL;
	}
 
	//Call our verification function.
	ReturnVal = WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
 
	//Check return.
	ReturnFlag = SUCCEEDED(ReturnVal);
 
	//Free context.
	if (CatalogContext)
		CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
 
	//If we successfully verified, we need to free.
	if (ReturnFlag)
	{
		WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
		WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
	}
 
	//Free memory.
	free(MemberTag);
	free(Buffer);
	CloseHandle(FileHandle);
	CryptCATAdminReleaseContext(Context, 0);
 
	return ReturnFlag;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
	IsFileDigitallySigned(L"C:\\Windows\\System32\\svchost.exe");
}

方法三、 

三、一种内核级的api

github地址:  https://github.com/mstefanowich/IsFileSigned

C Win32 API code segment. Utilizes kernel level API calls to achieve similiar functionality to that of WinVerifyTrust.

Prerequisites

User must import NtReadFile, NtWaitForSingleObject, and Wdm.h.

An example of importing NtReadFile:

typedef NTSTATUS (NTAPI *NTREADFILE)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
HMODULE hMod = LoadLibrary(L"Ntdll.dll");
NTREADFILE NtReadFile = GetProcAddress(hMod, "NtReadFile");

 代码:

/*
Prior to function call + function call

WCHAR *szPath = "C:\\Users\\...\\Desktop\\TestFile.exe";

DWORD dwCount = ERROR_SUCCESS;
HANDLE hHandle;

NTSTATUS Status;
OBJECT_ATTRIBUTES Attributes;
IO_STATUS_BLOCK IoBlock;
LARGE_INTEGER Integer;
UNICODE_STRING uString;
    
VxZeroMemory(&Attributes, sizeof(OBJECT_ATTRIBUTES));
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
VxZeroMemory(&Integer, sizeof(LARGE_INTEGER));
Integer.QuadPart = 2048;
VxZeroMemory(&uString, sizeof(UNICODE_STRING));
    
if(szPath[0] != L'\\')
    RtlDosPathNameToNtPathName_U(szPath, &uString, NULL, NULL);
else
    RtlInitUnicodeString(&uString, szPath);
    	
InitializeObjectAttributes(&Attributes, &uString, OBJ_CASE_INSENSITIVE, NULL, NULL);

if(NtCreateFile(&hHandle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &Attributes, &IoBlock, &Integer, FILE_ATTRIBUTE_NORMAL, 
		FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 
		0, 0) != 0x00000000){     return;     }


if((!VxIsTargetSigned(hHandle, CERT_SECTION_TYPE_ANY, &dwCount, NULL, 0)) && (dwCount == ERROR_SUCCESS))
    	return;

*/
BOOL VxIsTargetSigned(HANDLE FileHandle, DWORD TypeFilter, PDWORD CertificateCount, PDWORD Indices, DWORD IndexCount) //NOT
{
	DWORD dwSize, dwCount, dwAddress, dwIndex, dwOffset;
	WIN_CERTIFICATE Hdr;
	BOOL bFlag;
	IO_STATUS_BLOCK IoBlock;
	NTSTATUS Status;
	CONST SIZE_T CertHdrSize = sizeof(Hdr) - sizeof(Hdr.bCertificate);

	if(!VxGetSecurityDirectoryOffsetEx(FileHandle, &dwAddress, &dwSize))
		goto FAILURE;
		
	dwOffset 			= ERROR_SUCCESS;
	dwIndex 			= ERROR_SUCCESS;
	*CertificateCount 	= ERROR_SUCCESS;
	
	VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
	
	while(dwOffset < dwSize)
	{
		if(VxSetFilePointer(FileHandle, dwAddress + dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
			goto FAILURE;
			
		Status = NtReadFile(FileHandle, NULL, NULL, NULL, &IoBlock, &Hdr, CertHdrSize, NULL, NULL);
		if(Status == 0x00000103)
		{
			Status = NtWaitForSingleObject(FileHandle, FALSE, NULL);
			if(Status == ERROR_SUCCESS)
				Status = IoBlock.Status;
		}
		
		if(Status == ERROR_SUCCESS)
			dwCount = IoBlock.Information;
		else
			goto FAILURE;
			
		if((dwCount != CertHdrSize) || (Hdr.dwLength < CertHdrSize) || (Hdr.dwLength > (dwSize - dwOffset)))
			goto FAILURE;
			
		if((TypeFilter == CERT_SECTION_TYPE_ANY) || (TypeFilter == Hdr.wCertificateType))
		{
			(*CertificateCount)++;
			if(Indices && *CertificateCount <= IndexCount)
				*Indices++ = dwIndex;
		}
		
		dwOffset += Hdr.dwLength;
		
		if(Hdr.dwLength % 0x08)
			dwOffset += 8 - (Hdr.dwLength % 0x08);
			
		dwIndex++;
	}

	return TRUE;
	
FAILURE:
	
	return FALSE;
}

BOOL VxGetSecurityDirectoryOffsetEx(HANDLE hHandle, PDWORD dwOffset, PDWORD dwSize) //pi
{
	IMAGE_NT_HEADERS32 Hdr32;
	IMAGE_NT_HEADERS64 Hdr64;
	PIMAGE_DATA_DIRECTORY Data;
	INT dwReturn = VxGetCertificateNtHeaders(hHandle, NULL, &Hdr32, &Hdr64);
	
	switch(dwReturn)
	{
		case -1:
			return FALSE;
		case 0:
			Data = &Hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
			break;
		case 1:
			Data = &Hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
	}
	
	*dwSize = Data->Size;
	*dwOffset = Data->VirtualAddress;
	
	return TRUE;	
}

INT VxGetCertificateNtHeaders(HANDLE hHandle, PDWORD Offset, PIMAGE_NT_HEADERS32 Nt32, PIMAGE_NT_HEADERS64 Nt64) //pe
{
	IMAGE_DOS_HEADER Dos;
	DWORD dwCount = ERROR_SUCCESS;
	IO_STATUS_BLOCK IoBlock;
	VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
	NTSTATUS Status;
		
	if(VxSetFilePointer(hHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
		goto FAILURE;
		
	Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, &Dos, sizeof(Dos), NULL, NULL);
	if(Status == 0x00000103)
	{
		Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
		if(Status == ERROR_SUCCESS)
			Status = IoBlock.Status;
	}
	
	if(Status == ERROR_SUCCESS)
		dwCount = IoBlock.Information;
	else
		goto FAILURE;
		
	if((dwCount != sizeof(Dos)) || (Dos.e_magic != IMAGE_DOS_SIGNATURE))
		goto FAILURE;
		
	if(VxSetFilePointer(hHandle, Dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
		goto FAILURE;

	dwCount = ERROR_SUCCESS;
	if(Dos.e_magic != IMAGE_DOS_SIGNATURE)
		*Offset = Dos.e_lfanew;
		
	Status = ERROR_SUCCESS;
	VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
	
	Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, Nt32, sizeof(IMAGE_NT_HEADERS32), NULL, NULL);
	if(Status == 0x00000103)
	{
		Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
		if(Status == ERROR_SUCCESS)
			Status = IoBlock.Status;
	}
	
	if(Status == ERROR_SUCCESS)
		dwCount = IoBlock.Information;
	else
		goto FAILURE;
	
	if((dwCount != sizeof(IMAGE_NT_HEADERS32)) || (Nt32->Signature != IMAGE_NT_SIGNATURE))
		goto FAILURE;

	switch(Nt32->OptionalHeader.Magic)
	{
		case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
			return 0;
		case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
		{
			if(VxSetFilePointer(hHandle, Dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
				goto FAILURE;
				
			Status = ERROR_SUCCESS;
			VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
			
			Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, Nt64, sizeof(IMAGE_NT_HEADERS64), NULL, NULL);
			if(Status == 0x00000103)
			{
				Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
				if(Status == ERROR_SUCCESS)
					Status = IoBlock.Status;
			}
	
			if(Status == ERROR_SUCCESS)
				dwCount = IoBlock.Information;
			else
				goto FAILURE;
				
			if((dwCount != sizeof(IMAGE_NT_HEADERS64)) || (Nt64->Signature != IMAGE_NT_SIGNATURE))
				goto FAILURE;
			else
				return 1;
		}
		default:
			goto FAILURE;
	}
		
FAILURE:
	
	return -1;
}

猜你喜欢

转载自blog.csdn.net/vevenlcf/article/details/81204171