Read digital signatures from multi-signed files

Here is code example of how to use WinTrust to retrieve digital signatures and certificates from a file. It supports multi-signed and catalog-signed files.

What it does:

  • Use WinTrust API to enumerate all embedded digital signatures (including nested ones and timestamps) from the file and display the properties of each signature;
  • For each digital signature, establish the trust chain of the signing certiifcate, display propertie of each certificate in the trust chain;
  • Check if the file is catalog signed, and if yes, do the same to the catalog file: display properties of catalog file’s signatures and their certificates;

What it doesn’t do:

  • Verify the signature
  • Verify the certificate
  • Verify the file against the signature

signature.cpp

#include "signature.h"

#include <vector>
#include <memory>
#include <map>
#include <sstream>
#include <functional>
#include <algorithm>
#include <ctime>
#include <iomanip>
#include <locale>
#include <codecvt>

#include <windows.h>
#include <wincrypt.h>
#include <softpub.h>
#include <mscat.h>
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "wintrust.lib")

template<typename T, typename T::pointer invalid_value = nullptr> struct pointer_wrapper {
	pointer_wrapper(T& pointer) : _pointer(pointer), _raw_pointer(invalid_value) {}
	~pointer_wrapper() {
		if (_raw_pointer != invalid_value)
			_pointer.reset(_raw_pointer);
	}
	pointer_wrapper(pointer_wrapper&& _other) : _pointer(_other._pointer) {
		std::swap(_raw_pointer, _other._raw_pointer);
	}
	operator typename T::pointer*() && { return &_raw_pointer; }
	operator typename T::pointer&() && { return _raw_pointer; }

private:
	T& _pointer;
	typename T::pointer _raw_pointer;
	pointer_wrapper(pointer_wrapper&) = delete;
	pointer_wrapper operator = (const pointer_wrapper&) = delete;
	pointer_wrapper operator = (pointer_wrapper&&) = delete;
	static void* operator new (size_t) = delete;
	static void* operator new (size_t, void*) = delete;
	static void* operator new[](size_t) = delete;
	static void* operator new[](size_t, void*) = delete;
};

template<typename T, typename T::pointer invalid_value = nullptr> pointer_wrapper<T, invalid_value> get_pointer_wrapper(T& _pointer) {
	return pointer_wrapper<T, invalid_value>(_pointer);
}

template <typename T, BOOL(__stdcall *f)(T), T null_t = 0> struct deleter_t {
	using pointer = T;
	void operator() (pointer value) {
		if (value != null_t)
			f(value);
	}
};

using HCRYPTMSG_t = std::unique_ptr<HCRYPTMSG, deleter_t<HCRYPTMSG, CryptMsgClose>>;
using CERT_CONTEXT_t = std::unique_ptr<CERT_CONTEXT, deleter_t<PCCERT_CONTEXT, CertFreeCertificateContext>>;
using HANDLE_t = std::unique_ptr<HANDLE, deleter_t<HANDLE, CloseHandle, INVALID_HANDLE_VALUE>>;

BOOL __stdcall CertCloseStore0(HCERTSTORE pcrypt_cert_store) {
	return CertCloseStore(pcrypt_cert_store, 0);
}
using HCERTSTORE_t = std::unique_ptr<HCERTSTORE, deleter_t<HCERTSTORE, CertCloseStore0>>;

BOOL __stdcall CertFreeCertificateChain0(PCCERT_CHAIN_CONTEXT pcrypt_cert_chain) {
	CertFreeCertificateChain(pcrypt_cert_chain);
	return true;
}
using CERT_CHAIN_CONTEXT_t = std::unique_ptr<const CERT_CHAIN_CONTEXT, deleter_t<PCCERT_CHAIN_CONTEXT, CertFreeCertificateChain0>>;

BOOL __stdcall CryptCATAdminReleaseContext0(HCATADMIN hcatadmin) {
	return CryptCATAdminReleaseContext(hcatadmin, 0);
}
using HCATADMIN_t = std::unique_ptr<HCATADMIN, deleter_t<HCATADMIN, CryptCATAdminReleaseContext0>>;

struct deleter_HCATINFO {
	using pointer = HCATINFO;
	deleter_HCATINFO(HCATADMIN catadmin) : _catadmin(catadmin) {}
	void operator() (pointer hcatinfo) {
		if (hcatinfo != 0)
			CryptCATAdminReleaseCatalogContext(_catadmin, hcatinfo, 0);
	}
	HCATADMIN _catadmin;
};
using HCATINFO_t = std::unique_ptr<HCATADMIN, deleter_HCATINFO>;

struct crypt_allocator : std::allocator<BYTE> {
	BYTE* allocate(std::size_t n) {
		return reinterpret_cast<BYTE*>(::CryptMemAlloc(static_cast<ULONG>(n)));
	}
	void deallocate(BYTE* p, std::size_t n) {
		if (p)
			::CryptMemFree(p);
	}
};

std::unique_ptr<tm> filetime_to_tm(const FILETIME* pft) {
	FILETIME ft_local = {};
	FileTimeToLocalFileTime(pft, &ft_local);
	SYSTEMTIME st = {};
	FileTimeToSystemTime(&ft_local, &st);
	std::unique_ptr<tm> t(std::make_unique<tm>());
	t->tm_year = st.wYear - 1900;
	t->tm_mon = st.wMonth - 1;
	t->tm_mday = st.wDay;
	t->tm_hour = st.wHour;
	t->tm_min = st.wMinute;
	t->tm_sec = st.wSecond;
	t->tm_isdst = -1;
	return std::move(t);
}

std::wstring string_from_filetime(const FILETIME* pft) {
	wchar_t str[128] = {};
	wcsftime(str, _countof(str), L"%c", filetime_to_tm(pft).get());
	return str;
}

std::wstring get_cert_field(PCCERT_CONTEXT pcrypt_cert, DWORD type, DWORD flags) {
	DWORD size = CertGetNameString(pcrypt_cert, type, flags, 0, 0, 0);
	if (size > 0) {
		std::vector<WCHAR, crypt_allocator> value(size + 1);
		size = CertGetNameString(pcrypt_cert, type, flags, 0, value.data(), static_cast<DWORD>(value.size()));
		return std::wstring(value.data());
	}
	return L"";
}

std::wstring get_cert_name(CERT_NAME_BLOB* pcrypt_blob, DWORD type) {
	DWORD size = CertNameToStr(X509_ASN_ENCODING, pcrypt_blob, type, 0, 0);
	if (size > 0) {
		std::vector<WCHAR, crypt_allocator> value(size + 1);
		size = CertNameToStr(X509_ASN_ENCODING, pcrypt_blob, type, value.data(), static_cast<DWORD>(value.size()));
		return std::wstring(value.data());
	}
	return L"";
}

std::wstring get_oid_info(DWORD type, void* p, DWORD groupid) {
	const PCCRYPT_OID_INFO pcrypt_oid_info = CryptFindOIDInfo(type, p, groupid);
	if (pcrypt_oid_info && pcrypt_oid_info->pwszName)
		return pcrypt_oid_info->pwszName;
	return L"";
}

std::wstring format_crypt_blob(const CRYPT_INTEGER_BLOB* pcrypt_blob, bool reverse = false, DWORD limit = 36) {
	std::wstringstream ss;
	ss << std::hex << std::setfill(L'0');
	DWORD size = min(limit - 3, pcrypt_blob->cbData);
	if (reverse) {
		for (DWORD n = size; n > 0; --n) {
			ss << std::setw(2) << pcrypt_blob->pbData[n - 1];
		}
	}
	else {
		for (DWORD n = 0; n < size; ++n) {
			ss << std::setw(2) << pcrypt_blob->pbData[n];
		}
	}
	if (size < pcrypt_blob->cbData)
		ss << L"...";
	return ss.str();
}

DWORD get_cert_property(const PCCERT_CONTEXT pcrypt_cert, DWORD property_id, std::vector<BYTE, crypt_allocator>& _buffer) {
	DWORD size = 0;
	if (!CertGetCertificateContextProperty(pcrypt_cert, property_id, 0, &size))
		return GetLastError();
	std::vector<BYTE, crypt_allocator> buffer(size);
	if (!CertGetCertificateContextProperty(pcrypt_cert, property_id, buffer.data(), &size))
		return GetLastError();
	std::swap(buffer, _buffer);
	return 0;
}

DWORD crypt_decode(LPCSTR decode_type, const std::vector<BYTE, crypt_allocator>& encoded, std::vector<BYTE, crypt_allocator>& decoded) {
	DWORD size = 0;
	if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, decode_type, encoded.data(), static_cast<DWORD>(encoded.size()), 0, 0, &size))
		return GetLastError();
	std::vector<BYTE, crypt_allocator> _decoded(size);
	if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, decode_type, encoded.data(), static_cast<DWORD>(encoded.size()), 0, _decoded.data(), &size))
		return GetLastError();
	std::swap(_decoded, decoded);
	return 0;
}

void decode_usage(CTL_USAGE* pcert_usage, pairs& usages) {
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> utf8_to_utf16;
	for (DWORD n = 0; n < pcert_usage->cUsageIdentifier; ++n) {
		const CCRYPT_OID_INFO* pcrypt_oidinfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pcert_usage->rgpszUsageIdentifier[n], 0);
		std::wstring name, usage = utf8_to_utf16.from_bytes(pcert_usage->rgpszUsageIdentifier[n]);
		name = (pcrypt_oidinfo && pcrypt_oidinfo->pwszName) ? pcrypt_oidinfo->pwszName : usage;
		usages.push_back({ name, usage });
	}
}

DWORD get_cert_from_CERT_CONTEXT(const PCCERT_CONTEXT pcrypt_cert, CERT* pcert) {
	pcert->version = pcrypt_cert->pCertInfo->dwVersion;
	pcert->serial_number = format_crypt_blob(&pcrypt_cert->pCertInfo->SerialNumber, true);
	pcert->issuer = get_cert_field(pcrypt_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG);
	pcert->name = get_cert_field(pcrypt_cert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0);
	pcert->valid_from = string_from_filetime(&pcrypt_cert->pCertInfo->NotBefore);
	pcert->valid_to = string_from_filetime(&pcrypt_cert->pCertInfo->NotAfter);
	pcert->subject = get_cert_name(&pcrypt_cert->pCertInfo->Subject, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG);
	pcert->hash_algorithm = get_oid_info(CRYPT_OID_INFO_OID_KEY, pcrypt_cert->pCertInfo->SignatureAlgorithm.pszObjId, 0);
	pcert->algorithm = get_oid_info(CRYPT_OID_INFO_OID_KEY, pcrypt_cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, 0);

	std::vector<BYTE, crypt_allocator> buffer;
	if (0 == get_cert_property(pcrypt_cert, CERT_HASH_PROP_ID, buffer)) {
		CRYPT_INTEGER_BLOB blob = { static_cast<DWORD>(buffer.size()), buffer.data() };
		pcert->thumbprint = format_crypt_blob(&blob);
	}
	if (0 == get_cert_property(pcrypt_cert, CERT_SIGNATURE_HASH_PROP_ID, buffer)) {
		CRYPT_INTEGER_BLOB blob = { static_cast<DWORD>(buffer.size()), buffer.data() };
		pcert->signature_hash = format_crypt_blob(&blob);
	}
	if (0 == get_cert_property(pcrypt_cert, CERT_SUBJECT_PUB_KEY_BIT_LENGTH_PROP_ID, buffer)) {
		pcert->publickey_length = *reinterpret_cast<DWORD*>(buffer.data());
	}
	if (0 == get_cert_property(pcrypt_cert, CERT_CTL_USAGE_PROP_ID, buffer)) {
		std::vector<BYTE, crypt_allocator> cert_usage;
		if (0 == crypt_decode(X509_ENHANCED_KEY_USAGE, buffer, cert_usage)) {
			decode_usage(reinterpret_cast<CTL_USAGE*>(cert_usage.data()), pcert->usages);
		}
	}

	DWORD size = 0;
	if (CertGetEnhancedKeyUsage(pcrypt_cert, 0, 0, &size)) {
		buffer.resize(size);
		if (CertGetEnhancedKeyUsage(pcrypt_cert, 0, reinterpret_cast<PCERT_ENHKEY_USAGE>(buffer.data()), &size)) {
			decode_usage(reinterpret_cast<CERT_ENHKEY_USAGE*>(buffer.data()), pcert->enhanced_key_usages);
		}
	}

	pcert->publickey = format_crypt_blob(reinterpret_cast<CRYPT_INTEGER_BLOB*>(&pcrypt_cert->pCertInfo->SubjectPublicKeyInfo.PublicKey));
	
	return 0;
}

void oid_publisher(CRYPT_ATTRIBUTE& crypt_attr, ATTR& attr, SIGNATURE* psignature) {
	DWORD size = 0;
	if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, SPC_SP_OPUS_INFO_OBJID,
		crypt_attr.rgValue[0].pbData, crypt_attr.rgValue[0].cbData, 0, 0, &size))
		return;
	std::vector<BYTE, crypt_allocator> opusinfo(size);
	if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, SPC_SP_OPUS_INFO_OBJID,
		crypt_attr.rgValue[0].pbData, crypt_attr.rgValue[0].cbData, 0, opusinfo.data(), &size))
		return;

	const PSPC_SP_OPUS_INFO popus = reinterpret_cast<PSPC_SP_OPUS_INFO>(opusinfo.data());
	if (popus->pwszProgramName) {
		attr.value += L"program:";
		attr.value += popus->pwszProgramName;
		attr.value += L"; ";
	}
	if (popus->pPublisherInfo) {
		switch (popus->pPublisherInfo->dwLinkChoice) {
		case SPC_URL_LINK_CHOICE:
			attr.value += L"publisher:";
			attr.value += popus->pPublisherInfo->pwszUrl;
			attr.value += L"; ";
			break;
		case SPC_FILE_LINK_CHOICE:
			attr.value += L"publisher:";
			attr.value += popus->pPublisherInfo->pwszFile;
			attr.value += L"; ";
			break;
		}
	}
	if (popus->pMoreInfo) {
		switch (popus->pMoreInfo->dwLinkChoice) {
		case SPC_URL_LINK_CHOICE:
			attr.value += L"moreinfo:";
			attr.value += popus->pMoreInfo->pwszUrl;
			attr.value += L"; ";
			break;
		case SPC_FILE_LINK_CHOICE:
			attr.value += L"moreinfo:";
			attr.value += popus->pMoreInfo->pwszFile;
			attr.value += L"; ";
			break;
		}
	}
}

void oid_signingtime(CRYPT_ATTRIBUTE& crypt_attr, ATTR& attr, SIGNATURE* psignature) {
	FILETIME ft = {};
	DWORD size = sizeof(ft);
	if (CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_RSA_signingTime,
		crypt_attr.rgValue[0].pbData, crypt_attr.rgValue[0].cbData, 0, &ft, &size)) {
		attr.value += L"timestamp:";
		attr.value += string_from_filetime(&ft);
		attr.value += L"; ";
	}
}

void oid_general(CRYPT_ATTRIBUTE& crypt_attr, ATTR& attr, SIGNATURE* psignature) {
	attr.value = format_crypt_blob(&crypt_attr.rgValue[0]);
}

std::map<std::string, void(*)(CRYPT_ATTRIBUTE&, ATTR&, SIGNATURE*)> oidfuncs = {
	{ SPC_SP_OPUS_INFO_OBJID, oid_publisher },
	{ szOID_RSA_signingTime, oid_signingtime }
};

void process_attrs(CRYPT_ATTRIBUTES& crypt_attrs, attrs_t& attrs, SIGNATURE* psignature) {
	for (DWORD index = 0; index < crypt_attrs.cAttr; ++index) {
		std::unique_ptr<ATTR> attr(std::make_unique<ATTR>());
		std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
		attr->oid = conv.from_bytes(crypt_attrs.rgAttr[index].pszObjId);
		attr->size = crypt_attrs.rgAttr[index].rgValue->cbData;

		PCCRYPT_OID_INFO pcrypt_oidinfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, crypt_attrs.rgAttr[index].pszObjId, 0);
		if (pcrypt_oidinfo && pcrypt_oidinfo->pwszName)
			attr->name = pcrypt_oidinfo->pwszName;
		else
			attr->name = attr->oid;

		auto& it = oidfuncs.find(crypt_attrs.rgAttr[index].pszObjId);
		if (it != oidfuncs.end())
			it->second(crypt_attrs.rgAttr[index], *attr.get(), psignature);
		else
			oid_general(crypt_attrs.rgAttr[index], *attr.get(), psignature);

		attrs.insert(std::make_pair(attr->oid, std::move(attr)));
	}
}

DWORD get_signature_from_CMSG_SIGNER_INFO(CMSG_SIGNER_INFO* pcrypt_signature, HCERTSTORE hcrypt_certstore, SIGNATURE* psignature) {
	psignature->issuer = get_cert_name(&pcrypt_signature->Issuer, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG);
	psignature->version = pcrypt_signature->dwVersion;
	psignature->serial_number = format_crypt_blob(&pcrypt_signature->SerialNumber, true);
	psignature->encryption_algorithm = get_oid_info(CRYPT_OID_INFO_OID_KEY, pcrypt_signature->HashEncryptionAlgorithm.pszObjId, 0);
	psignature->hash_algorithm = get_oid_info(CRYPT_OID_INFO_OID_KEY, pcrypt_signature->HashAlgorithm.pszObjId, 0);

	CERT_INFO certinfo = {};
	certinfo.Issuer = pcrypt_signature->Issuer;
	certinfo.SerialNumber = pcrypt_signature->SerialNumber;
	CERT_CONTEXT_t cert_ctx(CertFindCertificateInStore(hcrypt_certstore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, &certinfo, 0));
	if (!cert_ctx)
		return GetLastError();

	std::unique_ptr<CERT> cert(std::make_unique<CERT>());
	DWORD last_error = get_cert_from_CERT_CONTEXT(cert_ctx.get(), cert.get());
	if (last_error != 0)
		return last_error;

	CERT_CHAIN_PARA crypt_chain_para = { sizeof(CERT_CHAIN_PARA) };
	crypt_chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
	CERT_CHAIN_CONTEXT_t cert_chain_ctx;
	if (!CertGetCertificateChain(0, cert_ctx.get(), 0, 0, &crypt_chain_para, 0, 0, get_pointer_wrapper(cert_chain_ctx)))
		return GetLastError();

	if (cert_chain_ctx->cChain > 0 && cert_chain_ctx->rgpChain[0]->cElement > 1) {
		CERT* pcert_current = cert.get();
		for (DWORD index = 1; index < cert_chain_ctx->rgpChain[0]->cElement; ++index) {
			pcert_current->chained_cert = std::make_unique<CERT>();
			if ((last_error = get_cert_from_CERT_CONTEXT(cert_chain_ctx->rgpChain[0]->rgpElement[index]->pCertContext, pcert_current->chained_cert.get())) != 0)
				return last_error;
			pcert_current = pcert_current->chained_cert.get();
		}
	}

	process_attrs(pcrypt_signature->AuthAttrs, psignature->attrs_auth, psignature);
	process_attrs(pcrypt_signature->UnauthAttrs, psignature->attrs_unauth, psignature);

	psignature->cert = std::move(cert);

	return 0;
}

DWORD get_signature_from_wtstatedata(HANDLE state_data, SIGNATURE* psignature) {
	CRYPT_PROVIDER_DATA* pcrypt_prov_data = WTHelperProvDataFromStateData(state_data);

	std::unique_ptr<SIGNATURE> countersign(std::make_unique<SIGNATURE>());
	BOOL is_countersign[2] = { FALSE, TRUE };
	SIGNATURE* psignatures[2] = { psignature, countersign.get() };
	for (size_t n = 0; n < _countof(is_countersign); ++n) {
		CRYPT_PROVIDER_SGNR *pcrypt_signature = WTHelperGetProvSignerFromChain(pcrypt_prov_data, 0, is_countersign[n], 0);
		if (!pcrypt_signature)
			continue;
		CRYPT_PROVIDER_CERT *pcrypt_cert = WTHelperGetProvCertFromChain(pcrypt_signature, 0);
		if (!pcrypt_cert)
			continue;

		HCERTSTORE_t cert_store(CertOpenStore(CERT_STORE_PROV_COLLECTION, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, 0));
		if (!cert_store)
			return GetLastError();

		for (DWORD index = 0; index < pcrypt_prov_data->chStores; ++index) {
			if (!CertAddStoreToCollection(cert_store.get(), pcrypt_prov_data->pahStores[index], 0, 0))
				return GetLastError();
		}

		DWORD last_error = get_signature_from_CMSG_SIGNER_INFO(pcrypt_signature->psSigner, cert_store.get(), psignatures[n]);
		if (last_error != 0)
			return last_error;
	}
	psignature->countersign = std::move(countersign);
	return 0;
}

unsigned int get_file_signatures(SIGNATURE_INFO& siginfo) {
	WINTRUST_DATA wt_data = { sizeof(WINTRUST_DATA) };
	wt_data.dwUIChoice = WTD_UI_NONE;
	wt_data.fdwRevocationChecks = WTD_REVOKE_NONE;
	wt_data.dwUnionChoice = WTD_CHOICE_FILE;

	WINTRUST_FILE_INFO wt_fileinfo = { sizeof(WINTRUST_FILE_INFO) };
	wt_fileinfo.pcwszFilePath = siginfo.target.c_str();
	wt_data.pFile = &wt_fileinfo;

	WINTRUST_SIGNATURE_SETTINGS wt_sig_settings = { sizeof(WINTRUST_SIGNATURE_SETTINGS) };
	wt_sig_settings.dwFlags = WSS_GET_SECONDARY_SIG_COUNT | WSS_VERIFY_SPECIFIC;
	wt_data.pSignatureSettings = &wt_sig_settings;

	GUID wt_guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
	DWORD last_error = 0;
	while (true) {
		wt_data.dwStateAction = WTD_STATEACTION_VERIFY;
		if ((last_error = WinVerifyTrust(NULL, &wt_guid, &wt_data)) != 0)
			return last_error;

		std::unique_ptr<SIGNATURE> signature = std::make_unique<SIGNATURE>();
		if ((last_error = get_signature_from_wtstatedata(wt_data.hWVTStateData, signature.get())) != 0)
			return last_error;
		siginfo.signatures.push_back(std::move(signature));

		wt_data.dwStateAction = WTD_STATEACTION_CLOSE;
		if ((last_error = WinVerifyTrust(NULL, &wt_guid, &wt_data)) != 0)
			return last_error;
		wt_data.hWVTStateData = NULL;

		if (wt_data.pSignatureSettings == nullptr || ++wt_data.pSignatureSettings->dwIndex > wt_data.pSignatureSettings->cSecondarySigs)
			break;
	}
	return 0;
}

unsigned int get_file_signatures(const wchar_t* file, SIGNATURE_INFO& catalog, SIGNATURE_INFO& embedded) {
	embedded.target = file;
	embedded.result = get_file_signatures(embedded);

	HCATADMIN_t catadmin;
	const GUID guid = DRIVER_ACTION_VERIFY;
	if (!CryptCATAdminAcquireContext(get_pointer_wrapper(catadmin), &guid, 0))
		return (catalog.result = GetLastError());
	HANDLE_t h(CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0));
	if (!h)
		return (catalog.result = GetLastError());

	DWORD size = 0;
	if (!CryptCATAdminCalcHashFromFileHandle(h.get(), &size, 0, 0))
		return (catalog.result = GetLastError());
	std::vector<BYTE, crypt_allocator> buffer(size);
	if (!CryptCATAdminCalcHashFromFileHandle(h.get(), &size, buffer.data(), 0))
		return (catalog.result = GetLastError());

	HCATINFO_t hcatinfo(CryptCATAdminEnumCatalogFromHash(catadmin.get(), buffer.data(), static_cast<DWORD>(buffer.size()), 0, 0), deleter_HCATINFO(catadmin.get()));
	if (!hcatinfo)
		return (catalog.result = GetLastError());

	CATALOG_INFO catinfo = {};
	if (!CryptCATCatalogInfoFromContext(hcatinfo.get(), &catinfo, 0))
		return (catalog.result = GetLastError());

	catalog.target = catinfo.wszCatalogFile;
	catalog.result = get_file_signatures(catalog);

	return 0;
}

signature.h

#pragma once

#include <string>
#include <list>
#include <map>
#include <vector>
#include <memory>

using pairs = std::vector<std::pair<std::wstring, std::wstring>>;

struct CERT {
	unsigned int version;
	std::wstring serial_number;
	std::wstring name;
	std::wstring issuer;
	std::wstring subject;
	std::wstring algorithm;
	std::wstring hash_algorithm;
	std::wstring thumbprint;
	std::wstring signature_hash;
	std::wstring publickey;
	unsigned long publickey_length;
	pairs usages;
	pairs enhanced_key_usages;
	std::wstring valid_from;
	std::wstring valid_to;

	std::unique_ptr<CERT> chained_cert;
};

struct ATTR {
	unsigned int size;
	std::wstring oid;
	std::wstring name;
	std::wstring value;
};
using attrs_t = std::map<std::wstring, std::unique_ptr<ATTR>>;

struct SIGNATURE {
	unsigned int version;
	std::wstring issuer;
	std::wstring serial_number;
	std::wstring encryption_algorithm;
	std::wstring hash_algorithm;
	attrs_t attrs_auth;
	attrs_t attrs_unauth;
	std::unique_ptr<CERT> cert;
	std::unique_ptr<SIGNATURE> countersign;
};

using signatures_t = std::list<std::unique_ptr<SIGNATURE>>;

struct SIGNATURE_INFO {
	std::wstring target;
	signatures_t signatures;
	unsigned int result;
};

unsigned int get_file_signatures(const wchar_t* file, SIGNATURE_INFO& catalog, SIGNATURE_INFO& embedded);

test.cpp

#include "signature.h"

#include <string>
#include <list>
#include <vector>
#include <iterator>
#include <stdarg.h>

using strings_t = std::vector<std::wstring>;

std::wstring formatstring(const wchar_t* format, ...) {
	va_list arguments;
	va_start(arguments, format);
	int size = _vscwprintf(format, arguments) + 1;
	std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]);
	vswprintf_s(buffer.get(), size, format, arguments);
	va_end(arguments);
	return std::wstring(buffer.get());
}

strings_t format_cert(const CERT* pcert) {
	strings_t strings;
	strings.push_back(formatstring(L"version: %lu", pcert->version));
	strings.push_back(formatstring(L"serial number: %s", pcert->serial_number.c_str()));
	strings.push_back(formatstring(L"name: %s", pcert->name.c_str()));
	strings.push_back(formatstring(L"issuer: %s", pcert->issuer.c_str()));
	strings.push_back(formatstring(L"subject: %s", pcert->subject.c_str()));
	strings.push_back(formatstring(L"algorithm: %s", pcert->algorithm.c_str()));
	strings.push_back(formatstring(L"hashing: %s", pcert->hash_algorithm.c_str()));
	strings.push_back(formatstring(L"thumbprint: %s", pcert->thumbprint.c_str()));
	strings.push_back(formatstring(L"signature hash: %s", pcert->signature_hash.c_str()));
	strings.push_back(formatstring(L"public key (%lu bits): %s", pcert->publickey_length, pcert->publickey.c_str()));
	strings.push_back(formatstring(L"valid from: %s", pcert->valid_from.c_str()));
	strings.push_back(formatstring(L"valid to: %s", pcert->valid_to.c_str()));
	if (!pcert->usages.empty()) {
		strings.push_back(formatstring(L"%zu cert usage(s) ->", pcert->usages.size()));
		for (const auto& it : pcert->usages) {
			strings.push_back(formatstring(L"%zs : %zs", it.first.c_str(), it.second.c_str()));
		}
	}
	if (!pcert->enhanced_key_usages.empty()) {
		strings.push_back(formatstring(L"%zu extended key usage(s) ->", pcert->enhanced_key_usages.size()));
		for (const auto& it : pcert->enhanced_key_usages) {
			strings.push_back(formatstring(L"%zs : %zs", it.first.c_str(), it.second.c_str()));
		}
	}
	return strings;
}

strings_t format_signature(const SIGNATURE* psignature) {
	strings_t strings;
	strings.push_back(formatstring(L"version: %lu", psignature->version));
	strings.push_back(formatstring(L"issuer: %s", psignature->issuer.c_str()));
	strings.push_back(formatstring(L"serial number: %s", psignature->serial_number.c_str()));
	strings.push_back(formatstring(L"algorithm: %s", psignature->encryption_algorithm.c_str()));
	strings.push_back(formatstring(L"hashing: %s", psignature->hash_algorithm.c_str()));
	strings.push_back(L"authenticated attributes ->");
	for (const auto& it : psignature->attrs_auth) {
		const std::wstring name = it.second->oid == it.second->name ? it.second->oid : formatstring(L"%s(%s)", it.second->oid.c_str(), it.second->name.c_str());
		strings.push_back(formatstring(L"%s(%lu bytes): %s", name.c_str(), it.second->size, it.second->value.c_str()));
	}
	strings.push_back(L"unauthenticated attributes ->");
	for (const auto& it : psignature->attrs_unauth) {
		const std::wstring name = it.second->oid == it.second->name ? it.second->oid : formatstring(L"%s(%s)", it.second->oid.c_str(), it.second->name.c_str());
		strings.push_back(formatstring(L"%s(%lu bytes): %s", name.c_str(), it.second->size, it.second->value.c_str()));
	}
	return strings;
}

void print_with_indent(const std::wstring& indent, const strings_t& strings) {
	for (const auto& it : strings) {
		wprintf(L"%s%s\n", indent.c_str(), it.c_str());
	}
}

void print_certs(std::wstring indent, const CERT* pcert) {
	while (true) {
		indent += L'\t';
		print_with_indent(indent, format_cert(pcert));
		pcert = pcert->chained_cert.get();
		if (pcert == nullptr)
			break;

		wprintf(L"\n");
		print_with_indent(indent, { L"chained certificate ->" });
	}
}

void print_signature(std::wstring indent, const SIGNATURE* psignature) {
	print_with_indent(indent, format_signature(psignature));
	if (psignature->cert) {
		wprintf(L"\n");
		print_with_indent(indent, { L"signing certificate ->" });
		indent += L'\t';
		print_certs(indent, psignature->cert.get());
	}
}

void print_signatures(std::wstring indent, const signatures_t& signatures) {
	size_t index = 0;
	for (auto& it : signatures) {
		wprintf(L"\n");
		print_with_indent(indent, { formatstring(L"signature %zu of %zu ->", ++index, signatures.size()) });
		indent += L'\t';
		print_signature(indent, it.get());

		if (it->countersign) {
			wprintf(L"\n");
			print_with_indent(indent, { L"counter-signing signature ->" });
			wprintf(L"\n");
			indent += L'\t';
			print_signature(indent, it->countersign.get());
		}
	}
}

int wmain(int argc, wchar_t* argv[])
{
	if (argc < 2) {
		wprintf(L"error: no file specified\n");
		return -1;
	}
	SIGNATURE_INFO catalog, embedded;
	get_file_signatures(argv[1], catalog, embedded);
	if (catalog.result == 0 && !catalog.signatures.empty()) {
		wprintf(L"%s is catalog signed by %s ->", argv[1], catalog.target.c_str());
		wprintf(L"\n\n");
		print_signatures(L"\t", catalog.signatures);
		wprintf(L"\n");
	}
	if (embedded.result == 0 && !embedded.signatures.empty()) {
		wprintf(L"%s has %zu embedded signature(s) ->", embedded.target.c_str(), embedded.signatures.size());
		wprintf(L"\n\n");
		print_signatures(L"\t", embedded.signatures);
		wprintf(L"\n");
	}
	return 0;
}

Test output for C:\Windows\system32\msvcp140.dll:

C:\WINDOWS\system32\msvcp140.dll has 2 embedded signature(s) ->


	signature 1 of 2 ->
		version: 1
		issuer: CN=Microsoft Code Signing PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
		serial number: 330000014096a9ee7056fecc07000100000140
		algorithm: RSA
		hashing: sha1
		authenticated attributes ->
		1.2.840.113549.1.9.3(Content Type)(12 bytes): 060a2b060104018237020104
		1.2.840.113549.1.9.4(Message Digest)(22 bytes): 04144ea7d086546229b36cfb647ded03417b134ae818
		1.3.6.1.4.1.311.2.1.11(14 bytes): 300c060a2b060104018237020115
		1.3.6.1.4.1.311.2.1.12(54 bytes): program:msvcp140.dll; moreinfo:http://microsoft.com; 
		unauthenticated attributes ->
		1.2.840.113549.1.9.6(Counter Sign)(533 bytes): 3082021102010130818e3077310b30090603550406130255533113301106035504...
		1.3.6.1.4.1.311.2.4.1(9212 bytes): 308223f806092a864886f70d010702a08223e9308223e5020101310f300d060960...

		signing certificate ->
				version: 2
				serial number: 330000014096a9ee7056fecc07000100000140
				name: Microsoft Corporation
				issuer: Microsoft Code Signing PCA
				subject: CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
				algorithm: RSA
				hashing: sha1RSA
				thumbprint: 98ed99a67886d020c564923b7df25e9ac019df26
				signature hash: 2ccee2e34061e1c24c1dd6aa3147b6c0dfb4eafc
				public key (2048 bits): 3082010a0282010100db4b8be9036a5fc81b5d0a0539e4d50e92d0c4e18be8a40d...
				valid from: Sun Aug 18 16:17:17 2016
				valid to: Sun Nov  2 16:17:17 2017
				1 extended key usage(s) ->
				Code Signing : 1.3.6.1.5.5.7.3.3

				chained certificate ->
					version: 2
					serial number: 6133261a000000000031
					name: Microsoft Code Signing PCA
					issuer: Microsoft Root Certificate Authority
					subject: CN=Microsoft Code Signing PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha1RSA
					thumbprint: 3caf9ba2db5570caf76942ff99101b993888e257
					signature hash: 27543a3f7612de2261c7228321722402f63a07de
					public key (2048 bits): 3082010a0282010100b272595c193064bf1d9a602020429976536c3e1bd66fcccb...
					valid from: Sun Aug 31 18:19:32 2010
					valid to: Sun Aug 31 18:29:32 2020

					chained certificate ->
						version: 2
						serial number: 79ad16a14aa0a5ad4c7358f407132e65
						name: Microsoft Root Certificate Authority
						issuer: Microsoft Root Certificate Authority
						subject: CN=Microsoft Root Certificate Authority, DC=microsoft, DC=com
						algorithm: RSA
						hashing: sha1RSA
						thumbprint: cdd4eeae6000ac7f40c3802c171e30148030c072
						signature hash: 391be92883d52509155bfeae27b9bd340170b76b
						public key (4096 bits): 3082020a0282020100f35dfa8067d45aa7a90c2c9020d035083c7584cdb707899c...
						valid from: Sun May  9 19:19:22 2001
						valid to: Sun May  9 19:28:13 2021

		counter-signing signature ->

			version: 1
			issuer: CN=Microsoft Time-Stamp PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
			serial number: 33000000c59640604bf4deae2e0000000000c5
			algorithm: sha1RSA
			hashing: sha1
			authenticated attributes ->
			1.2.840.113549.1.9.3(Content Type)(11 bytes): 06092a864886f70d010701
			1.2.840.113549.1.9.4(Message Digest)(22 bytes): 04145d47a122156c313c94853b1cf0297d649d7e7dd5
			1.2.840.113549.1.9.5(Signing Time)(15 bytes): timestamp:Sun Feb  8 03:09:39 2017; 
			unauthenticated attributes ->

			signing certificate ->
					version: 2
					serial number: 33000000c59640604bf4deae2e0000000000c5
					name: Microsoft Time-Stamp Service
					issuer: Microsoft Time-Stamp PCA
					subject: CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:C0F4-3086-DEF8, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha1RSA
					thumbprint: 7ba57715b0f79ca2cf921e5f2a72be11c2fadc67
					signature hash: 82a0b845f75deb250c3ef6a214fa5895edc4e693
					public key (2048 bits): 3082010a0282010100b6bc33e0258ea6f9f010154e7b572b28496bb3709097fcae...
					valid from: Sun Sep  7 13:58:52 2016
					valid to: Sun Sep  7 13:58:52 2018
					1 extended key usage(s) ->
					Time Stamping : 1.3.6.1.5.5.7.3.8

					chained certificate ->
						version: 2
						serial number: 6116683400000000001c
						name: Microsoft Time-Stamp PCA
						issuer: Microsoft Root Certificate Authority
						subject: CN=Microsoft Time-Stamp PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha1RSA
						thumbprint: 375fcb825c3dc3752a02e34eb70993b4997191ef
						signature hash: 023cf1c5e99dc2f24133dae6937145bb481306e6
						public key (2048 bits): 3082010a02820101009fa16cb1dfdb48922a7c6b2e19e1bde2e3c599512350adce...
						valid from: Sun Apr  3 08:53:09 2007
						valid to: Sun Apr  3 09:03:09 2021
						1 extended key usage(s) ->
						Time Stamping : 1.3.6.1.5.5.7.3.8

						chained certificate ->
							version: 2
							serial number: 79ad16a14aa0a5ad4c7358f407132e65
							name: Microsoft Root Certificate Authority
							issuer: Microsoft Root Certificate Authority
							subject: CN=Microsoft Root Certificate Authority, DC=microsoft, DC=com
							algorithm: RSA
							hashing: sha1RSA
							thumbprint: cdd4eeae6000ac7f40c3802c171e30148030c072
							signature hash: 391be92883d52509155bfeae27b9bd340170b76b
							public key (4096 bits): 3082020a0282020100f35dfa8067d45aa7a90c2c9020d035083c7584cdb707899c...
							valid from: Sun May  9 19:19:22 2001
							valid to: Sun May  9 19:28:13 2021

			signature 2 of 2 ->
				version: 1
				issuer: CN=Microsoft Code Signing PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
				serial number: 330000008e8791a4571a5fca3e00000000008e
				algorithm: RSA
				hashing: sha256
				authenticated attributes ->
				1.2.840.113549.1.9.25.4(3 bytes): 020101
				1.2.840.113549.1.9.3(Content Type)(12 bytes): 060a2b060104018237020104
				1.2.840.113549.1.9.4(Message Digest)(34 bytes): 0420efbf66f54719eaa363ada4fa9cbe0dc4d722ec7a1563bb406bf90bb7f25272...
				1.3.6.1.4.1.311.2.1.11(14 bytes): 300c060a2b060104018237020115
				1.3.6.1.4.1.311.2.1.12(54 bytes): program:msvcp140.dll; moreinfo:http://microsoft.com; 
				unauthenticated attributes ->
				1.3.6.1.4.1.311.3.3.1(4921 bytes): 3082133506092a864886f70d010702a082132630821322020103310f300d060960...

				signing certificate ->
						version: 2
						serial number: 330000008e8791a4571a5fca3e00000000008e
						name: Microsoft Corporation
						issuer: Microsoft Code Signing PCA 2011
						subject: CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha256RSA
						thumbprint: b9eaa034c821c159b05d3521bcf7feb796ebd6ff
						signature hash: 84d8717a416c8c9e214c6e0dbd091860d8133f413bcff35673998f27bba084ca
						public key (2048 bits): 3082010a0282010100d087d4422b7e9dd9c67ad4a2c3e31592d2539d9517c95236...
						valid from: Sun Nov 17 18:09:21 2016
						valid to: Sun Feb 17 18:09:21 2018
						2 extended key usage(s) ->
						Microsoft Publisher : 1.3.6.1.4.1.311.76.8.1
						Code Signing : 1.3.6.1.5.5.7.3.3

						chained certificate ->
							version: 2
							serial number: 610e90d2000000000003
							name: Microsoft Code Signing PCA 2011
							issuer: Microsoft Root Certificate Authority 2011
							subject: CN=Microsoft Code Signing PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
							algorithm: RSA
							hashing: sha256RSA
							thumbprint: f252e794fe438e35ace6e53762c0a234a2c52135
							signature hash: f6f717a43ad9abddc8cefdde1c505462535e7d1307e630f9544a2d14fe8bf26e
							public key (4096 bits): 3082020a0282020100abf0fa72101c2eadd86eaa82104d34baf2b658219f421b2a...
							valid from: Sun Jul  8 16:59:09 2011
							valid to: Sun Jul  8 17:09:09 2026

							chained certificate ->
								version: 2
								serial number: 3f8bc8b5fc9fb29643b569d66c42e144
								name: Microsoft Root Certificate Authority 2011
								issuer: Microsoft Root Certificate Authority 2011
								subject: CN=Microsoft Root Certificate Authority 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
								algorithm: RSA
								hashing: sha256RSA
								thumbprint: 8f43288ad272f3103b6fb1428485ea3014c0bcfe
								signature hash: 279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1
								public key (4096 bits): 3082020a0282020100b28041aa35384d13723268224db8b2f1ffd552bc6cc7f5d2...
								valid from: Sun Mar 22 18:05:28 2011
								valid to: Sun Mar 22 18:13:04 2036

				counter-signing signature ->

					version: 1
					issuer: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					serial number: 33000000a1a5fdb9eea7fc9e9d0000000000a1
					algorithm: sha256RSA
					hashing: sha256
					authenticated attributes ->
					1.2.840.113549.1.9.16.2.12(210 bytes): 3081cf3081cc3081b1041482ae89f5b4e63f165c20bc17e4c1c340cd39eb683081...
					1.2.840.113549.1.9.3(Content Type)(13 bytes): 060b2a864886f70d0109100104
					1.2.840.113549.1.9.4(Message Digest)(34 bytes): 04201fb274bf8d2388a9f67a01264c6be27f3c51e852bccd15a91287092ddd4799...
					unauthenticated attributes ->

					signing certificate ->
							version: 2
							serial number: 33000000a1a5fdb9eea7fc9e9d0000000000a1
							name: Microsoft Time-Stamp Service
							issuer: Microsoft Time-Stamp PCA 2010
							subject: CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:BBEC-30CA-2DBE, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
							algorithm: RSA
							hashing: sha256RSA
							thumbprint: 82ae89f5b4e63f165c20bc17e4c1c340cd39eb68
							signature hash: fd68d99c338b8ebfc6990fccd15e2ed939f78bea8a2fd528bb197c0a4256af0b
							public key (2048 bits): 3082010a02820101009bd00179e622af7a7c1b751ef3b767d61ddea7de0034d812...
							valid from: Sun Sep  7 13:56:48 2016
							valid to: Sun Sep  7 13:56:48 2018
							1 extended key usage(s) ->
							Time Stamping : 1.3.6.1.5.5.7.3.8

							chained certificate ->
								version: 2
								serial number: 6109812a000000000002
								name: Microsoft Time-Stamp PCA 2010
								issuer: Microsoft Root Certificate Authority 2010
								subject: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
								algorithm: RSA
								hashing: sha256RSA
								thumbprint: 2aa752fe64c49abe82913c463529cf10ff2f04ee
								signature hash: 85975b97560b1c3698f6ea90e4423691bfcc76ef2b95971293c079363f4decd7
								public key (2048 bits): 3082010a0282010100a91d0dbc77118a3a20ecfc1397f5fa7f69946b745410d5a5...
								valid from: Sun Jul  1 17:36:55 2010
								valid to: Sun Jul  1 17:46:55 2025

								chained certificate ->
									version: 2
									serial number: 28cc3a25bfba44ac449a9b586b4339aa
									name: Microsoft Root Certificate Authority 2010
									issuer: Microsoft Root Certificate Authority 2010
									subject: CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
									algorithm: RSA
									hashing: sha256RSA
									thumbprint: 3b1efd3a66ea28b16697394703a72ca340a05bd5
									signature hash: 08fba831c08544208f5208686b991ca1b2cfc510e7301784ddf1eb5bf0393239
									public key (4096 bits): 3082020a0282020100b9089e28e4e4ec064e5068b341c57bebaeb68eaf81ba2244...
									valid from: Sun Jun 23 17:57:24 2010
									valid to: Sun Jun 23 18:04:01 2035

Test output for C:\Windows\system32\drivers\wdboot.sys:

C:\WINDOWS\system32\drivers\wdboot.sys is catalog signed by C:\WINDOWS\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Windows-Defender-Core-Group-onecore-Package~31bf3856ad364e35~amd64~~10.0.15063.0.cat ->


	signature 1 of 1 ->
		version: 1
		issuer: CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
		serial number: 33000001066ec325c431c9180e000000000106
		algorithm: RSA
		hashing: sha256
		authenticated attributes ->
		1.2.840.113549.1.9.3(Content Type)(11 bytes): 06092b0601040182370a01
		1.2.840.113549.1.9.4(Message Digest)(34 bytes): 042067c948513cff6cf1449df945fd6366c98e8d15912dc7a50d881df4e2fa4eb0...
		1.3.6.1.4.1.311.2.1.11(14 bytes): 300c060a2b060104018237020115
		1.3.6.1.4.1.311.2.1.12(76 bytes): program:Microsoft Windows; moreinfo:http://www.microsoft.com/windows; 
		unauthenticated attributes ->
		1.3.6.1.4.1.311.3.3.1(4919 bytes): 3082133306092a864886f70d010702a082132430821320020103310f300d060960...

		signing certificate ->
				version: 2
				serial number: 33000001066ec325c431c9180e000000000106
				name: Microsoft Windows
				issuer: Microsoft Windows Production PCA 2011
				subject: CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
				algorithm: RSA
				hashing: sha256RSA
				thumbprint: afdd80c4ebf2f61d3943f18bb566d6aa6f6e5033
				signature hash: 0ae3a29cfb54cd16c853b2246cc428219bb87f7e4ea299b0374b2ac43f2a61d8
				public key (2048 bits): 3082010a0282010100c9671a0988213489e4dde729caedae67b2c257d412ec6598...
				valid from: Sun Oct 11 16:39:31 2016
				valid to: Sun Jan 11 16:39:31 2018
				2 extended key usage(s) ->
				Windows System Component Verification : 1.3.6.1.4.1.311.10.3.6
				Code Signing : 1.3.6.1.5.5.7.3.3

				chained certificate ->
					version: 2
					serial number: 61077656000000000008
					name: Microsoft Windows Production PCA 2011
					issuer: Microsoft Root Certificate Authority 2010
					subject: CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha256RSA
					thumbprint: 580a6f4cc4e4b669b9ebdc1b2b3e087b80d0678d
					signature hash: 4e80be107c860de896384b3eff50504dc2d76ac7151df3102a4450637a032146
					public key (2048 bits): 3082010a0282010100dd0cbba2e42e09e3e7c5f79669bc0021bd693333efad04cb...
					valid from: Sun Oct 19 14:41:42 2011
					valid to: Sun Oct 19 14:51:42 2026

					chained certificate ->
						version: 2
						serial number: 28cc3a25bfba44ac449a9b586b4339aa
						name: Microsoft Root Certificate Authority 2010
						issuer: Microsoft Root Certificate Authority 2010
						subject: CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha256RSA
						thumbprint: 3b1efd3a66ea28b16697394703a72ca340a05bd5
						signature hash: 08fba831c08544208f5208686b991ca1b2cfc510e7301784ddf1eb5bf0393239
						public key (4096 bits): 3082020a0282020100b9089e28e4e4ec064e5068b341c57bebaeb68eaf81ba2244...
						valid from: Sun Jun 23 17:57:24 2010
						valid to: Sun Jun 23 18:04:01 2035

		counter-signing signature ->

			version: 1
			issuer: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
			serial number: 33000000b235056837221c0da70000000000b2
			algorithm: sha256RSA
			hashing: sha256
			authenticated attributes ->
			1.2.840.113549.1.9.16.2.12(210 bytes): 3081cf3081cc3081b10414bdffc5956390f1139c60d619c0afe9b89e1e201d3081...
			1.2.840.113549.1.9.3(Content Type)(13 bytes): 060b2a864886f70d0109100104
			1.2.840.113549.1.9.4(Message Digest)(34 bytes): 0420282e8f34290e60ad90ff3d2e6a4769d1085b7cb498601afb4aed9836ab5caf...
			unauthenticated attributes ->

			signing certificate ->
					version: 2
					serial number: 33000000b235056837221c0da70000000000b2
					name: Microsoft Time-Stamp Service
					issuer: Microsoft Time-Stamp PCA 2010
					subject: CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:728D-C45F-F9EB, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha256RSA
					thumbprint: bdffc5956390f1139c60d619c0afe9b89e1e201d
					signature hash: 07448ef8afa3dcda224722d295b2929d226982c4bbe4960143c07bf3a4bd143f
					public key (2048 bits): 3082010a0282010100984a01bbd158f57f749142e9a12e535df22c206f122e9bd3...
					valid from: Sun Sep  7 13:56:57 2016
					valid to: Sun Sep  7 13:56:57 2018
					1 extended key usage(s) ->
					Time Stamping : 1.3.6.1.5.5.7.3.8

					chained certificate ->
						version: 2
						serial number: 6109812a000000000002
						name: Microsoft Time-Stamp PCA 2010
						issuer: Microsoft Root Certificate Authority 2010
						subject: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha256RSA
						thumbprint: 2aa752fe64c49abe82913c463529cf10ff2f04ee
						signature hash: 85975b97560b1c3698f6ea90e4423691bfcc76ef2b95971293c079363f4decd7
						public key (2048 bits): 3082010a0282010100a91d0dbc77118a3a20ecfc1397f5fa7f69946b745410d5a5...
						valid from: Sun Jul  1 17:36:55 2010
						valid to: Sun Jul  1 17:46:55 2025

						chained certificate ->
							version: 2
							serial number: 28cc3a25bfba44ac449a9b586b4339aa
							name: Microsoft Root Certificate Authority 2010
							issuer: Microsoft Root Certificate Authority 2010
							subject: CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
							algorithm: RSA
							hashing: sha256RSA
							thumbprint: 3b1efd3a66ea28b16697394703a72ca340a05bd5
							signature hash: 08fba831c08544208f5208686b991ca1b2cfc510e7301784ddf1eb5bf0393239
							public key (4096 bits): 3082020a0282020100b9089e28e4e4ec064e5068b341c57bebaeb68eaf81ba2244...
							valid from: Sun Jun 23 17:57:24 2010
							valid to: Sun Jun 23 18:04:01 2035

C:\WINDOWS\system32\drivers\wdboot.sys has 1 embedded signature(s) ->


	signature 1 of 1 ->
		version: 1
		issuer: CN=Microsoft Code Signing PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
		serial number: 330000014b617d5ba87a68e2db00000000014b
		algorithm: RSA
		hashing: sha256
		authenticated attributes ->
		1.2.840.113549.1.9.3(Content Type)(12 bytes): 060a2b060104018237020104
		1.2.840.113549.1.9.4(Message Digest)(34 bytes): 042062954297f4e99bf2dd8d3caa05995f44dd488f4d5a3dfa81dfeb4e6ca8440a...
		1.3.6.1.4.1.311.10.3.28(Platform Manifest Binary ID)(46 bytes): 0c2c7134377a473137304f7a4f724737375770554a6845773039515339722f6a49...
		1.3.6.1.4.1.311.2.1.11(14 bytes): 300c060a2b060104018237020115
		1.3.6.1.4.1.311.2.1.12(76 bytes): program:Microsoft Windows; moreinfo:http://www.microsoft.com/windows; 
		unauthenticated attributes ->
		1.3.6.1.4.1.311.3.3.1(4915 bytes): 3082132f06092a864886f70d010702a08213203082131c020103310f300d060960...

		signing certificate ->
				version: 2
				serial number: 330000014b617d5ba87a68e2db00000000014b
				name: Microsoft Windows Early Launch Anti-malware Publisher
				issuer: Microsoft Code Signing PCA 2010
				subject: CN=Microsoft Windows Early Launch Anti-malware Publisher, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
				algorithm: RSA
				hashing: sha256RSA
				thumbprint: 1412f186eeadbfbc37982d36a45e4bef823ee2ca
				signature hash: b4042b1d4310481b79ba8bc0f14d7ad09af03a5a35fa875d158e903996b0996c
				public key (2048 bits): 3082010a0282010100a0ee2f90342edf3f43f05d1c574654cd06c702cab0adf3bf...
				valid from: Sun Nov 17 17:59:06 2016
				valid to: Sun Feb 17 17:59:06 2018
				2 extended key usage(s) ->
				Early Launch Antimalware Driver : 1.3.6.1.4.1.311.61.4.1
				Code Signing : 1.3.6.1.5.5.7.3.3

				chained certificate ->
					version: 2
					serial number: 610c524c000000000003
					name: Microsoft Code Signing PCA 2010
					issuer: Microsoft Root Certificate Authority 2010
					subject: CN=Microsoft Code Signing PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha256RSA
					thumbprint: 8bfe3107712b3c886b1c96aaec89984914dc9b6b
					signature hash: 121af4b922a74247ea49df50de37609cc1451a1fe06b2cb7e1e079b492bd8195
					public key (2048 bits): 3082010a0282010100e90e64507967b5c4e3fd09004c9e94acf75668ea44d8cfc5...
					valid from: Sun Jul  6 16:40:17 2010
					valid to: Sun Jul  6 16:50:17 2025

					chained certificate ->
						version: 2
						serial number: 28cc3a25bfba44ac449a9b586b4339aa
						name: Microsoft Root Certificate Authority 2010
						issuer: Microsoft Root Certificate Authority 2010
						subject: CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha256RSA
						thumbprint: 3b1efd3a66ea28b16697394703a72ca340a05bd5
						signature hash: 08fba831c08544208f5208686b991ca1b2cfc510e7301784ddf1eb5bf0393239
						public key (4096 bits): 3082020a0282020100b9089e28e4e4ec064e5068b341c57bebaeb68eaf81ba2244...
						valid from: Sun Jun 23 17:57:24 2010
						valid to: Sun Jun 23 18:04:01 2035

		counter-signing signature ->

			version: 1
			issuer: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
			serial number: 33000000b4433a1cfeb6ba52890000000000b4
			algorithm: sha256RSA
			hashing: sha256
			authenticated attributes ->
			1.2.840.113549.1.9.16.2.12(210 bytes): 3081cf3081cc3081b1041407c09597ae2e4e6ec9d375f6d98951988b206d3a3081...
			1.2.840.113549.1.9.3(Content Type)(13 bytes): 060b2a864886f70d0109100104
			1.2.840.113549.1.9.4(Message Digest)(34 bytes): 042015571b68ee3a60fc0f568bc76ab99943ea4ab997b59fb7d2f822098d89a84b...
			unauthenticated attributes ->

			signing certificate ->
					version: 2
					serial number: 33000000b4433a1cfeb6ba52890000000000b4
					name: Microsoft Time-Stamp Service
					issuer: Microsoft Time-Stamp PCA 2010
					subject: CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:148C-C4B9-2066, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
					algorithm: RSA
					hashing: sha256RSA
					thumbprint: 07c09597ae2e4e6ec9d375f6d98951988b206d3a
					signature hash: b54f26fad46985a2e2ef7b93e5a4a223149273ce39b052dc38b350bad09280ec
					public key (2048 bits): 3082010a0282010100e0814fbbb5d1303a3f8300b7cc569ff79bacbab35d64111e...
					valid from: Sun Sep  7 13:56:58 2016
					valid to: Sun Sep  7 13:56:58 2018
					1 extended key usage(s) ->
					Time Stamping : 1.3.6.1.5.5.7.3.8

					chained certificate ->
						version: 2
						serial number: 6109812a000000000002
						name: Microsoft Time-Stamp PCA 2010
						issuer: Microsoft Root Certificate Authority 2010
						subject: CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
						algorithm: RSA
						hashing: sha256RSA
						thumbprint: 2aa752fe64c49abe82913c463529cf10ff2f04ee
						signature hash: 85975b97560b1c3698f6ea90e4423691bfcc76ef2b95971293c079363f4decd7
						public key (2048 bits): 3082010a0282010100a91d0dbc77118a3a20ecfc1397f5fa7f69946b745410d5a5...
						valid from: Sun Jul  1 17:36:55 2010
						valid to: Sun Jul  1 17:46:55 2025

						chained certificate ->
							version: 2
							serial number: 28cc3a25bfba44ac449a9b586b4339aa
							name: Microsoft Root Certificate Authority 2010
							issuer: Microsoft Root Certificate Authority 2010
							subject: CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
							algorithm: RSA
							hashing: sha256RSA
							thumbprint: 3b1efd3a66ea28b16697394703a72ca340a05bd5
							signature hash: 08fba831c08544208f5208686b991ca1b2cfc510e7301784ddf1eb5bf0393239
							public key (4096 bits): 3082020a0282020100b9089e28e4e4ec064e5068b341c57bebaeb68eaf81ba2244...
							valid from: Sun Jun 23 17:57:24 2010
							valid to: Sun Jun 23 18:04:01 2035


Code can be downloaded from https://1drv.ms/u/s!Am6jBwy5CzMPhmfMRhTZzaExRHAP.

Advertisements

Posted on September 8, 2016, in Uncategorized. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: