从可执行文件读取并验证证书

时间:2011-08-30 09:54:49

标签: c++ windows validation certificate executable

我想验证已签名的可执行映像的证书(通过验证,我的意思是告诉签名是否来自MS / Adob​​e / Oracle等)。 Windows是否为此任务提供api?我该怎么办,不知道。任何帮助,将不胜感激。 我正在使用Windows和C ++。我想验证本机可执行映像,而不是.NET程序集或Java jar文件。

更新


好的,我会尽快描述我想要的内容。

1)验证PE证书。签名是否有效。当签名嵌入在PE中并且签名位于安全目录中时,它应该工作。 (我在sysinternals论坛上找到了这个并且运行正常,所以我不再需要这个了)。

2)告诉谁是文件的签名者/出版者。我知道它可以通过CryptQueryObject实现(我发现了一个工作示例,虽然它不能与安全目录一起使用),但不知道如何将它与安全目录文件一起使用。

3 个答案:

答案 0 :(得分:23)

有许多API和方法可以获取和验证可执行文件的签名以及如何获取所需的其他信息。问题在于您选择的级别(高级别,如WinVerifyTrust

可用于从CAT或EXE文件获取加密上下文的最简单的第一个API是CryptQueryObject函数。 KB323809中的代码示例可以帮助您了解如何解码所需信息。如果您使用CAT文件的主要区别是您应该修改CryptQueryObject的一些参数。我建议您只使用CERT_QUERY_CONTENT_FLAG_ALLCERT_QUERY_FORMAT_FLAG_ALLCryptQueryObject将在内部完成您所需的所有工作:

BOOL bIsSuccess;
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PVOID pvContext = NULL;

// fill szFileName
...

// Get message handle and store handle from the signed file.
bIsSuccess = CryptQueryObject (CERT_QUERY_OBJECT_FILE,
                               szFileName,
                               CERT_QUERY_CONTENT_FLAG_ALL,
                               CERT_QUERY_FORMAT_FLAG_ALL,
                               0,
                               &dwEncoding,
                               &dwContentType,
                               &dwFormatType,
                               &hStore,
                               &hMsg,
                               &pvContext);

dwContentType设置的值CryptQueryObject将为您提供有关文件类型szFileName的基本信息。对于您需要的大多数情况,pvContext将为PCCERT_CONTEXT,但如果您使用.ctl或.crl文件作为输入,它也可以是PCCRL_CONTEXTPCCTL_CONTEXT。您将收到hStore,其中包含文件szFileName中的所有证书。因此,对于pvContexthStore,您可以检查包含CryptoAPI的文件。如果你愿意的话  您可以使用hMsg的低级别按摩API,如果某些dwContentType(至少适用于CERT_QUERY_CONTENT_PKCS7_SIGNEDCERT_QUERY_CONTENT_PKCS7_UNSIGNEDCERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED),则会额外设置

要验证文件的签名,我建议您使用CertGetCertificateChainCertVerifyCertificateChainPolicy来验证证书一般有效,但它(或其所有父项)是有效的for authenticode(szOID_PKIX_KP_CODE_SIGNING)。 CertGetCertificateChain可用于不同的撤销方案。您应该使用CERT_CHAIN_POLICY_AUTHENTICODECERT_CHAIN_POLICY_AUTHENTICODE_TS进行两次单独调用,以验证Authenticode链策略和Authenticode时间戳链策略是否有效。

更新:我重读了您当前的问题(更新后的部分)。您当前的问题是如何获取文件的签名者/发布者。所以我只回答这个问题。

如果您使用the code from sysinternal进行签名验证,则应该只搜索

if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )

语句sill设置InfoStruct的字段,以防该文件是系统窗口文件,哪个签名是针对某些.cat文件进行验证的。字段InfoStruct.wszCatalogFile将为您提供.cat文件的名称。

例如,在我的Windows 7上,如果我尝试验证C:\Windows\explorer.exe文件的数字签名,则可以找到其哈希值的.cat是C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat

如果您使用KB323809中的代码与CryptQueryObject的上述参数,您将解码SPC_SP_OPUS_INFO_OBJID(“1.3.6.1.4.1.311.2.1.12”)属性{ {1}}(请参阅函数C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat),您将知道

GetProgAndPublisherInfo

因此,该文件不包含特殊的发布者信息。如果你检查目录的签名者,你会发现:

pwszProgramName: "Windows Express Security Catalogs"
pPublisherInfo: NULL
pMoreInfo->dwLinkChoice: SPC_URL_LINK_CHOICE
pMoreInfo->pwszUrl "http://www.microsoft.com"

所以你应该只使用.cat文件的签名者,因为没有The signer of the .cat file: "Microsoft Windows" The signer signed it with the certificate: Serial Number: 0x6115230F00000000000A Issuer Name: Microsoft Windows Verification PCA Full Issuer Name: CN = Microsoft Windows Verification PCA O = Microsoft Corporation L = Redmond S = Washington C = US Subject Name: Microsoft Windows Full Subject Name: CN = Microsoft Windows OU = MOPR O = Microsoft Corporation L = Redmond S = Washington C = US The Date of TimeStamp : 28.02.2011 21:16:36 TimeStamp Certificate: Serial Number: 0x6103DCF600000000000C Issuer Name: Microsoft Time-Stamp PCA Subject Name: Microsoft Time-Stamp Service 的其他签名者。

答案 1 :(得分:4)

WinVerifyTrust函数对指定对象执行信任验证操作。该函数将查询传递给支持操作标识符的信任提供程序(如果存在)。

对于证书验证,请使用CertGetCertificateChain和CertVerifyCertificateChainPolicy函数。

答案 2 :(得分:1)

@Davita  我彻底阅读了上述问题并试图解决它。

我的建议是在CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED

的第三个参数中尝试CERT_QUERY_CONTENT_FLAG_ALL而不是CryptQueryObject()