[
][png.HerpaderpIcon]
进程 Herpaderping 是一种通过在镜像映射后修改磁盘上内容来模糊进程意图的方法。这会导致安全产品和操作系统本身出现奇怪的行为。
![][png.mimioogle]
![][gif.SurivDemo]
通常,安全产品通过在内核中注册回调函数([PsSetCreateProcessNotifyRoutineEx][msdn.PsSetCreateProcessNotifyRoutineEx])来对进程创建采取行动。此时,安全产品可能会检查用于映射可执行文件的文件,并确定是否允许执行该进程。这个内核回调是在初始线程插入时调用的,而不是在进程对象创建时。
正因为如此,攻击者可以创建并映射一个进程,修改文件的内容,然后创建初始线程。在创建回调时进行检查的产品将看到修改后的内容。此外,一些产品使用写入时扫描的方法,即监控文件写入。这里一个常见的优化是记录文件已被写入,并将实际检查推迟到 [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] 发生时(例如文件句柄关闭)。因此,采用 写入 -> 映射 -> 修改 -> 执行 -> 关闭 工作流的攻击者将绕开仅依赖在 [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] 时进行检查的写入时扫描。
为了滥用这种约定,我们首先将一个二进制文件写入磁盘上的目标文件。然后,我们映射目标文件的镜像,并将其提供给操作系统用于进程创建。操作系统友好地为我们映射了原始二进制文件。利用现有的文件句柄,并且在创建初始线程之前,我们修改目标文件的内容,以隐藏或伪造支撑镜像的文件。稍后,我们创建初始线程以开始执行原始二进制文件。最后,我们将关闭目标文件句柄。让我们一步步来:
NtCreateProcessEx)。NtCreateThreadEx)。
![][svg.StateDiagram]
@startuml
hide empty description
[*] --> CreateFile
CreateFile --> FileHandle
FileHandle --> Write
FileHandle --> NtCreateSection
Write -[hidden]-> NtCreateSection
NtCreateSection --> SectionHandle
SectionHandle --> NtCreateProcessEx
FileHandle --> Modify
NtCreateProcessEx -[hidden]-> Modify
NtCreateProcessEx --> NtCreateThreadEx
Modify -[hidden]-> NtCreateThreadEx
NtCreateThreadEx --> [*]
FileHandle --> CloseFile
NtCreateThreadEx -[hidden]-> CloseFile
NtCreateThreadEx --> PspCallProcessNotifyRoutines
PspCallProcessNotifyRoutines -[hidden]-> [*]
CloseFile --> IRP_MJ_CLEANUP
IRP_MJ_CLEANUP -[hidden]-> [*]
PspCallProcessNotifyRoutines --> Inspect
PspCallProcessNotifyRoutines -[hidden]-> CloseFile
IRP_MJ_CLEANUP --> Inspect
Inspect -[hidden]-> [*]
CreateFile : 创建目标文件,保持句柄打开。
Write : 将源负载写入目标文件。
Modify : 混淆磁盘上的文件。
NtCreateSection : 使用文件句柄创建节。
NtCreateProcessEx : 进程的镜像节被映射并缓存在文件对象中。
NtCreateThreadEx : 使用缓存的节。
NtCreateThreadEx : 进程通知例程在内核中触发。
Inspect : 磁盘上的内容与执行的内容不匹配。
Inspect : 此时对文件的检查将导致错误的归属。
@enduml
你将在下面的演示中看到,CMD.exe 被用作执行目标。第一次运行时,使用一个模式覆盖磁盘上的字节。第二次运行时,将 CMD.exe 覆盖为 ProcessHacker.exe。Herpaderping 工具尽量将二进制文件修复得与 ProcessHacker.exe 接近,甚至保留了原始签名。请注意同一二进制文件的多次执行,以及用户看到的进程与磁盘上文件内容的差异。
![][gif.ProcessHerpaderp]
![][png.procmon]
我们已经观察到了这种行为,其中一些可能令人惊讶。让我们尝试解释这种行为。
[技术深入探讨][md.DivingDeeper]
在设计保护 Windows 平台的产品时,这个领域的许多工程师(包括我自己)都会陷入关于操作系统如何处理数据的先入为主的观念。在这种场景下,一些人可能期望当进程创建时,磁盘上的文件保持“锁定”状态。你不能删除该文件。你不能写入它。但你可以重命名它。在这里我们可以看到,在适当条件下,你实际上可以写入它。请对你的假设保持警惕,始终质疑它们,并进行研究。
这项研究的动机源于发现如何在文件被写入时进行分析。基于先前研究进程挖空和 Doppelganging 的经验,我推测这可能实现。目标是提供更好的安全性。不先了解如何打破旧锁,就无法创建更好的锁。
Herpaderping 与 挖空 和 Doppelganging 类似,但有一些关键区别:
进程挖空涉及在执行开始前修改映射的节,抽象地看,流程是:映射 -> 修改节 -> 执行。这种工作流导致被挖空进程的预期执行流偏离到非预期代码。Doppelganging 可以被视为挖空的一种形式。然而,我认为挖空更接近注入,因为挖空通常涉及显式写入已经映射的代码。这与 Herpaderping 不同,Herpaderping 没有修改任何节。
进程 Doppelganging 更接近 Herpaderping。Doppelganging 滥用事务文件操作,通常涉及以下步骤:事务 -> 写入 -> 映射 -> 回滚 -> 执行。在这种工作流中,操作系统会创建镜像节并处理事务,因此缓存的镜像节最终成为你写入事务的内容。操作系统已经修补了这种技术。好吧,他们修补了它导致的崩溃。也许他们认为这是事务的“合法”使用。幸运的是,Windows Defender 确实能检测到 Doppelganging 技术。Doppelganging 与 Herpaderping 的不同之处在于,Herpaderping 不依赖事务文件操作。而 Defender 无法检测到 Herpaderping。
作为参考,通用的技术步骤如下:
| 类型 | 技术 |
|---|---|
| 挖空 | 映射 -> 修改节 -> 执行 |
| Doppelganging | 事务 -> 写入 -> 映射 -> 回滚 -> 执行 |
| Herpaderping | 写入 -> 映射 -> 修改 -> 执行 -> 关闭 |
我们可以在这里看到区别。虽然 Herpaderping 可以说比 Doppelganging 噪音更大(恶意数据确实会写盘),但我们已经看到安全产品仍然无法检测 Herpaderping。
这里没有明确的修复方案。在文件仍有写权限时,阻止镜像节被映射/缓存似乎是合理的,这应该能堵住漏洞。然而,这未必是一个实用的解决方案。
另一个选择可能是将对文件的修改刷新到缓存的镜像节(如果还没有映射到进程)。但是,由于映射到新进程发生在 NtCreateProcess,这可能不是一个可行的解决方案。
从检测的角度来看,没有很好的方法识别实际被映射的比特。在 [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] 时进行检查,或在通过 [PsSetCreateProcessNotifyRoutineEx][msdn.PsSetCreateProcessNotifyRoutineEx] 注册的回调中进行检查,都会导致错误的归属,因为磁盘上的比特已经被更改。你必须从已创建的节中重建文件。值得指出的是,Windows 10 中有一个新的回调,你可以注册 [PsSetCreateProcessNotifyRoutineEx2][msdn.PsSetCreateProcessNotifyRoutineEx2],但这同样存在之前回调的问题:它是在初始线程执行时调用的,而不是在进程对象创建时。微软确实添加了 [PsSetCreateThreadNotifyRoutineEx][msdn.PsSetCreateThreadNotifyRoutineEx],如果使用 [PsCreateThreadNotifyNonSystem][msdn.PSCREATETHREADNOTIFYTYPE] 注册,它会在初始线程插入时被调用,而不是在即将开始执行时(正如旧回调那样)。扩展 [PSCREATEPROCESSNOTIFYTYPE][msdn.PSCREATEPROCESSNOTIFYTYPE] 在进程对象创建时被调用也无济于事,我们在 深入探讨 部分已经看到,镜像节对象是在 [NtCreateSection][msdn.NtCreateSection] 调用时缓存的,而不是 NtCreateProcess。
我们无法轻易识别已经执行的内容。我们只能尝试检测攻击者的利用行为,我将把行为指标的发现留给读者作为练习。
以下是截至(2020年8月31日)经过测试的产品和 Windows 操作系统列表。测试使用已知的恶意二进制文件进行。
| 操作系统 | 版本 | 受影响 |
|---|---|---|
| Windows 7 Enterprise x86 | 6.1.7601 | 是 |
| Windows 10 Pro x64 | 10.0.18363.900 | 是 |
| Windows 10 Pro Insider Preview x64 | 10.0.20170.1000 | 是 |
| Windows 10 Pro Insider Preview x64 | 10.0.20201.1000 | 是 |
| 安全产品 | 版本 | 受影响 |
|---|---|---|
| Windows Defender AntiMalware Client | 4.18.2006.10 | 是 |
| Windows Defender Engine | 1.1.17200.2 | 是 |
| Windows Defender Antivirus | 1.319.1127.0 | 是 |
| Windows Defender Antispyware | 1.319.1127.0 | 是 |
| Windows Defender AntiMalware Client | 4.18.2007.6 | 是 |
| Windows Defender Engine | 1.1.17300.2 | 是 |
| Windows Defender Antivirus | 1.319.1676.0 | 是 |
| Windows Defender Antispyware | 1.319.1676.0 | 是 |
| Windows Defender AntiMalware Client | 4.18.2007.8 | 是 |
| Windows Defender Engine | 1.1.17400.5 | 是 |
| Windows Defender Antivirus | 1.323.267.0 | 是 |
| Windows Defender Antispyware | 1.323.267.0 | 是 |
此漏洞已于 2020年7月17日 向 Microsoft 安全响应中心 (MSRC) 披露,MSRC 于 2020年7月22日 创建了案例。MSRC 于 2020年8月25日 结束调查,并认定发现有效,但未达到立即修复的标准。目前他们的案例已关闭,没有解决方案,并标记为未来审查,没有时间表。
我们对此漏洞的严重性持不同意见;这已于 2020年8月27日 传达给 MSRC。