获取非托管中已签名 EXE 的 X509 代码签名证书序列号 C/C++
Get X509 Code Signing Certificate Serial Number of signed EXE in unmanaged C/C++
我知道如何使用 C# DotNet 获取已签名 DLL 或 EXE 的代码签名证书详细信息,包括序列号。例如:
using System.Security.Cryptography.X509Certificates;
...
X509Certificate certinfo = X509Certificate.CreateFromSignedFile(filename);
byte[] serialno = certinfo.GetSerialNumber();
但是我如何使用非托管 C/C++ 来做到这一点?
我确实找到了如何在 C/++ 中遍历证书存储的 example,但没有找到如何获取已签名 EXE 或 DLL 的证书详细信息。
下面是一个如何解码可执行文件的 PKCS7 (CMS) 数据的示例。
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
// Get PKCS7 data
if(1)
{
// Must be an absolute path.
const wchar_t *filePath = L"C:\Windows\System32\ntdll.dll";
if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, filePath,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
&dwContentType, &dwFormatType, &hStore,
&hMsg, NULL))
return 1;
}
else
{
/* Or do this if you want more control:
- load exe into memory
- find the certificate directory (WIN_CERTIFICATE)
WIN_CERTIFICATE &winCert = ...
CERT_BLOB certBlob = { winCert.dwLength, winCert.bCertificate };
if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &certBlob,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
&dwContentType, &dwFormatType, &hStore,
&hMsg, NULL))
return 1;
*/
}
// Get signers information
DWORD dwSignerCount = 0;
DWORD dwSignerCountSize = sizeof(dwSignerCount);
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwSignerCount, &dwSignerCountSize))
return 1;
// The signer count seems to always be 1.
// Subsequent certificates can be retrieved like this:
//
for(DWORD i = 0; i < dwSignerCount; ++i)
{
DWORD cbSignerInfo;
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, NULL, &cbSignerInfo))
return 1;
PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)malloc(cbSignerInfo);
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, pSignerInfo, &cbSignerInfo))
return 1;
// Do something with pSignerInfo->SerialNumber
// Enumerate nested certificates...
free(pSignerInfo);
}
return 0;
我知道如何使用 C# DotNet 获取已签名 DLL 或 EXE 的代码签名证书详细信息,包括序列号。例如:
using System.Security.Cryptography.X509Certificates;
...
X509Certificate certinfo = X509Certificate.CreateFromSignedFile(filename);
byte[] serialno = certinfo.GetSerialNumber();
但是我如何使用非托管 C/C++ 来做到这一点?
我确实找到了如何在 C/++ 中遍历证书存储的 example,但没有找到如何获取已签名 EXE 或 DLL 的证书详细信息。
下面是一个如何解码可执行文件的 PKCS7 (CMS) 数据的示例。
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
// Get PKCS7 data
if(1)
{
// Must be an absolute path.
const wchar_t *filePath = L"C:\Windows\System32\ntdll.dll";
if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, filePath,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
&dwContentType, &dwFormatType, &hStore,
&hMsg, NULL))
return 1;
}
else
{
/* Or do this if you want more control:
- load exe into memory
- find the certificate directory (WIN_CERTIFICATE)
WIN_CERTIFICATE &winCert = ...
CERT_BLOB certBlob = { winCert.dwLength, winCert.bCertificate };
if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &certBlob,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding,
&dwContentType, &dwFormatType, &hStore,
&hMsg, NULL))
return 1;
*/
}
// Get signers information
DWORD dwSignerCount = 0;
DWORD dwSignerCountSize = sizeof(dwSignerCount);
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwSignerCount, &dwSignerCountSize))
return 1;
// The signer count seems to always be 1.
// Subsequent certificates can be retrieved like this:
//
for(DWORD i = 0; i < dwSignerCount; ++i)
{
DWORD cbSignerInfo;
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, NULL, &cbSignerInfo))
return 1;
PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)malloc(cbSignerInfo);
if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, i, pSignerInfo, &cbSignerInfo))
return 1;
// Do something with pSignerInfo->SerialNumber
// Enumerate nested certificates...
free(pSignerInfo);
}
return 0;