验证PE文件的签名

4
我正在尝试使用OpenSSL(或实际上是Python,但似乎Python在证书处理方面表现不佳)验证PE文件的证书/签名。
我已根据此处描述从PE文件中提取了DER PKCS7证书: http://blog.didierstevens.com/2008/01/11/the-case-of-the-missing-digital-signatures-tab/ 并且我创建了一个修改过的PE文件版本,其中不包括校验和和签名数据,如此处描述的那样: http://www.mail-archive.com/cryptography@c2.net/msg04202.html 修改后文件的sha1sum与证书中的sha1sum相同。
我尝试使用以下命令使用openssl验证未签名的修改后PE文件: openssl smime -verify -in signature.der -content modified_executable.exe -inform DER -binary 但是我只得到

验证失败 140415508248232:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:pk7_smime.c:342:Verify error:unsupported certificate purpose

如果我在命令中添加 -noverify,我会得到以下结果:

验证失败 140595583981224:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:pk7_doit.c:1097: 140595583981224:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:pk7_smime.c:410:

我错过了什么?


还可以参考使用OpenSSL API验证Authenticode签名的可执行文件和DLL,但它在实现细节方面比较简略。 - jww
需要使用openssl CLI来完成此操作,因为执行此操作的系统是用Python编写的,我无法轻松地从那里调用openssl C API函数。 - espenfjo
我已经大幅更新了我的答案。如果它对你有用,请投赞成票。 - guest
似乎Python在证书处理方面表现不佳 - M2Crypto在证书处理方面有相当好的支持,并提供PKCS#7验证功能。自从提交了03eb29d10之后,您甚至可以设置自定义验证回调以忽略“不支持的证书目的”错误。 - Konstantin Shemyak
4个回答

2
假设:以下操作在带有OpenSSL 0.9.8e的Cygwin上完成。
对于“不支持的证书用途”,直接签名者可能没有S/MIME用途。
引用自 OpenSSL文档
-purpose purpose 证书的预期用途。如果没有此选项,则不会进行链验证。 $ openssl x509 -purpose -in goodcert.pem -noout
证书用途:
SSL客户端:否
SSL客户端CA:否
SSL服务器:否
SSL服务器CA:否
Netscape SSL服务器:否
Netscape SSL服务器CA:否 S/MIME签名:否
S/MIME签名CA:否
S/MIME加密:否
S/MIME加密CA:否
CRL签名:否
CRL签名CA:否 任何目的:是
任何目的CA:是
关于this,我添加了开关“-purpose any”。然后我不再看到“不支持的证书目的”,但仍然遇到与你一样的摘要和签名失败。
1900:错误:21071065:PKCS7例程:PKCS7_signatureVerify:摘要失败:pk7_doit.c:948:
1900:错误:21075069:PKCS7例程:PKCS7_verify:签名失败:pk7_smime.c:312:
通过this的提示和大量研究(#1,#2),发现将输入“modified_exe”转换为-content是错误的。它应该是PKCS#7 SignedData中Sequence ContentInfo的content字段,不包括其DER标记和长度字节。
请参阅Authenticode_PE.docx以获取SignedData的声明。
(有太多细节,我认为不必包含!)

请参考下面的内容以获得更清晰的说明:
openssl asn1parse -inform der -in signature.der > signature.txt
head signature.txt -n30
    0:d=0  hl=4 l=5464 cons: SEQUENCE          
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l=5449 cons: cont [ 0 ]        
   19:d=2  hl=4 l=5445 cons: SEQUENCE          //SignedData
   23:d=3  hl=2 l=   1 prim: INTEGER           :01 //Version
   26:d=3  hl=2 l=  11 cons: SET               //DigestAlgorithmIdentifiers
   28:d=4  hl=2 l=   9 cons: SEQUENCE          
   30:d=5  hl=2 l=   5 prim: OBJECT            :sha1
   37:d=5  hl=2 l=   0 prim: NULL              
   39:d=3  hl=2 l= 104 cons: SEQUENCE          //ContentInfo
   41:d=4  hl=2 l=  10 prim: OBJECT            :1.3.6.1.4.1.311.2.1.4 //ContentType
   53:d=4  hl=2 l=  90 cons: cont [ 0 ]        
   55:d=5  hl=2 l=  88 cons: SEQUENCE          //SpcIndirectDataContent (exclude this tag and length bytes)
   57:d=6  hl=2 l=  51 cons: SEQUENCE          //SpcAttributeTypeAndOptionalValue
   59:d=7  hl=2 l=  10 prim: OBJECT            :1.3.6.1.4.1.311.2.1.15 //ObjectID
   71:d=7  hl=2 l=  37 cons: SEQUENCE          
   73:d=8  hl=2 l=   1 prim: BIT STRING        
   76:d=8  hl=2 l=  32 cons: cont [ 0 ]        
   78:d=9  hl=2 l=  30 cons: cont [ 2 ]        
   80:d=10 hl=2 l=  28 prim: cont [ 0 ]        
  110:d=6  hl=2 l=  33 cons: SEQUENCE          //DigestInfo
  112:d=7  hl=2 l=   9 cons: SEQUENCE          //AlgorithmIdentifier
  114:d=8  hl=2 l=   5 prim: OBJECT            :sha1 //ObjectID
  121:d=8  hl=2 l=   0 prim: NULL              
  123:d=7  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:<hash of modified_exe> //digest OCTETSTRING
  145:d=3  hl=4 l=4774 cons: cont [ 0 ]        
  149:d=4  hl=4 l=1332 cons: SEQUENCE          
  153:d=5  hl=4 l= 796 cons: SEQUENCE          
  157:d=6  hl=2 l=   3 cons: cont [ 0 ]        
  159:d=7  hl=2 l=   1 prim: INTEGER           :02

从偏移量57到144的字节流是-content!的正确输入。
确切的偏移量取决于您的文件。
作为一个粗略的指导,"1.3.6.1.4.1.311.2.1.15"之前的2行是"SpcIndirectDataContent",在这一行注意55+2+88-1=144。下一行从57开始。

最终命令如下:

openssl smime -verify -inform DER -in signature.der -binary -content signedData -CAfile myCA.crt -purpose any -out tmp


1

验证失败 140415508248232:错误:21075075:PKCS7程序:PKCS7_verify:证书验证错误:pk7_smime.c:342:验证错误:不支持的证书目的

正如@guest指出的那样,OpenSSL在验证smime(或cms)时有一个“特性”:它会像传递了-purpose smimesign一样运行。详情请参见{{link1:此处}}。

如果您的签名证书与OpenSSL的smimesign“目的”(请参见man x509,第CERTIFICATE EXTENSIONS节列出的“目的”列表)不兼容,那么您必须使用-purpose any禁用扩展检查(并使用其他函数进行检查,如果您的策略需要)。

如果我将-noverify添加到命令中

您可能不想这样做。此选项会禁用对签名者证书的任何检查。


0
修改文件的哈希值与提取的证书中的哈希值相同。
我的错。我漏掉了那部分。
这是你在pk7_smime.c中失败的地方。就是这行代码:i = X509_verify_cert。
i = X509_verify_cert(&cert_ctx);
if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx);
X509_STORE_CTX_cleanup(&cert_ctx);
if (i <= 0) {
    PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CERTIFICATE_VERIFY_ERROR);
    ERR_add_error_data(2, "Verify error:",
        X509_verify_cert_error_string(j));
    sk_X509_free(signers);
    return 0;
}

X509_verify_cert位于<openssl dir>/crypto/x509/x509_vfy.c的第150行左右。这是一个相当大的函数(约250行),因此您可能需要逐步了解它。

在您浏览该函数之前,您可以尝试将-signer选项添加到openssl smime函数中。这可能是一个简单的修复方法。请参阅OpenSSL文档simime(3)

我不知道在哪里获取签名证书,因为它不在我面前,而搜索“Microsoft Code Signing CA”会产生太多噪音。转储最终实体证书,找到发行者,然后搜索发行者的名称。


签名者证书可能是文件中签名条目的一部分。对于dropbox.exe,它具有以下证书:http://pastebin.com/wYPndWb9 - espenfjo
发布者:/C=US/O=Thawte,Inc./CN=Thawte Code Signing CA - G2。但它未在Thawte根证书上提供下载。一个名为TBS Internet的公司在http://www.tbs-certificates.co.uk/FAQ/en/577.html上发布了证书。 - jww
但它在文件中。主题:/ C = US / O = Thawte,Inc. / CN = Thawte代码签名CA-G2“发行人:/ C = US / O =thawte,Inc. / OU =认证服务部门/OU =(c)2006 thawte,Inc.-仅供授权使用/CN = thawte Primary Root CA”,一直到Western Cape。 - espenfjo
也许你可以尝试使用cms(1)-CAfile选项。在这种情况下,我会尝试保存Thawte根证书并明确提供给openssl cms -verify。很抱歉我不能提供更多帮助。 - jww

0
我已经创建了一个修改过的PE文件版本,没有校验和签名数据,就像这里描述的一样:http://www.mail-archive.com/cryptography@c2.net/msg04202.html 为什么不直接使用微软发布的格式呢?没有必要采用逆向工程。
我漏掉了什么?
PE/PE+可执行文件的部分文件被签名,而不是整个文件。在计算数据散列时,您必须从OptionalHeader中省略校验和,从Data Directory中省略证书表,以及从Attribute Certificate Table部分中省略。
以下有两个你可能想要了解的参考资料: 需要省略的部分在Windows Authenticode Portable Executable Signature Format, 第6页中显示。以下是其复制内容。

enter image description here


如果您需要编程方式解析PE文件格式的帮助,请参阅Matt Pietrek在MSDN杂志上发表的深入了解Win32可移植可执行文件格式

正如我在问题中所写的,我已经剥离了未签名的部分,并且修改后文件的哈希值与提取的证书中的哈希值相同。 - espenfjo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接