1

[翻译]Authenticode签名对未签名代码的应用

skeep 2017-10-10 02:54 1100

Authenticode签名对未签名代码的应用

众所周知,攻击者将合法的数字证书应用于其恶意软件,这大概是为了躲避基本的签名验证程序。Petya勒索病毒便是这种情况。作为一名逆向工程师或red team的开发者,了解哪些合法的签名可以被应用到其他的未签名代码以及攻击者提供的代码的方法。这篇博客将会给出代码签名机制、二进制数字签名,以及对数字证书应用于未签名的PE文件的相关技术背景的介绍。不久,你将会在我下个月发布的研究中看到相关技术的联系。

背景

对PE文件(如exe、dll、sys等文件)进行签名是什么意思呢?一个比较简明的答案就是选择相应的PE文件,右键单击之后,查看文件属性,如果存在“数字签名”选项卡,则表示已经该文件已经被签名。当你看到文件属性中的这个“数字签名”选项卡的时候,实际上意味着该PE文件是Authenticode签名的,在这个文件中有一个二进制的数据包,其中包括一个证书和这个文件的签名哈希值(更具体点说,Authenticode哈希值就是在散列计算中去除PE头的那部分数据的哈希值)。存储Authenticode签名的格式在PE代码签名规范【见附件1】中有详细说明。

 

text

 

然而,很多本应该被签名的文件(以notepad.exe为例),事实上却并没有我们所说的“数字签名”选项卡。那这是否意味着该文件没有签名,并且微软也运行了这些未签名的代码呢?这个要视情况而定。虽然notepad.exe本身没有嵌入Authenticode签名,但实际上它通过目录签名这种方式进行过签名。Windows包含由许多目录文件组成的目录存储库,基本上只是Authenticode的散列表。然后,每个目录文件都被签名,以证明任何具有匹配哈希的文件源自目录文件的签名者(基本上都是Microsoft的程序)。因此,当Explorer UI不尝试查找目录签名时,几乎其他的所有签名验证工具都将执行目录查找。在PowerShellSysinternals Sigcheck中获取可以Authenticode签名

注:目录文件存储在%windir%\System32\CatRoot{F750E6C3-38EE-11D1-85E5-00C04FC295EE}

 

text

 

在上述屏幕截图中,SignatureType属性指示notepad.exe是目录签名(”Catalog”)。还值得注意的是IsOSBinary属性。虽然具体的实现没有文档化,但如果签名链接到几个已知的,散列的Microsoft根证书之一,则将显示“True”。有兴趣了解更多有关如何工作的人可以逆向CertVerifyCertificateChainPolicy函数【https://msdn.microsoft.com/en-us/library/windows/desktop/aa377163(v=vs.85).aspx 】。

 

Sigcheck工具使用“-i”参数,执行目录证书验证,并显示包含匹配的Authenticode哈希的目录文件路径。 “-h”参数还将计算并显示PE文件的SHA1SHA256形式的Authenticode散列(分别为PESHA1PE256):

sigcheck -q -h -i C:\Windows\System32\notepad.exe
c:\windows\system32\notepad.exe:
  Verified:       Signed
  Catalog:        C:\WINDOWS\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Microsoft-Windows-Client-Features-Package-AutoMerged-shell~31bf3856ad364e35~amd64~~10.0.15063.0.cat
  Signers:
    Microsoft Windows
      Status:         Valid
      Valid Usage:    NT5 Crypto, Code Signing
      Serial Number:  33 00 00 01 06 6E C3 25 C4 31 C9 18 0E 00 00 00 00 01 06
      Thumbprint:     AFDD80C4EBF2F61D3943F18BB566D6AA6F6E5033
      Algorithm:      1.2.840.113549.1.1.11
      Valid from:     1:39 PM 10/11/2016
      Valid to:       1:39 PM 1/11/2018
    Microsoft Windows Production PCA 2011
      Status:         Valid
      Valid Usage:    All
      Serial Number:  61 07 76 56 00 00 00 00 00 08
      Thumbprint:     580A6F4CC4E4B669B9EBDC1B2B3E087B80D0678D
      Algorithm:      1.2.840.113549.1.1.11
      Valid from:     11:41 AM 10/19/2011
      Valid to:       11:51 AM 10/19/2026
    Microsoft Root Certificate Authority 2010
                Status:         Valid
                Valid Usage:    All
                Serial Number:  28 CC 3A 25 BF BA 44 AC 44 9A
                                9B 58 6B 43 39 AA
                Thumbprint:     3B1EFD3A66EA28B16697394703A72CA340A05BD5
                Algorithm:      1.2.840.113549.1.1.11
                Valid from:     2:57 PM 6/23/2010
                Valid to:       3:04 PM 6/23/2035
    Signing date:   1:02 PM 3/18/2017
    Counter Signers:
      Microsoft Time-Stamp Service
        Status:         Valid
        Valid Usage:    Timestamp Signing
        Serial Number:  33 00 00 00 B3 39 BB D4 12 93 15 A9 FE 00 00 00 00 00 B3
        Thumbprint:     BEF9C1F4DA0F153FF0900303BE78A59ADA8ADCB9
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     10:56 AM 9/7/2016
        Valid to:       10:56 AM 9/7/2018
      Microsoft Time-Stamp PCA 2010
        Status:         Valid
        Valid Usage:    All
        Serial Number:  61 09 81 2A 00 00 00 00 00 02
        Thumbprint:     2AA752FE64C49ABE82913C463529CF10FF2F04EE
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     2:36 PM 7/1/2010
        Valid to:       2:46 PM 7/1/2025
      Microsoft Root Certificate Authority 2010
        Status:         Valid
        Valid Usage:    All
        Serial Number:  28 CC 3A 25 BF BA 44 AC 44 9A 9B 58 6B 43 39 AA
        Thumbprint:     3B1EFD3A66EA28B16697394703A72CA340A05BD5
        Algorithm:      1.2.840.113549.1.1.11
        Valid from:     2:57 PM 6/23/2010
        Valid to:       3:04 PM 6/23/2035
    Publisher:      Microsoft Windows
    Description:    Notepad
    Product:        Microsoft« Windows« Operating System
    Prod version:   10.0.15063.0
    File version:   10.0.15063.0 (WinBuild.160101.0800)
    MachineType:    64-bit
    MD5:    F60A9D3A9461F68DE0FCCEBB0C6CB31A
    SHA1:   2302BA58181F3C4E1E44A47A7D214EE9397CF2BA
    PESHA1: ACCE8ADCE9DDDE507EAE295DBB37683CA272DB9E
    PE256:  0C67E3923EDA8154A89ADCA8A6BF47DF7C07D40BB41963DEB16ACBCF2E54803E
    SHA256: C84C361B7F5DBAEAC93828E60D2B54704D3E7CA84148BAFDA632F9AD6CDC96FA
    IMP:    645E8D8B0AEA808FF16DAA70D6EE720E

理解Authenticode哈希的概念会使你比较容易的在目录文件中找到相应的条目。你也可以双击目录文件来查看其它条目。我还编写了CatalogToolshttps://github.com/mattifestation/CatalogTools 】,这是用于解析目录文件的PowerShell模块。在“hint”元数据字段说明了notepad.exe确实是相应的条目:

 

text

 

text

数字签名的二进制格式

现在你已经了解了可以对PE文件进行签名的方法(Authenticode签名目录签名),那么对签名的二进制格式有所了解也是十分必要的。无论是Authenticode签名还是目录签名,其签名都存储PKCS#7https://tools.ietf.org/html/rfc2315 】签名数据中,这种数据是一种ASN.1格式的二进制数据。 ASN.1只是一个标准,用于说明应该存储不同数据类型的二进制数据。在观察/解析数字签名的字节之前,你必须首先知道它如何存储在文件中。目录文件很简单,因为文件本身由原始的PKCS#7数据组成。 网上有在线的ASN.1解析器【https://lapo.it/asn1js/ 】解析ASN.1数据,并以直观的方式呈现出来。例如,尝试将包含notepad.exe的哈希的目录文件加载到解析器中,你将可以看到一个层次分明的数据布局的视图。 以下是解析输出的代码段:

 

text

 

ASN.1编码数据中的每个属性都以对象标识符(OID,object identifier)开头,这是一个唯一的数字序列,用于标识以下数据的类型。上述代码段中值得注意的OID如下:

  • 1.2.840.113549.1.7.2 - 这表明PKCS#7签名数据 – 后面跟着Authenticode和目录签名代码。
  • 1.3.6.1.4.1.311.12.1.1 - 这表明后面会跟着目录文件散列数据

建议想要深入理解的读者花点时间探索数字签名中包含的所有字段。然而,图中的字段都不在本博客的讨论范围之内。这里【https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography 】列出了附加的加密/签名相关OID

嵌入式PE Authenticode签名检索

具有嵌入式Authenticode签名的PE文件中的数字签名数据附加在文件末尾(这里说的是格式正常的的PE文件)。操作系统显然需要一些信息来检索嵌入式签名的确切偏移量和大小。 给大家介绍一款我最喜欢PE解析/编辑工具CFF Explorerhttp://www.ntcore.com/exsuite.php 】,下面是使用CFF Explorer来解析kernel32.dll

 

图 6

 

嵌入式数字签名的偏移量和大小存储在PE的可选头内的“security directory”数组中的“data directories”偏移量中。 数据目录包含PE文件中的各种结构的偏移量和大小——导出表,导入表,重定位表等。数据目录中的所有偏移量都是相对虚拟地址(RVA),这意味着它们是加载时PE相应部分的在内存中的偏移量。只有一个例外——安全目录表将其偏移量存储为文件偏移量,这是因为Windows加载程序实际上并没有在内存中加载安全目录表的内容。

 

安全目录表的二进制数据是WIN_CERTIFICATE结构【https://msdn.microsoft.com/en-us/library/windows/desktop/dn582059(v=vs.85).aspx 】的。下面是kernel32.dll010Editor中解析的结果【https://gist.github.com/mattifestation/d10f91859bd0dffd4a539945ae02eccb, 相应文件见附件2 】(文件偏移是0x000A9600):

 

图 7

 

PE文件的Authenticode签名应始终具有WIN_CERT_TYPE_PKCS_SIGNED_DATAwRevision。后续的字节数组是与目录文件内容相同的PKCS#7以及ASN.1编码签名数据。唯一的区别是你应该找不到1.3.6.1.4.1.311.12.1.1这样的OID,因为这表明存在的目录散列签名。

 

在网上在线的ASN.1解码器解析出的原始bCertificate数据证实我们正在处理正确的PKCS#7的数据:

 

图 8

数字签名对未签名PE文件的应用

现在你已经了解了数字签名的二进制格式和存储位置的基本概念,接下来可以开始将现有签名应用于未签名的代码。

嵌入式签名认证的应用

将嵌入的Authenticode签名从签名文件应用到未签名的PE文件是非常简单的。虽然这个过程可以自动化完成,这里我将用十六进制编辑器和CFF Explorer来讲解如何手动实现。

 

步骤1: 识别要窃取的Authenticode签名。在实例中,我将使用kernel32.dll中的一个签名作为演示。

 

步骤2: 识别“security directory”中的WIN_CERTIFICATE结构的偏移量和大小。

 

图 9

 

可以看到上述截图中的文件偏移量为0x000A9600,大小为0x00003A68。

 

步骤3: 在一款十六进制编辑器中打开kernel32.dll,从偏移量0xA9600处选择0x3A68字节的数据,然后复制这些数据。

 

图 10

 

步骤4:在十六进制编辑器中打开你的未签名PE(在此示例中为HelloWorld.exe),滚动到最后,粘贴从kernel32.dll复制的3A68字节的数据。 注意签名开头的文件偏移量(在我的机器环境下为0x00000E00)。粘贴完数据之后记得保存文件。

 

图 11

 

步骤5:在CFF Explorer中打开HelloWorld.exe,并更新安全目录以指向应用的数字签名:offset - 0x00000E00,size - 0x00003A68。 进行修改后保存文件。 忽略“无效”警告,这是因为CFF Explorer不将安全目录视为文件偏移量,并在尝试引用数据所在的位置时发出警告。

 

图 12

 

这就完成了所有操作。现在,签名验证实用程序将正确解析和显示签名。 唯一需要注意的是,它们将报告签名无效,因为所计算的文件的Authenticode与证书中存储的签名哈希的Authenticode不匹配。

 

图 13

 

现在,如果你想知道为什么SignerCertificate指纹符号不匹配,那么你是一个精明的读者。考虑到我们应用了相同的签名,为什么证书指纹不符合?这是因为Get-AuthenticodeSignature首先尝试对kernel32.dll进行目录文件查找。在这种情况下,它找到了kernel32.dll的目录条目,并显示目录文件的签名者的签名信息。kernel32.dll也是Authenticode签名的。 所以要验证Authenticode散列的指纹值是否相同,请临时停止CryptSvc服务,该服务负责执行目录哈希查询的服务。如此,你将看到指纹值匹配。 这表示目录哈希是使用不同的代码签名证书用于签署kernel32.dll本身的证书。

 

图 14

目录签名对PE文件的应用

实际上,CryptSvc一直在运行,并且将会执行目录查找。假设你想要注意OPSEC,并匹配用于签署目标二进制文件的相同证书。事实证明,您可以通过在WIN_CERTIFICATE结构中交换bCertificate的内容并相应地更新dwLength来将目录文件的内容实际应用于嵌入式PE签名。 可以跟着后续的实例一起操作。请注意,我们的目标(在本实例中)是将Authenticode签名应用于我们的无符号二进制文件,与用于对包含的目录文件进行签名的二进制文件相同:本实例中,证书指纹为: AFDD80C4EBF2F61D3943F18BB566D6AA6F6E5033

 

步骤1:识别包含目标二进制文件的Authenticode哈希的目录文件——kernel32.dll。 如果一个文件是Authenticode签名的,Sigcheck工具将无法解析目录文件。然而,Signtool(包括在Windows SDK中)可以做到。

 

图 15

 

步骤2:在十六进制编辑器中打开目录文件,并获取文件大小为0x000137C7

 

图 16

 

步骤3:我们将在十六进制编辑器中手动构造一个WIN_CERTIFICATE结构。我们来看看我们提供的每个成员:

  • dwLength:这是WIN_CERTIFICATE结构的总长度,即bCertificate字节加上其他字段的大小= 4(DWORD大小)+ 2(WORD大小)+ 2(WORD大小)+ 0x000137C7bCertificate —— .cat文件的文件大小)= 0x000137CF
  • wRevision:这将是0x0200来表示WIN_CERT_REVISION_2_0
  • wCertificateType:这将是0x0002来表示WIN_CERT_TYPE_PKCS_SIGNED_DATA
  • bCertificate:由目录文件的原始字节组成。

在十六进制编辑器中制作数据时,请注意数据以小端格式存储。

 

图 17

 

步骤4:复制所有WIN_ERTIFICATE的所有字节,附加到未签名的PE的末尾,并相应地更新安全目录的偏移量和大小。

 

 

现在,假设你的计算和对齐是正确的,看看与目录文件的指纹匹配情况!

 

 

 

这篇博文中提出的技术,希望可以引起一些人考虑如何检测数字签名的滥用。虽然我没有彻底研究清楚签名的启发,但我只是提出一系列问题,以期待能够激励他人开始调查和撰写检测潜在的签名异常:

  • 对于合法签名的Microsoft PE文件中PE时间戳和证书有效期之间是否存在任何相关性?攻击者提供的代码的PE时间戳偏离上述相关性吗?
  • 阅读本文后,你对一个一个具有哈希不匹配的“签名”文件的信任级别是什么级别呢?
  • 你将如何检测具有由目录文件组成的嵌入式Authenticode签名的PE文件?提示:前面提到的特定OID可能是有用的。
  • 如何在不同的系统上验证目录签名文件的签名?
  • 停止/禁用的CryptSvc服务对执行本地签名验证的安全产品有什么影响?如果发生这种情况,那么所有意图和目的的大多数系统文件将不再被签名。
  • 我看到的每一个合法的PE填充在一个0x10字节的边界。我在示例中将目录内容应用于Authenticode签名的示例不是0x10字节对齐。
  • 如何区分合法的Microsoft数字签名和所有证书属性应用于自签名证书的签名?
  • 如果在数字签名之后附加数据,该怎么办?这在过去一直被滥用。
  • 建议英特尔的专家应该在使用不同的证书调查相同的代码时,找到Authenticode哈希成为一个有趣的实验方向。VirusTotal将其提供为“Authentihash”值:即使用“sigcheck -h”计算的哈希值。如果我正在调查在VirusTotal中的一个Authentihash上有多次命中的样本的变体,我会发现这非常有趣。
上传的附件:
最新回复 (8)
10
cvcvxk 2017-10-11 22:50
2
到最后,签名不还是无效的么
2
noNumber 2017-10-11 23:11
3
能自主添加有效的数字签名就厉害了。  以前搞免杀的把别的程序上的数字签名扒过来然后PE头改一下偏移就有数字签名了,可惜是无效的,
yangya 2017-10-12 17:55
4
这样都能有效,那签名就没什么用了。
hzqst 2017-10-12 18:27
5
后面图挂了?
聖blue 2017-10-12 19:53
6
不错!!!!
sorrywyb 4天前
7
搞来搞去都是无用的
1
skeep 16小时前
8
cvcvxk 到最后,签名不还是无效的么
感觉作者这里也是提供一个思路,探究一下签名的格式与应用,文中的图都是作者的原图,翻译中我也注意到了貌似最后的Status还是不对,但是确实是修改了前面的哈希值
小艾 13小时前
9
对的  并没有什么卵用
返回