获取文件的catlog签名信息

直接嵌入在文件里的签名信息获取很简单,文件上右键属性-签名信息就可以看到

catlog签名稍微麻烦一下,

1.如果只是想验证签名,用WinVerifyTrust这样的high level api即可,示例代码如下(from sysinternal:https://forum.sysinternals.com/howto-verify-the-digital-signature-of-a-file_topic19247.html)

#include 
#include 
#include 
#include 
#include 

#pragma comment (lib, "wintrust")

BOOL CheckMSSignature111(LPCWSTR lpFileName)
{
	BOOL bRet = FALSE;
	HCATADMIN hCatAdmin = NULL;
	if (!CryptCATAdminAcquireContext(&hCatAdmin, NULL, 0))
		return FALSE;

	HANDLE hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		CryptCATAdminReleaseContext(hCatAdmin, 0);
		return FALSE;
	}

	DWORD dwCnt = 100;
	BYTE byHash[100];
	CryptCATAdminCalcHashFromFileHandle(hFile, &dwCnt, byHash, 0);
	CloseHandle(hFile);

	LPWSTR pszMemberTag = new WCHAR[dwCnt * 2 + 1];
	for (DWORD dw = 0; dw < dwCnt; ++dw)
	{
		wsprintfW(&pszMemberTag[dw * 2], L"%02X", byHash[dw]);
	}

	WINTRUST_DATA wd = { 0 };
	WINTRUST_FILE_INFO wfi = { 0 };
	WINTRUST_CATALOG_INFO wci = { 0 };
	CATALOG_INFO ci = { 0 };
	HCATINFO hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, byHash, dwCnt, 0, NULL);
	if (NULL == hCatInfo)
	{
		wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
		wfi.pcwszFilePath = lpFileName;
		wfi.hFile = NULL;
		wfi.pgKnownSubject = NULL;

		wd.cbStruct = sizeof(WINTRUST_DATA);
		wd.dwUnionChoice = WTD_CHOICE_FILE;
		wd.pFile = &wfi;
		wd.dwUIChoice = WTD_UI_NONE;
		wd.fdwRevocationChecks = WTD_REVOKE_NONE;
		wd.dwStateAction = WTD_STATEACTION_IGNORE;
		wd.dwProvFlags = WTD_SAFER_FLAG;
		wd.hWVTStateData = NULL;
		wd.pwszURLReference = NULL;
	}
	else
	{
		CryptCATCatalogInfoFromContext(hCatInfo, &ci, 0);
		wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
		wci.pcwszCatalogFilePath = ci.wszCatalogFile;
		wci.pcwszMemberFilePath = lpFileName;
		wci.pcwszMemberTag = pszMemberTag;

		wd.cbStruct = sizeof(WINTRUST_DATA);
		wd.dwUnionChoice = WTD_CHOICE_CATALOG;
		wd.pCatalog = &wci;
		wd.dwUIChoice = WTD_UI_NONE;
		wd.fdwRevocationChecks = WTD_STATEACTION_VERIFY;
		wd.dwProvFlags = 0;
		wd.hWVTStateData = NULL;
		wd.pwszURLReference = NULL;
	}

	GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
	HRESULT hr = WinVerifyTrust(NULL, &action, &wd);
	bRet = SUCCEEDED(hr);

	if (NULL != hCatInfo)
		CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);

	CryptCATAdminReleaseContext(hCatAdmin, 0);
	delete[] pszMemberTag;
	return bRet;
}

2.如果要获取详细的签名人名称等信息,从上面的代码里CryptCATAdminEnumCatalogFromHash返回的ci.wszCatalogFile;里得到catlog文件的全路径后,继续解析,示例代码如下,(from https://support.microsoft.com/en-us/kb/323809)(入参为catlog文件的全路径,如

C:\\windows\\system32\\CatRoot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\Package_4_for_KB3046017~31bf3856ad364e35~amd64~~6.1.1.1.cat"


BOOL GetSignName(LPCWSTR lpszCatFile, CString& strSignName)
{	CString strFile = lpszCatFile;
	if (strFile.IsEmpty())
	{
		return FALSE;
	}
	BOOL fResult;
	DWORD dwEncoding, dwContentType, dwFormatType;
	HCERTSTORE hStore = NULL;
	HCRYPTMSG hMsg = NULL;

	//查询签名信息
	fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
		(LPVOID)strFile.GetBuffer(),
		CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
		CERT_QUERY_FORMAT_FLAG_BINARY,
		0,
		&dwEncoding,
		&dwContentType,
		&dwFormatType,
		&hStore,
		&hMsg,
		NULL);
	if (!fResult)
	{
		WRITE_LOG(_T("CryptQueryObject failed with %x\n"), GetLastError());
		return FALSE;
	}
	// Get signer information size.
	DWORD dwSignerInfo;
	fResult = CryptMsgGetParam(hMsg,
		CMSG_SIGNER_INFO_PARAM,
		0,
		NULL,
		&dwSignerInfo);
	if (!fResult)
	{
		WRITE_LOG(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
		return FALSE;
	}
	// Allocate memory for signer information.
	PCMSG_SIGNER_INFO pSignerInfo = NULL;
	pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
	if (!pSignerInfo)
	{
		WRITE_LOG(_T("Unable to allocate memory for Signer Info.\n"));
		return FALSE;
	}
	// Get Signer Information.
	fResult = CryptMsgGetParam(hMsg,
		CMSG_SIGNER_INFO_PARAM,
		0,
		(PVOID)pSignerInfo,
		&dwSignerInfo);
	if (!fResult)
	{
		WRITE_LOG(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
		return FALSE;
	}

	// Search for the signer certificate in the temporary
	// certificate store.
	CERT_INFO CertInfo;
	CertInfo.Issuer = pSignerInfo->Issuer;
	CertInfo.SerialNumber = pSignerInfo->SerialNumber;
	PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore,
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		0,
		CERT_FIND_SUBJECT_CERT,
		(PVOID)&CertInfo,
		NULL);
	if (!pCertContext)
	{
		WRITE_LOG(_T("CertFindCertificateInStore failed with %x\n"),
			GetLastError());
		return FALSE;
	}
	LPTSTR szName = NULL;
	DWORD dwData;
	if (!(dwData = CertGetNameString(pCertContext,
		CERT_NAME_SIMPLE_DISPLAY_TYPE,
		0,
		NULL,
		NULL,
		0)))
	{
		WRITE_LOG(_T("CertGetNameString failed.\n"));
		return FALSE;
	}
	// Allocate memory for subject name.
	szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
	if (!szName)
	{
		WRITE_LOG(_T("Unable to allocate memory for subject name.\n"));
		return FALSE;
	}
	// Get subject name.
	if (!(CertGetNameString(pCertContext,
		CERT_NAME_SIMPLE_DISPLAY_TYPE,
		0,
		NULL,
		szName,
		dwData)))
	{
		WRITE_LOG(_T("CertGetNameString failed.\n"));
		return FALSE;
	}
	strSignName = szName;
	return TRUE;
}





你可能感兴趣的:(Windows开发)