有多种类型的内核驱动程序;最先想到的是设备驱动程序,它们提供了对硬件设备的如 即插即用 接口或 过滤驱动程序 等的软体接口。这些低级系统组件有着严格的开发过程,包括对安全性的审查。然而,还有一些额外的“软件”驱动程序,它们设计为在 Ring 0 中运行,并提供特定的非硬件相关功能,如软件调试和诊断、系统分析等。如下面所示,这些驱动程序容易显著扩大攻击面。
虽然在较新版本的 Windows 中,直接加载恶意的未签名驱动程序已经不再可能(除非在启动时显式禁用驱动程序签名强制),并且内核 rootkit 被认为是过去的事了,但仍然有方法将恶意代码加载到内核中。虽然真正的漏洞和利用这些漏洞的方法受到了很多关注,但有一种更简单的方法:滥用合法的已签名驱动程序。有许多来自各种硬件和软件供应商的驱动程序,它们提供了以最小的努力完全访问内核的功能。
签名驱动程序中的漏洞通常被游戏作弊开发者利用,以绕过反作弊机制,但也已被若干APT组织和常见恶意软件利用。
本文讨论了内核驱动程序中常见的漏洞类型,提供了利用这些漏洞的恶意软件的几个案例研究,分析了我们在研究中发现的易受攻击的驱动程序示例,并概述了对这种类型的利用的有效缓解技术。虽然这个问题并不新鲜,并且关于这个主题的相关研究在2018年和2019年已经提出过 ([1], [2], [3]),但截至本文撰写时,这仍然是一个问题。
常见的驱动程序漏洞类型
虽然每个漏洞都是不同的,但类似类型的漏洞似乎在无关的内核驱动程序中反复出现。这可能部分是由于 (古老的) 驱动程序代码示例 在当时访问内核模式不受签名驱动程序限制,并且开发者没有考虑安全性(恶意软件可以简单地加载未签名的 rootkit 驱动程序)。以下部分描述了在各种硬件和软件供应商的驱动程序中最常观察到的漏洞。
MSR 读/写
模型特定寄存器(MSRs)是在1993年引入的 Pentium 80586 CPU 中的。MSR 可以被认为是 CPU(或特定核心)的“全局变量”。一些 MSR 包含有关处理器或特定 CPU 核心的各种信息,例如温度、电力等。此外,还有许多 MSR 包含对系统工作至关重要的数据,例如 IA32_LSTAR(0xC0000082)用于 SYSCALL 或 IA32_SYSENTER_EIP(0x00000176)用于 SYSENTER,它们都包含指向内核中处理 SYSCALL 或 SYSENTER 指令时 CPU 跳转的地址的指针。在较新的 Windows x64 平台上,如 Windows 10 或 11,SYSCALL 被用于 AMD 和 Intel CPU,其中 IA32_LSTAR 应指向 ntoskrnl.exe 中的 KiSystemCall64 函数。SYSCALL 执行时过渡到 Windows 内核的机制如图1所示。
图1. SYSCALL 在 x64 Windows 中的处理方式
MSR 由一个编号索引,通过特权的 RDMSR 和 WRMSR 指令访问,这些指令只能在内核模式下执行。许多商业驱动程序通过 IOCTL 机制实现了用户模式应用程序访问这些指令的功能。这通常是为了能够读取或写入一些特定的无害 MSR(如 CPU 电压、温度等),但开发者有时未添加任何额外检查来限制对关键 MSR 的访问,如图2所示。这给潜在攻击者提供了机会,例如,修补 SYSCALL/SYSENTER 入口点 MSR,这些 MSR 是指向处理任何来自用户模式的系统调用的函数的指针。
图2. AMDPowerProfiler.sys 驱动程序中的易受攻击的 MSR IOCTL 处理程序
在旧的 CPU 和系统上,覆盖系统调用指针是非常简单和强大的,在引入像 Supervisor Mode Execution Prevention (SMEP) 这样的缓解措施之前就是这样。在这些系统上,只需将指针更改为包含恶意代码的任意用户模式可执行缓冲区的地址,然后立即在同一 CPU 核心上执行系统调用指令,就足以获得内核级别的代码执行。由于现代的利用缓解措施,这种情况在较新的系统上不再适用。尽管如此,通过巧妙使用各种技术,仍然可以绕过大多数这些缓解措施,并在 Windows 10 或甚至全新的 Windows 11 系统上(截至2021年12月)实现内核级别的代码执行。
以下部分的所有缓解措施在大多数现代机器上都已到位,需要绕过这些措施才能成功进行内核模式利用。
SMEP
SMEP 是一种保护机制,于2011年在基于 Ivy Bridge 架构的 Intel 处理器中引入,并从 Windows 8.0 开始默认启用。它防止从 Ring 0 执行用户模式页面中的代码,并通过在页面表的每个虚拟内存页面上分配用户模式或内核模式的标志位来实现。如果系统尝试从内核空间执行用户模式页面中的代码,将触发 0x000000FC 错误(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY)并导致蓝屏。SMEP 可以在执行期间动态切换开关,其状态保存在每个 CPU 核心的 CR4 寄存器中(见图3)。
图3. CPU 的 CR4 寄存器标志(图片来源:维基百科)
SMEP 可以缓解滥用 MSR 读/写 IOCTL 技术,将 LSTAR MSR 更改为直接指向恶意用户模式代码的简单利用方式。也就是说,由于攻击者控制着传递到内核模式的系统调用的栈,他们可能会利用一种称为 ROP 链 的技术来操控栈。通过在栈上放置一系列返回地址,攻击者可以通过易受攻击的 IOCTL 更改 LSTAR MSR 来安排在内核模式下执行精心挑选的一组指令。将栈适当准备好后,执行系统调用指令会导致 ROP 链中的第一个“ gadget” 执行,完成后其代码会“返回”到链中的下一个 gadget,该 gadget 是栈上与其余链一起提供的。
这种 ROP 链的功能受到内核模块中可用的合适代码块(称为 gadgets)的限制。由于攻击者可以从文件系统中读取内核模块,并知道模块加载的地址,因此可以轻松查找 gadgets,如果这些 gadgets 存在,那么可以构建一个有效的 ROP 链。
为了正确初始化过渡到内核,ROP 链需要使用 SWAPGS 指令交换 GS 寄存器。在 64 位 Windows 中,GS 寄存器在用户模式下保存线程环境块(TEB)的地址,而在内核模式下保存
内核处理器控制区域(KPCR)的地址。因此,在内核中进行任何操作之前,至关重要的是这两个地址发生变化。毫不奇怪,SWAPGS 指令也是 Windows 内核 KiSystemCall64 函数中的第一条指令。
下一步是使用 WRMSR 指令恢复 LSTAR MSR 的原始值,以避免在下一次执行 SYSCALL 指令时执行 ROP 链。
此时,恶意代码在内核中正确执行,攻击者可以执行任何想要的负载。这可以是额外的 ROP gadgets,例如,通过覆盖 CR4 禁用 SMEP 或 SMAP 保护,或甚至直接调用导出的 ntoskrnl API 函数。
攻击者可以利用 MOV CR4 gadget 来覆盖 CR4,禁用 SMEP 和 SMAP,这将在下一节中讨论。他们然后可以直接执行用户模式负载。唯一的困难是预先计算一个有效的 CR4 值。虽然大多数 CR4 值可以通过运行 CPUID 指令从用户模式猜测,但不同版本的 Windows 之间可能会存在一些不一致性。
为了安全地过渡回用户模式,一旦攻击者的 ROP 链运行完,他们需要再次执行 SWAPGS 指令,然后执行 SYSRET 指令。
描述绕过 SMEP 的旧利用的方法见 [4],(2015年)。
SMAP
Supervisor Mode Access Prevention (SMAP) 是一种较新的缓解措施,引入以补充 SMEP 并进一步限制从内核到用户模式页面的访问——它既不允许读取也不允许写入。与 SMEP 一样,它的状态作为位存储在 CR4 寄存器中(见图3)。
SMAP 应该使之前描述的 ROP 链技术无效,因为包含 ROP 链的栈实际上是一个用户模式页面。启用 SMAP 的系统将会在尝试访问堆栈时立即蓝屏。
SMAP 也可以通过在 EFLAGS CPU 寄存器中设置 AC 标志来暂时禁用。这个特性也是 MSR 利用中这种缓解措施的弱点——事实证明,AC 标志可以从用户模式设置,在过渡到内核模式之前,通过使用 POPF 和 PUSHF 指令实现。这是由于控制 SYSCALL 指令执行时哪些 EFLAGS 寄存器位被清除的 SFMASK MSR。即使在最新的 Windows 11 机器上,掩码也没有设置 AC 标志位,这意味着在过渡到内核时,SMAP 可以被用户禁用。
由于 SFMASK 由另一个 MSR(0xC0000084)控制,即使 Microsoft 更改了 SFMASK 以隐式清除 AC 标志,理论上攻击者仍然可以在利用之前修补此 MSR。
值得注意的是,SMAP 仅在最近才在 Windows 10 x64 的新硬件中默认启用。
KVA Shadowing
KVA shadowing 是为应对 Meltdown CPU 漏洞而引入的软件缓解措施。其基本思路是将虚拟地址空间分为用户模式和内核模式两部分。用户模式地址空间只能访问 ntoskrnl 模块中的一个非常受限的部分,即 .KVASCODE 代码段,该段负责处理系统调用时进入和退出内核的低级操作。通过实现这些操作的“Shadow”版本,如 KiSystemCall64Shadow,它模拟了原始的 KiSystemCall64,但包含了处理 KVA shadowing 和正确切换地址空间上下文的不同之处(见图4)。其余的内核部分完全隔离,并映射到自己的地址空间中,在上下文适当切换之前,CPU 甚至不能直接访问用户模式地址空间中的内核部分。
图4. KiSystemCall64 和 KiSystemCall64Shadow 系统调用处理程序的比较 - 函数开始处可以发现一些细微差别
虽然 KVA shadowing 旨在修复 Meltdown 漏洞,但它也可能对其他类型的漏洞(包括 MSR 漏洞)造成麻烦。
禁用这种缓解措施通常有两种方法 - 一是通过注册表设置来禁用,这需要管理员权限,并且需要重启才能生效。
另一种方法是在构建 ROP 链以利用 MSR 漏洞时,攻击者尝试只在 ntoskrnl 模块的 .KVASCODE 段中查找 gadgets - 由于该段处理系统调用过渡,因此可以构建有效的 ROP 链。
类似的缓解措施也在 Linux 系统中引入,称为 Kernel Page Table Isolation (KPTI)。
物理内存读/写
能够直接读写物理内存在许多低级内核驱动程序中似乎是一个常见的特性。这通常通过将特定范围的物理内存映射到一个可以被读取或写入的虚拟内存缓冲区来实现,甚至可以传递给用户模式应用程序。实现这一点的最常见方式是能够将 DevicePhysicalMemory 部分映射到虚拟内存中,如图5所示。
图5. Passmark DirectIO64.sys 驱动程序中的物理内存映射漏洞
一个潜在的缺点是攻击者首先需要将虚拟地址转换为物理地址。实现物理内存 I/O 的驱动程序有时也提供了一个 IOCTL 以进行物理到虚拟地址的转换,但即使驱动程序没有这样的地址转换功能,仍然有许多方法可以利用这个特性。
最直接的用例是遍历所有物理内存,寻找特定的标记数据结构。比如,攻击者可能会尝试查找恶意进程的 EPROCESS 结构,并通过窃取更高权限进程的令牌或修改其权限来提升它。以下是一些策略的演示 链接1 和 链接2。
由于物理内存映射忽略了任何虚拟内存保护特性,攻击者也可以写入可执行内存页面。这使得攻击者有机会查看特定的内核模块和代码块,仔细修改它们,并且如果修补的代码可以通过系统 API 或驱动程序的 IOCTL 执行,便可以实现恶意的内核级代码执行。
虚拟内存读/写
虚拟内存访问 IOCTL 在这些驱动程序中并不像物理内存 IOCTL 那样常见,但它们有非常类似的后果。利用这些 IOCTL 更容易,因为不需要地址转换,所有从用户模式找到的虚拟内核地址都可以直接访问。一个潜在的缺点是,访问受限于目标地址的内存保护,因此不能在不首先更改保护的情况下写入只读内存页面。
因此,这种漏洞通常用于操控各种内核数据结构,以实现将恶意进程提升为 SYSTEM 权限,如窃取令牌等。
这种漏洞通常通过在内核模式下简单的指针解引用的 IOCTL 形式出现,因此使用启发式方法检测这些漏洞可能会很困难。
案例研究
当恶意软件作者需要在启用了驱动程序签名强制 (DSE) 的 Windows x64 系统上运行恶意代码时,使用易受攻击的签名内核驱动程序似乎是一个可行的选项。这种技术被称为 Bring Your Own Vulnerable Driver (BYOVD),在实际中被高调的 APT 组织和常见的恶意软件使用。
以下是一些例子。
Slingshot APT
Slingshot 是一个网络间谍平台,于2018年被 Kaspersky 揭露 [5],被认为自2012年起就已经活跃。该恶意软件的作者决定将其主要模块,称为 Cahnadr,实现为内核模式驱动程序。在较旧的 x86 系统上,驱动程序会直接由用户模式模块加载。在启用了 DSE 的较新系统上,他们决定实现一个自定义驱动程序加载器,利用以下具有 MSR 漏洞的签名内核驱动程序:Goad、SpeedFan (CVE-2007-5633)、Sandra (CVE-2010-1592) 和 ElbyCDIO (CVE-2009-0824)。该利用针对的是 Windows 8 之前的系统,因此利用方法是简单地修改 LSTAR MSR,使其指向用户模式缓冲区中的恶意负载。
值得注意的是,Kaspersky 的研究人员估计这些威胁行为者自2012年至2018年活跃,这意味着这些漏洞利用已经相当陈旧且众所周知,但这并没有使攻击者停止使用它们,因为这些易受攻击驱动程序的证书从未被撤销。
InvisiMole
2018年,ESET 研究人员发现了一个复杂的 APT 组织,他们将其命名为 InvisiMole [6]。该组织从那时起被 ESET 跟踪,2020年发布了一篇详尽的 白皮书。在该白皮书中,我们的同事报告了 InvisiMole 使用 BYOVD 技术,利用 Speedfan.sys 驱动程序中的 MSR 漏洞 (CVE-2007-5633) 来加载恶意的未签名驱动程序。虽然这个活动针对的是较旧的 x86 系统,而且使用恶意驱动程序的利用在现代角度来看是简单的,但由于没有像 SMEP 这样的缓解措施,它仍然是一个有趣的案例,展示了该恶意软件背后的团队具有很高的技术能力。
然而,在调查过程中,我们发现了 InvisiMole 的一个更新变体,使用了 BYOVD 技术。这是迄今为止我们观察到的唯一在现代 Windows 10 x64 系统上使用 MSR 漏洞的实际案例。该变体使用了先进的技术来绕过诸如 SMEP 和 SMAP 之类的缓解措施。尽管如此,利用还是被 KVA shadowing 缓解措施阻碍了,作者未能处理这个问题。巧合的是,MSR 漏洞被用于部署一个试图禁用我们的安全产品的恶意驱动程序。尽管整个攻击链更为复杂,但我们将重点关注恶意软件在主用户模式模块中利用 BYOVD 技术
和 MSR 漏洞的特定部分。
用户模式模块
InvisiMole 的作者似乎开发了一个复杂的 ROP 链利用框架,用于 MSR 漏洞利用 - 尽管样本中包含许多调试消息,我们未能将其与任何已知项目关联。这使我们相信该框架是这些恶意软件作者的原创工作,且花费了相当大的资源进行开发。该框架是一个广泛的 C++ 代码库,具有各种类。
看起来 InvisiMole 的作者不知道可以使用 PUSHF 和 POPF 指令设置 AC 标志的可能性,而选择了一个在 MiDbgCopyMemory 内核函数中找到的非常复杂的 ROP gadget,该 gadget 以特权的 STAC 指令开始,该指令专门用于设置 AC 标志(见图6)。此外,InvisiMole 在每个显式设置 AC 标志的 RFLAGS 寄存器的 gadget 后使用 IRETQ 指令,进一步稳定了利用过程。
图6. InvisiMole 用于禁用 SMAP 缓解措施的 ROP gadget
初始 gadget 直接跳转到 STAC 指令,这会通过设置 AC 标志立即禁用 SMAP。由于这个 gadget 出现在 MiDbgCopyMemory 函数中间,恶意软件仔细准备了堆栈和寄存器以安全地离开该函数。一旦 MiDbgCopyMemory 函数返回,ROP 链继续到 SWAPGS gadget [7] 以正确切换到内核模式,然后使用 WRMSR gadget 将 LSTAR MSR 设置回原始值。此时,InvisiMole 将继续执行负载,这可能是一个导出的内核函数或加载的恶意驱动程序的入口点。
驱动加载器
驱动加载技术相当复杂——InvisiMole 首先会安装一个“驱动加载器”——这是另一个内核驱动模块,用于加载作为参数传递的恶意负载(另一个驱动)。为了初始化驱动加载器,InvisiMole 执行了几个独立的 MSR 利用,每个实例都携带一个带有单个 API 调用负载的 ROP 链。恶意软件会首先执行 ExAllocatePoolWithTag 来分配一个可执行的内核内存缓冲区用于加载器,然后在用户模式下准备映像以反映其在内核中的未来地址——部分被移动到它们的虚拟偏移量;导入被解析,重定位被修复。一旦映像准备好,就通过 ntoskrnl 模块的 memcpy 从用户模式复制到分配的内核缓冲区。
为了在将代码执行转移到加载器一旦它被复制到内核时,InvisiMole 的作者也利用了 MSR 漏洞,并在加载器中设计了几个专用的 PE 导出(参见图 7)用于处理从用户模式系统调用的过渡。它的工作方式与 ROP 链小工具非常相似——交换 GS 寄存器,交换用户模式和内核模式堆栈,将所有寄存器保存到堆栈中,恢复原始 LSTAR MSR 值,然后调用实际的函数。完成后,这一过程被反转。
图 7. 通过更改 LSTAR MSR 调用的驱动加载器模块中的导出函数
当加载器在内核中正确初始化后,通过更改 LSTAR MSR 到内核中的导出地址来执行名为 _Start64 的导出函数。在处理到内核的过渡后,_Start64 注册一个延迟例程,该例程负责加载负载驱动程序,然后返回到用户模式。延迟加载器例程将尝试以“正确”的方式初始化负载驱动程序——创建注册表项和内核驱动程序对象,执行所有必要步骤以将驱动程序注册到系统中,就像操作系统自身加载驱动程序一样,最后调用 IoCreateDriver。选择这种正确的初始化方法是为了使加载的负载驱动程序能够处理 I/O 请求包并使用 IOCTL 与用户模式模块进行通信。
负载驱动程序
负载驱动程序提供 IOCTL 功能来禁用各种通知回调(见图 8),主要目的是解除第三方安全解决方案的防护,并且有可能保护文件系统中的文件。具体命令由用户模式模块传递。有趣的是,用户模式模块将尝试禁用内核中的 ESET 保护的各个部分。
图 8. InvisiMole 负载驱动程序中的 IOCTL 处理程序
RobbinHood
在普通恶意软件中看到 BYOVD 技术并不常见,它旨在触及尽可能多的用户,但 RobbinHood 勒索软件家族表明它仍然可能有用[8]。
这种勒索软件利用一个易受攻击的 GIGABYTE 主板驱动程序 GDRV.SYS(CVE-2018-19320;见图 9 和图 10)来禁用 DSE 以安装自己的恶意驱动程序。
图 9. RobbinHood 示例中的 GIODrv 驱动程序利用
禁用 DSE 的方法取决于 Windows 版本——在 Windows 7 及更早版本中,直接修改 ntoskrnl 模块中的 nt!g_CiEnabled 变量。在更新的 Windows 8 到 Windows 11 系统中,则修改 ci.dll 模块中的变量 ci!g_CiOptions。找到这个变量稍微复杂一些,看起来作者采用了一种在 GitHub 上的开源项目 DSEFix 中发现的方法。此外,从 Windows 8.1 起,ci.dll 中的变量受到了 PathcGuard 的保护,篡改该模块最终会导致系统 BSOD,即使变量被更改回原始值。
然后,恶意驱动程序用于终止长列表的进程并删除它们的文件,主要集中在端点保护软件和其他实用程序上。由于终止是在内核模式下完成的,大多数安全软件采用的自我保护机制被规避,这种技术比尝试从用户模式解除保护更有可能成功。
图 10. GIODrv 中的 WriteVirtualMemory IOCTL 处理程序
LoJax
2018 年,ESET 研究人员发现了 第一个在野外使用的 UEFI rootkit。为了访问受害者的 UEFI 模块,恶意软件利用了一种强大的工具 RWEverything。
RWEverything 驱动程序最近被微软在 Windows 10 和 11 中通过 HVCI 内存完整性功能禁用了,该功能在 基于虚拟化的安全性 部分中描述。
发现的漏洞
在我们的研究中,我们决定不仅对现有漏洞进行编目,还寻找新的漏洞。我们设置了 YARA 规则来追踪具有特定功能和潜在漏洞指示的内核驱动程序。我们还创建了一个概念验证利用框架来测试新发现的驱动程序并确认它们是否可被利用。
我们查看了数百个符合我们标准的不同内核驱动程序,除了发现已知的驱动程序外,我们还发现了三种以前未被知晓的漏洞驱动程序,其中一些包含多个无关的错误。即使在几个独立的研究小组解决了这个领域后,我们仍然能够发现新的漏洞,即使来自知名厂商,这表明 Windows 驱动程序安全性仍然是一个问题。
在我们寻找所有种类的漏洞时,发现具有 MSR 访问权限的漏洞往往最为容易,因为它们通常由于使用特殊特权指令(RDMSR/WRMSR)而暴露出这种功能。有趣的是,在许多情况下,这类驱动程序还包含其他种类的漏洞,如任意物理或虚拟内存的读写功能。
AMD μProf (CVE-2021-26334)
我们在 AMDPowerProfiler.sys 内核驱动程序中发现了一个 MSR 漏洞,该驱动程序是 AMD μProf 性能分析软件的一部分。
该驱动程序的独特之处在于,一旦安装了基础软件包,该驱动程序会在每次系统启动时运行。未经过滤的 MSR IOCTL 访问以及缺少 FILE_DEVICE_SECURE_OPEN 标志(见图 11)和启动时的存在使得攻击者即使作为非特权用户也有很好的机会利用该驱动程序——这相比于 BYOVD 方法具有优势,因为攻击者需要自行加载驱动程序。
*图
-
AMD uProf 内核驱动程序设备创建时没有 FILE_DEVICE_SECURE_OPEN 标志,允许非管理员访问*
另一方面,这款软件是针对开发者的小众工具,并不是分发给大量系统的软件包。我们没有在驱动程序中发现其他漏洞。
易受攻击的 IOCTL 是 IOCTL_ACCESS_MSR (0x222030)。
AMD 已经承认了这一漏洞(CVE-2021-26334),并在 2021 年 11 月 Patch Tuesday 发布了修复程序。
Passmark 软件
Passmark 是一家提供各种计算机基准测试和诊断工具的公司。为了在用户模式下实现这样的功能,需要通过利用内核模式驱动程序访问许多低级系统功能。
Passmark 的 DirectIo32.sys 和 DirectIo64.sys 内核驱动程序是一个在多个供应商应用程序之间共享和分发的通用框架——即 BurnInTest、PerformanceTest 和 OSForensics。
该驱动程序包含直接、未经过滤的 MSR R/W 访问(CVE-2020-15480)、映射物理内存(CVE-2020-15481)的能力用于读写,且 IOCTL 处理程序还包含一个缓冲区溢出(CVE-2020-15479),由于盲目复制、没有任何大小检查,将任意大小的 IOCTL 输入缓冲区复制到堆栈上的本地变量中。
Passmark 已经承认了这些漏洞,并很快发布了修复版本。
CVE-2020-15479
当驱动程序接收到来自用户模式程序的IOCTL请求时,它会首先将请求的输入缓冲区复制到栈上的本地缓冲区中。memmove的大小仅基于输入缓冲区的大小(见图12),而不考虑栈缓冲区的容量。如果提供了足够大的IOCTL缓冲区,这可能会导致缓冲区溢出。在IOCTL处理函数中有多个未经检查的memmove调用,多个IOCTL可以利用缓冲区溢出。
图12. 漏洞Passmark驱动程序中的缓冲区溢出
CVE-2020-15480
该驱动程序通过一个IOCTL暴露了RDMSR和WRMSR功能,允许没有特权的用户模式程序读取和写入任意CPU MSR,而无需任何额外的检查。易受攻击的IOCTL是IOCTL_READ_MSR (0x80112060)和IOCTL_WRITE_MSR (0x80112088)。
CVE-2020-15481
物理内存映射功能通过一个控制代码暴露 – IOCTL_MAP_PHYSICAL_MEMORY (0x80112044)。实现分为两个部分:主要版本通过ZwMapViewOfSection API完成;如果由于某种原因此方法失败,函数还实现了一个备用的次要方法,通过MmMapIoSpace和MmMapLockedPages内核API。两者在图13中有所说明。
图13. Passmark驱动程序中的物理内存IOCTL实现
Devid Espenschied PC Analyser
PC Analyser是另一个用于检查机器各种细节的工具。与应用程序一起分发的PCADRVX64.sys内核驱动程序包含两个独立的漏洞 – 未过滤的MSR访问(CVE-2020-28921)和读取和写入任意物理内存地址的能力(CVE-2020-28922)。在创建驱动程序设备时,FILE_DEVICE_SECURE_OPEN标志未指定,允许没有特权的用户检索到驱动程序的句柄。
Devid Espenschied已承认这些漏洞并发布了更新版本。
CVE-2020-28921
与之前的驱动程序一样,MSR访问不受限制(见图14),IOCTL代码处理程序包含FILE_ANY_ACCESS标志,允许即使是没有特权的用户也能利用该功能。
图14. PC Analyser驱动程序中的MSR IOCTL实现
CVE-2020-28922
该驱动程序的物理内存读取和写入功能通过基于读取或写入请求大小的不同IOCTL实现。它提供了以下控制代码,均未对请求的内存地址进行检查:
IOCTL_READ_PHYSICAL_MEMORY_BYTE (0x82002400)
IOCTL_READ_PHYSICAL_MEMORY_WORD (0x82002500)
IOCTL_READ_PHYSICAL_MEMORY_DWORD (0x82002600)
IOCTL_WRITE_PHYSICAL_MEMORY_BYTE (0x82002700)
IOCTL_WRITE_PHYSICAL_MEMORY_WORD (0x82002800)
IOCTL_WRITE_PHYSICAL_MEMORY_DWORD (0x82002900)
缓解措施
虽然我们已经提到了一些CPU和/或操作系统使用的机制,但大多数可以通过一些巧妙的技术绕过,并且如果攻击者事先做好准备,它们的效果不是很好。在本节中,我们将提到一些实际有效的缓解措施,以完全阻止漏洞驱动程序的滥用。
基于虚拟化的安全性
基于虚拟化的安全性或VBS是Windows 10中引入的一项功能,它利用硬件虚拟化并通过虚拟机监控程序对内核进行沙箱化,以便通过各种保护措施来保护操作系统。
VBS提供了几种保护功能,其中最显著的是Hypervisor-Protected Code Integrity (HVCI),它也可以作为一个独立的功能存在。HVCI在内核中强制代码完整性,只允许执行签名代码。它还使用了阻止列表功能,已知的由特定有效签名签署的代码可以被阻止,不允许运行或加载。通过这种方法已经被阻止的驱动程序之一是RWEverything实用程序。
HVCI有效地防止了漏洞驱动程序被滥用以执行未签名的内核代码或加载恶意驱动程序(无论使用何种攻击方法),而且似乎恶意软件利用漏洞驱动程序加载恶意代码是Microsoft实施此功能的主要动机之一:
VBS提供了显著的安全收益,以应对包括我们去年看到的几种实际攻击,包括人操作的[勒索软件攻击如RobbinHood]和[复杂的恶意软件攻击如Trickbot,这些攻击利用内核驱动程序和HVCI可以缓解的技术]。我们的研究表明,与未启用HVCI的系统相比,启用HVCI的机器报告给Microsoft 365 Defender的活动恶意软件报告减少了60%。Surface Book 3于2020年5月发货,Surface Laptop Go于2020年10月发货,用户可能没有注意到他们正在运行VBS,因此在幕后完成的工作使他们更好地受到保护。[重点添加]
除了强制执行内核代码完整性之外,VBS还保护重要的MSR,并禁止对其进行任何更改。不出所料,这种保护还影响LSTAR MSR,并缓解了上述所有的利用可能性。
虽然VBS是针对MSR利用和在内核中运行恶意代码的一种有效保护,但这一新功能的采用相当有限,因为它有几个硬件要求,只有较新的机器才能满足。还有一些缺点,其中最显著的是性能下降,根据工作负载,这可能会非常明显。虽然一些基准测试估计性能下降高达25%在特定视频游戏中,Tom’s Hardware的更详细基准测试估计性能下降约为5%,具体取决于特定的基准测试和硬件配置(见图15),这仍然是一个不可忽视的数额,可能会导致一些用户考虑关闭此功能。与遗留驱动程序和软件可能也存在一些兼容性问题。随着Windows 11的发布,Microsoft决定默认启用所有兼容设备的HVCI。
第三方虚拟机监控程序
类似于Microsoft的VBS,使用足够新的硬件,第三方安全解决方案可能会部署自己的自定义虚拟机监控程序。在虚拟机监控程序下运行操作系统提供了对机器状态的详细监督,并提供了检查和拦截任何事件的
可能性,包括执行特定指令。与VBS一样,这也有代价,即性能和兼容性。
证书撤销
在现代Windows系统上,驱动程序需要具有基于“可接受”证书的有效签名。因此,撤销易受攻击的驱动程序的证书将是“解除武装”它并使其在大多数情况下无效的一种简单方法。
可惜的是,撤销很少发生,在我们研究中记录的易受攻击的驱动程序中,没有一个驱动程序的签名被撤销。可能有许多原因导致这种撤销没有发生,但主要的原因可能是时间和成本。由于没有人要求撤销,从供应商的角度来看,要求撤销没有多大意义,因为这将是一个昂贵且耗时的过程。此外,签名证书通常在其他项目中共享,因此由于单个驱动程序的撤销可能会阻碍每个项目的开发。
此外,在我们的研究中,我们了解到,撤销证书的驱动程序并不总是被阻止,这个问题比最初看起来的更复杂。撤销可能并不是最终的解决方案。
驱动程序黑名单
驱动程序黑名单是微软和各种第三方安全产品供应商采用的一种做法。一些最臭名昭著的易受攻击的驱动程序被ESET安全产品检测到,并在发现时从系统中删除。微软不仅通过其安全解决方案选择了黑名单驱动程序,还直接通过操作系统利用其HVCI缓解措施(虚拟化安全的一部分)来阻止这些驱动程序。虽然黑名单有效,但这不是一种主动解决方案——只能将已发现的易受攻击的驱动程序列入黑名单,并且必须由每个供应商手动执行。这意味着这种缓解措施对于以前未知的零日驱动程序漏洞可能无法有效应对,这些漏洞可能会被用在复杂的APT攻击中。
可能最著名的黑名单驱动程序是Capcom的“反作弊”驱动程序Capcom.sys,该驱动程序明确实现了一个IOCTL,直接在内核模式下执行提供的缓冲区的内容(见图16)。为了能够执行来自用户模式的缓冲区,它甚至暂时禁用了SMEP!
当被发现时,该驱动程序引起了广泛关注,并且许多未签名的驱动程序加载工具是基于滥用该驱动程序的功能创建的。因此,该驱动程序最终被包括微软和ESET在内的许多安全产品供应商列入了黑名单。
图16. Capcom反作弊驱动程序的代码片段
结论
易受攻击的驱动程序长期以来一直是一个已知问题,并且被游戏作弊社区和恶意软件作者滥用,虽然已经做出了一些缓解措施,但仍然是一场持续的战斗。似乎所有相关方都希望解决这个问题——我们联系的供应商在披露过程中表现得非常积极,急于修复我们发现的漏洞。微软试图从内部加强操作系统,最后但同样重要的是,第三方安全供应商也在试图提出聪明的方法来检测和缓解这些驱动程序。
然而,似乎仍然缺少一个部分——一种处理这些问题的共同统一方式,包括对驱动程序进行更彻底的“拆除”,无论是通过吊销或黑名单其证书,还是通过安全公司采用的一些公开共享黑名单。
参考文献
[1] J. Desimone 和 G. Landau, "BlackHat 2018: Kernel-mode Threats and Practical Defences," 2018年8月9日。[在线].
[2] R. Warns 和 T. Harrison, "INFILTRATE 2019: Device Driver Debauchery and MSR Madness," 2019年5月2日。[在线].
[3] J. Michael 和 M. Skhatov, "Defcon 27: Get off the Kernel if you can't Drive," 2019年8月13日。[在线].
[4] N. Economou 和 E. Nissim, "ekoparty 2015: Windows SMEP bypass: U=S," 2015年。[在线].
[5] A. Shulmin, S. Yunakovsky, V. Berdnikov 和 A. Dolgushev, "The Slingshot APT," 2018年3月6日。[在线].
[6] Z. Hromcová 和 A. Cherepanov, "InvisiMole: The Hidden Part of the Story – Unearthing InvisiMole's Espionage Toolset and Strategic Cooperations," 2020年6月18日。[在线].
[7] A. Ionescu, "UMPOwn: Ring 3 to Ring 0 in 3 acts," 见 PoC||GTFO, 第2卷, No Starch Press, 2018年,第768页。
[8] A. Brandt 和 M. Loman, "Living off another land: Ransomware borrows vulnerable driver to remove security software," Sophos, 2020年2月7日。[在线].
原文始发于微信公众号(3072):签名内核驱动程序 – 未受保护的Windows核心入口
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论