从可执行文件读取多个签名 [英] Reading multiple signatures from executable file
问题描述
我正在尝试编写从DLL或EXE读取签名(证书)的代码.大多数DLL或EXE只有一个签名,我的代码正确读取了与此签名关联的所有证书.更具体地说,它读取签名证书,它是颁发者(不是root),对证书进行签名(带有时间戳)和它的颁发者(不是root).我在C ++和C#中有2个示例程序,它们都返回相同的证书.这是C#代码,C ++长100倍:)
I am trying to write code that reads signatures (certificates) from DLLs or and EXEs. Most DLLs or EXEs have only one signature, and my code reads all certificates associated with this signature correctly. More specifically it reads signing cert, it's issuer (not root), countersigning cert (with timestamp) and its issuer (not root). I have 2 sample programs in C++ and C#, they both return the same certs. This is C# code, C++ is 100 times longer :)
static void Main(string[] args)
{
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import(args[0]);
}
但是有些DLL具有2个签名,如文件属性/数字签名所示,例如C:\ Program Files(x86)\ Microsoft SQL Server \ 80 \ Tools \ Binn \ msvcr71.dll:
But there are DLLs that have 2 signatures, as shown in file properties / Digital Signatures, for example C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn\msvcr71.dll:
对于此DLL,我的代码仅读取与第一个签名关联的证书.
For this DLL my code reads only certificates associated with first signature.
我也尝试使用signtool,它返回与我的代码相同的信息:第一个证书(带有路径)和加签名(带有路径).但还要注意最后的错误.
I also tried to use signtool, and it returns the same info as my code: first cert (with it's path), and countersignature (with its path). But also note error at the end.
C:\Windows>signtool verify /d /v "C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn\msvcr71.dll"
Verifying: C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn\msvcr71.dll
Signature Index: 0 (Primary Signature)
Hash of file (sha1): 33BBCCF6326276B413A1ECED1BF7842A6D1DDA07
Signing Certificate Chain:
Issued to: Microsoft Root Certificate Authority
Issued by: Microsoft Root Certificate Authority
Expires: Sun May 09 19:28:13 2021
SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072
Issued to: Microsoft Code Signing PCA
Issued by: Microsoft Root Certificate Authority
Expires: Wed Jan 25 19:32:32 2017
SHA1 hash: FDD1314ED3268A95E198603BA8316FA63CBCD82D
Issued to: Microsoft Corporation
Issued by: Microsoft Code Signing PCA
Expires: Fri Feb 01 18:49:17 2013
SHA1 hash: 8849D1C0F147A3C8327B4038783AEC3E06C76F5B
The signature is timestamped: Sat Feb 11 14:03:12 2012
Timestamp Verified by:
Issued to: Microsoft Root Certificate Authority
Issued by: Microsoft Root Certificate Authority
Expires: Sun May 09 19:28:13 2021
SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072
Issued to: Microsoft Time-Stamp PCA
Issued by: Microsoft Root Certificate Authority
Expires: Sat Apr 03 09:03:09 2021
SHA1 hash: 375FCB825C3DC3752A02E34EB70993B4997191EF
Issued to: Microsoft Time-Stamp Service
Issued by: Microsoft Time-Stamp PCA
Expires: Thu Oct 25 16:42:17 2012
SHA1 hash: FC33104FAE31FB538749D5F2D17FA0ECB819EAE5
SignTool Error: The signing certificate is not valid for the requested usage.
This error sometimes means that you are using the wrong verification
policy. Consider using the /pa option.
Number of files successfully Verified: 0
Number of warnings: 0
Number of errors: 1
我有2个问题: -第二次签名的目的是什么 -阅读方式(到目前为止,只有Windows资源管理器文件属性对话框可以显示它).
I have 2 questions: - what is the purpose of second signature - how to read it (so far only windows explorer file property dialog can show it).
谢谢!
推荐答案
After a lot of digging and trying different things I found that function WinVerifyTrust can read multiple embedded certificates. Disregard the function name, it can be used for many things, it's a universal function.
WinVerifyTrust 采用结构 WINTRUST_DATA
作为其输入/输出参数之一. Docs说它是IN
,但它也用于返回信息.
WinVerifyTrust takes struct WINTRUST_DATA
as one of its in/out parameters. Docs says it's IN
, but it is also used to return back information.
WINTRUST_DATA
具有字段pSignatureSettings
,它是指向另一个结构
WINTRUST_DATA
has field pSignatureSettings
, which is a pointer to another struct, WINTRUST_SIGNATURE_SETTINGS
. This stuct has field dwFlags
that controls what info will be returned by WinVerifyTrust.
首先,使用WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_GET_SECONDARY_SIG_COUNT
调用 WinVerifyTrust 以获取辅助签名的数量,该数量在字段WINTRUST_SIGNATURE_SETTINGS::cSecondarySigs
中返回.请注意,如果文件具有2个签名,则cSecondarySigs
将为1.
First you call WinVerifyTrust with WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_GET_SECONDARY_SIG_COUNT
to get back the number of secondary signatures, which is returned in the field WINTRUST_SIGNATURE_SETTINGS::cSecondarySigs
. Note that if your file has 2 signatures, cSecondarySigs
will be 1.
然后在循环for (int i = 0; i <= cSecondarySigs; i++)
中,使用WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_VERIFY_SPECIFIC
和WINTRUST_SIGNATURE_SETTINGS::dwIndex = i
调用 WinVerifyTrust .
Then in the loop for (int i = 0; i <= cSecondarySigs; i++)
you call WinVerifyTrust with WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_VERIFY_SPECIFIC
and WINTRUST_SIGNATURE_SETTINGS::dwIndex = i
.
在每次 WinVerifyTrust 调用之后,您可以通过以下调用顺序从WINTRUST_DATA::hWVTStateData
获取证书信息(包括签名):
After each WinVerifyTrust call you can get certificate info (including countersignatures) from WINTRUST_DATA::hWVTStateData
by this call sequence:
WTHelperProvDataFromStateData(hWVTStateData);
WTHelperGetProvSignerFromChain(...);
WTHelperGetProvCertFromChain(...);
我没有深入研究.NET API,但似乎它只能读取第一个签名.请注意,Windows 8中添加了WINTRUST_SIGNATURE_SETTINGS
,它似乎是读取多个签名的关键,因此,在较旧的操作系统上,您至少将无法使用MS API来读取它.
I did not dig much into .NET API, but it seems that it can read only first signature. Note that WINTRUST_SIGNATURE_SETTINGS
, which seems to be the key to read multiple signatures, was added in Windows 8, so on older OSs you will not be able to read it, at least not with MS API.
这篇关于从可执行文件读取多个签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!