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

本文介绍了如何在Windows环境下获取可执行文件(Exe)的数字签名以及进行签名验证。主要涉及WinVerifyTrust函数用于验证签名有效性和CryptQueryObject函数用于获取签名证书信息。还提及了一种内核级别的API实现,提供了相关的GitHub资源链接。
摘要由CSDN通过智能技术生成

 

 

主要函数说明: 

验证文件数字签名是否有效可以使用函数 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[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tiny丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值