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

发布于 2024-12-02 02:37:52 字数 447 浏览 5 评论 0 原文

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

更新


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

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

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

I want to validate certificates of signed executable images (by validation, I mean to tell if the signature comes from MS/Adobe/Oracle etc.). Does windows provides api for this task? How should I do that, no idea. Any help would be appreciated.
I'm using Windows and C++. I want to validate native executable images, not .NET assemblies or Java jar files.

UPDATE


Ok, I'll try to describe what I want shortly.

1) Validate PE certificate. Is the signature valid or not. It should work when signature is embedded in PE and when the signature is in security catalog. (I found this on sysinternals forum and works fine, so I don't need this one anymore).

2) Tell who's the signer/publisher of the file. I know it can be achieved through CryptQueryObject (I found a working example, though it doesn't work with security catalogs), but don't know how to use it with security catalog files.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

待天淡蓝洁白时 2024-12-09 02:37:52

有许多 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);

dwContentTypeCryptQueryObject设置将获得有关文件szFileName类型的基本信息。对于您需要的大多数情况,pvContext 将为 PCCERT_CONTEXT,但如果满足以下条件,它也可以是 PCCRL_CONTEXTPCCTL_CONTEXT您使用 .ctl 或 .crl 文件作为输入。您将收到 hStore,其中包含文件 szFileName 中的所有证书。因此,就 pvContexthStore 而言,您可以使用 CryptoAPI 检查包含的文件。如果你更喜欢
低级按摩 API,您可以使用 hMsg ,在某些 dwContentType 的情况下将另外设置(至少对于 CERT_QUERY_CONTENT_PKCS7_SIGNED CERT_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 时间戳链策略是否有效。

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

如果您使用来自 sysinternal 的代码对于签名验证,您应该只搜索行

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

The statements sill set the fields of the InfoStruct 以防该文件是系统 Windows 文件,其签名针对某些 .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”)属性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"

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

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 没有其他签名者。

There are many API and approaches how you can get and verify the signature of the executable and how you can get other additional information which you need. The problem is which level you choose (high level like WinVerifyTrust)

The easiest first API which can be used to get cryptography context from the CAT or EXE file is CryptQueryObject function. The code example from the KB323809 could get you the main idea how to decode information what you need. the main difference if you work with CAT files is that you should modify the some parameters of CryptQueryObject. I recommend you just to use CERT_QUERY_CONTENT_FLAG_ALL and CERT_QUERY_FORMAT_FLAG_ALL and CryptQueryObject will do all what you needs internally:

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);

The value dwContentType set by the CryptQueryObject will get you the base information about the type of the file szFileName. The pvContext will be PCCERT_CONTEXT for the most cases which you need, but it can be also PCCRL_CONTEXT or PCCTL_CONTEXT if you use .ctl or .crl file as the input. You will receive the hStore filled with all certificates from the file szFileName. So with respect of pvContext and hStore you can examine the file contain with CryptoAPI. If you do prefer
low-level massages API you can use hMsg which will be additionally set in case of some dwContentType (at least for for CERT_QUERY_CONTENT_PKCS7_SIGNED, CERT_QUERY_CONTENT_PKCS7_UNSIGNED, CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED).

To verify the signature of the file I would recommend you to use CertGetCertificateChain and CertVerifyCertificateChainPolicy to verify not only that the certificate is valid in general, but that it (or all its parents) is valid for authenticode (szOID_PKIX_KP_CODE_SIGNING). CertGetCertificateChain can be used for different revocation scenarios. You should do two separate calls with CERT_CHAIN_POLICY_AUTHENTICODE and CERT_CHAIN_POLICY_AUTHENTICODE_TS to verify that both Authenticode chain policy and Authenticode Time Stamp chain policy are valid.

UPDATED: I reread your current question (the Updated part). Your current problem is how to get the signer/publisher of the file. So I answer only on the question.

If you use the code from sysinternal for the signature verification you should just search for the line

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

The statement sill set the fields of the InfoStruct in case that that file is system windows file which signature is verified with respect of some .cat file. The field InfoStruct.wszCatalogFile will get you the name of the .cat file.

For example on my Windows 7 if I try to verify the digital signature of the C:\Windows\explorer.exe file, the .cat where its hash could be found is C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat.

If you would use code from KB323809 with described above parameters of CryptQueryObject you will decode the SPC_SP_OPUS_INFO_OBJID ("1.3.6.1.4.1.311.2.1.12") attribute of the C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat (see the function GetProgAndPublisherInfo) and you will know

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

So no special publisher information are included for the file. If you examine the signer of the the catalog you will find out that:

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

So you should use just the signer of the .cat file, because there are no other signer of explorer.exe.

久随 2024-12-09 02:37:52

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

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

The WinVerifyTrust function performs a trust verification action on a specified object. The function passes the inquiry to a trust provider that supports the action identifier, if one exists.

For certificate verification, use the CertGetCertificateChain and CertVerifyCertificateChainPolicy functions.

风轻花落早 2024-12-09 02:37:52

@达维塔
我仔细阅读了上面的问题并尝试解决它。

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

@Davita
I read the above problem thoroughly and tried to solve it.

My suggestion is to try CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED instead of CERT_QUERY_CONTENT_FLAG_ALL in the third parameter of CryptQueryObject()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文