有许多API和方法可以获取和验证可执行文件的签名,并获得其他所需的附加信息。问题在于选择哪个级别(例如高级别如 WinVerifyTrust
)。
从CAT或EXE文件中获取密码学上下文的最简单的API是 CryptQueryObject 函数。来自KB323809的代码示例可以帮助你了解如何解码所需的信息。如果您使用的是CAT文件,则应修改一些CryptQueryObject的参数。我建议您只使用 CERT_QUERY_CONTENT_FLAG_ALL
、CERT_QUERY_FORMAT_FLAG_ALL
,并且 CryptQueryObject
会在内部完成所有需要的工作:
BOOL bIsSuccess;
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PVOID pvContext = NULL;
...
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_CONTEXT
或
PCCTL_CONTEXT
。您将收到填充有来自文件
szFileName
中所有证书的
hStore
。因此,关于
pvContext
和
hStore
,您可以使用CryptoAPI检查文件内容。如果您喜欢低级别的消息API,则可以使用
hMsg
(至少对于一些
dwContentType
,例如
CERT_QUERY_CONTENT_PKCS7_SIGNED
,
CERT_QUERY_CONTENT_PKCS7_UNSIGNED
,
CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
)。
要验证文件的签名,我建议您使用CertGetCertificateChain和CertVerifyCertificateChainPolicy进行验证,以验证证书不仅在一般情况下有效,而且(或其所有父项)对于authenticode有效(szOID_PKIX_KP_CODE_SIGNING
)。 CertGetCertificateChain可以用于不同的吊销场景。您应该使用CERT_CHAIN_POLICY_AUTHENTICODE
和CERT_CHAIN_POLICY_AUTHENTICODE_TS
进行两个单独的调用,以验证Authenticode链策略和Authenticode Time Stamp链策略都有效。
更新:我重新阅读了您当前的问题(更新部分)。您当前的问题是如何获取文件的签名者/发布者。因此,我只回答这个问题。
如果您使用sysinternal的代码进行签名验证,只需搜索以下行:
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
该语句将设置
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
参数,您将解码位于
C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat
(请参见函数
GetProgAndPublisherInfo
)的
SPC_SP_OPUS_INFO_OBJID
("1.3.6.1.4.1.311.2.1.12")属性,然后您将知道...
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
。
CryptQueryObject
检查任何文本文件或未签名的可执行文件(如explorer.exe),则会收到CRYPT_E_NO_MATCH错误。如果您检查explorer.exe的属性,您将看不到“数字签名”选项卡,因此该文件未经签名。如果您在实现中遇到其他问题,可以向我提问。几年前,我花了很多时间编写带有代码签名的EXE、CAT等文件,所以我可能能够快速帮助您。 - OlegC:\Windows\System32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}
文件夹中,并将CAT文件中的所有哈希值包含在公共索引中。这允许通过简单调用CryptCATAdminAcquireContext、CryptCATAdminCalcHashFromFileHandle函数来获取CatFileName。 - Oleg