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

问题描述 投票:15回答:3

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

UPDATE


好的,我会尽快描述我想要的东西。

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

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

c++ windows validation certificate executable
3个回答
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的文件。如果你更喜欢低级按摩API,你可以使用hMsg,如果有一些dwContentType(至少CERT_QUERY_CONTENT_PKCS7_SIGNEDCERT_QUERY_CONTENT_PKCS7_UNSIGNEDCERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED),它将另外设置。

要验证文件的签名,我建议您使用CertGetCertificateChainCertVerifyCertificateChainPolicy来验证证书通常是有效的,但它(或其所有父节点)对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_OBJIDC:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat(“1.3.6.1.4.1.311.2.1.12”)属性(参见函数GetProgAndPublisherInfo),您将知道

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

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

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

所以你应该只使用.cat文件的签名者,因为没有其他explorer.exe的签名者。


4
投票

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

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


1
投票

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

我的建议是在CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED的第三个参数中尝试CERT_QUERY_CONTENT_FLAG_ALL而不是CryptQueryObject()

© www.soinside.com 2019 - 2024. All rights reserved.