windows 从可执行文件中读取和验证证书

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7241453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 17:57:47  来源:igfitidea点击:

Read and validate certificate from executable

c++windowsvalidationcertificateexecutable

提问by Davita

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.

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

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

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

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.

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

回答by Oleg

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)

有许多 API 和方法如何获取和验证可执行文件的签名,以及如何获取所需的其他附加信息。问题是你选择哪个级别(高级别喜欢WinVerifyTrust

The easiest first API which can be used to get cryptography context from the CAT or EXE file is CryptQueryObjectfunction. The code example from the KB323809could 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_ALLand CERT_QUERY_FORMAT_FLAG_ALLand CryptQueryObjectwill do all what you needs internally:

可用于从 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);

The value dwContentTypeset by the CryptQueryObjectwill get you the base information about the type of the file szFileName. The pvContextwill be PCCERT_CONTEXTfor the most cases which you need, but it can be also PCCRL_CONTEXTor PCCTL_CONTEXTif you use .ctl or .crl file as the input. You will receive the hStorefilled with all certificates from the file szFileName. So with respect of pvContextand hStoreyou can examine the file contain with CryptoAPI. If you do prefer low-level massages API you can use hMsgwhich 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).

dwContentType设置的值CryptQueryObject将为您提供有关文件类型的基本信息szFileName。这pvContextPCCERT_CONTEXT适用于您需要的大多数情况,但也可以是,PCCRL_CONTEXT或者PCCTL_CONTEXT如果您使用 .ctl 或 .crl 文件作为输入。您将收到hStore来自文件的所有证书szFileName。因此,与尊重pvContexthStore您可以检查该文件包含与CryptoAPI的。如果您确实更喜欢低级按摩 API,您可以使用hMsg它会在某些情况下额外设置dwContentType(至少对于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 CertGetCertificateChainand CertVerifyCertificateChainPolicyto 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). CertGetCertificateChaincan be used for different revocation scenarios. You should do two separate calls with CERT_CHAIN_POLICY_AUTHENTICODEand CERT_CHAIN_POLICY_AUTHENTICODE_TSto verify that both Authenticode chain policy and Authenticode Time Stamp chain policy are valid.

要验证文件的签名,我建议您使用CertGetCertificateChainCertVerifyCertificateChainPolicy来验证不仅证书一般有效,而且它(或其所有父级)对验证码(szOID_PKIX_KP_CODE_SIGNING)有效。CertGetCertificateChain可用于不同的撤销场景。您应该使用CERT_CHAIN_POLICY_AUTHENTICODECERT_CHAIN_POLICY_AUTHENTICODE_TS进行两次单独的调用,以验证 Authenticode 链策略和 Authenticode Time Stamp 链策略是否有效。

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 sysinternalfor the signature verification you should just search for the line

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

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

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

InfoStruct如果该文件是系统 Windows 文件,则该语句将设置字段,该文件是针对某些 .cat 文件验证签名的。InfoStruct.wszCatalogFile字段将为您提供 .cat 文件的名称。

For example on my Windows 7 if I try to verify the digital signature of the C:\Windows\explorer.exefile, 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.

例如,在我的 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.

If you would use code from KB323809with described above parameters of CryptQueryObjectyou 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

如果您使用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.catGetProgAndPublisherInfo

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.

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

回答by John

The WinVerifyTrustfunction 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.

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

For certificate verification, use the CertGetCertificateChain and CertVerifyCertificateChainPolicy functions.

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

回答by Raghav Guar

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

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

My suggestion is to try CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNEDinstead of CERT_QUERY_CONTENT_FLAG_ALLin the third parameter of CryptQueryObject()

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