在 Microsoft Windows Vista、Windows 7、Windows 8 和 Windows 8.1(KB3086255 之前的版本)以及 Macrovision SafeDisc 所附带的 secdrv.sys 驱动程序中,发现了一个问题。两次精确计时的 IOCTL 0xCA002813 调用可导致竞争条件,进而引发释放后使用。成功利用此漏洞后,非特权攻击者可在内核中执行任意代码。
该漏洞已报告给 Microsoft,由于它不影响已更新至最新版本的 Windows 系统(仅影响 KB3086255 之前的版本),因此 Microsoft 不会采取任何措施。已在 Windows 7 x86 上成功测试和利用。
另请参见 CVE-2018-7250。

本文记录了我对 secdrv.sys 驱动程序的一些小研究。所有描述的行为均来自逆向分析,可能不正确或不准确。
IOCTL(0x0CA002813)输入缓冲区偏移量 0x4 处包含一个数字,我将其称为 TYPE。 该 IOCTL(0x0CA002813)的主处理函数 sub_11A88 接收三种不同的类型:0x96、0x97 和 0x98。
在 IOCTL 类型 0x96 分配一个新块并对其进行初始化(但未完全完成)后,它会将该块复制到用户模式。新分配的块中有 16 位未被初始化,包含先前 PagedPool 分配的数据。未初始化的位随后通过 REP MOVSD 指令在 .text:00011BE9 处复制到用户模式。PoC 代码在此处。
当调用 IOCTL 类型 0x97 时,它会根据标签查找先前通过类型 0x96 分配的所需块。如果该分配已被 IOCTL 类型 0x97 释放,DeviceIoControl 将返回错误。此处的漏洞在于,类型 0x97 所使用的分配在其操作期间(因为未使用同步机制)可以被释放,因此如果赢得竞争条件,就会导致释放后使用。 如果攻击者设法在 IOCTL 类型 0x97 的操作期间(使用类型 0x98)释放该块,并在完全相同的内存位置分配一个攻击者控制的新块,那么他可以覆盖指向另一个结构的指针,该结构包含一个函数指针,最终可用于劫持驱动程序执行流并在 ring 0 中执行任意代码。 由于加密例程是在用户提供的缓冲区上执行的,该缓冲区可能非常大,因此加密执行可能需要很长时间,从而为 IOCTL 类型 0x98 释放仍在使用中的块提供了完美的时机。这个时间窗口可能非常长(超过 1 秒!),以至于竞争条件可以在首次尝试时可靠地获胜。释放后使用从 .text:00011B68 开始,实际被劫持以跳转到 shellcode 的调用发生在 .text:00011B86。
成功利用此漏洞的步骤如下:
操作系统: Windows 7 Kernel Version 7600 MP (1 procs) Free x86 compatible Built by: 7600.16385.x86fre.win7_rtm.090713-1255 虚拟机: 4GB RAM, 1 CPU 硬件: Windows 10 Pro 64位,主板 Gigabyte Z370 HD3,16GB RAM,Intel i5-8400 2.80GHz (6 CPUs)