Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

针对多个DirectX内核漏洞的分析

$
0
0
概述

操作系统内核,往往是每一个知名的漏洞利用链的最终目标。纵观多年来Zero Day Initiative(ZDI)Pwn2Own竞赛中涉及到的漏洞,其实就可以发现这一规律。长期以来,windows内核一直是攻击的主要目标。我个人最喜欢的是针对各种驱动程序的DeviceoControl调用滥用,因为通过该漏洞,可以访问大量厂商编写的许多应用程序,其中有一些驱动程序并没有实现安全编码,或者没有经过完善的测试流程。

多年来,大多数针对Windows内核的渗透攻击,都利用了win32k.sys,这是一个控制Windows图形和窗口管理系统的内核模式设备驱动程序。在20年前,当微软将这个功能从CSRSS中移除并将其加入内核时,就立即使Windows内核的攻击面扩大了1-3倍。从那时开始,这一驱动程序对漏洞研究人员来说就是一个“丰富的宝库”。

在过去十年中,自从WDDM(Wondows显示驱动程序模型)取代了早期的XDDM以来,另一个大范围的攻击面也已经开放。具体而言,是首先通过win32k.sys调用显示系统,随后通过用户进程借助GDIPlus中的入口点直接调用dgxkrnl.sys和其他驱动程序。这种扩大后的攻击面,针对研究人员来说是一个诱人的目标。

在2018年春季,ZDI获得了腾讯湛泸实验室ChenNan和Rancholce发现的5个针对DirectX内核接口的漏洞。其中的4个漏洞,获得了来自微软的CVE编号。本文主要对这些漏洞进行分析,同时提供了PoC概念证明的源代码。

针对其中的一个漏洞(ZDI-18-946/CVE-2018-8405),Rancho和ChenNan在9月份的44CON会议上发表了一次演讲,我强烈建议研究人员首先阅读 此次演讲的幻灯片 。

DirectX概述

在深入研究漏洞之前,我们先简单介绍一下DirectX的接口和驱动程序。

DirectX图形内核子系统由3个内核模式驱动程序组成,分别是dxgkrnl.sys、dxgmms1.sys和dxgmms2.sys。这些驱动程序通过win32k.sys和其自身的一组接口与用户进行通信。此外,它们还会与BasicRender.sys、BasicDisplay.sys以及显示驱动程序(Display Miniport Drivers)进行通信。

DirectX定义了许多复杂的内核对象,其中大多数的名称都以DXG开头。用户通过这些复杂的API入口点与DirectX连接,其中许多入口点都以D3DKMT开头,其他的一些入口点以DXGK开头。

我们分析一些重要的入口点:

D3DKMTEscape

该入口点完全将用户控制的数据Blob作为输入。由于这一数据Blob可能非常大,所以很有可能会将其保留在用户内存中,而不会在转换到内核处理期间在内核中捕获它。这样的模式会使其调用的内核例程很容易出现检验时间(Time-Of-Check)或使用时间(Time-Of-Use)漏洞。其中的数据没有采用标准化结构,每个驱动程序都有各自不同的定义。

D3DKMTRender

该入口点是实际渲染图形数据的核心。用户地址命令和补丁缓冲区由内核驱动程序来解释,最终传递给显示驱动程序。针对于此,可以使用竞态条件的攻击方式。另外,由于渲染可以生成工作线程,就更加容易产生竞态条件漏洞。

D3DKMTCreateAllocation

该入口点用来分配内存。由于传递给API调用的不同标志和句柄之间具有复杂的相互作用,可能会出现问题(参见下面的ZDI-18-946)。

从攻击的角度来看,IOActive的Ilja van Sprundel曾在2014年的Black Hat上针对WDDM进行了非常完整的概述,他的演讲题目是“Windows内核图形驱动程序攻击面”。我强烈建议各位读者首先阅读 相关材料 ,其中详细介绍了WDDM内核端的复杂攻击面。

漏洞利用

在这里,可以找到相关漏洞的概念证明(PoC)源代码。如果要复现漏洞,需要在2018年8月之前的Windows版本上实现。将内核调试程序添加到测试使用的计算机上,并在存在漏洞的驱动程序上设置一个特殊池。在实际测试中,我在Windows 10 x64上成功复现了这些漏洞。

D3DKMTCreateAllocation类型混淆漏洞(ZDI-18-946/CVE-2018-8405)

在dgxkrnl.sys中的DXGDEVICE::CreateAllocation发现的第一个漏洞,是通过D3DKMTCreateAllocation方法暴露的,并且可能允许本地攻击者将权限提升至SYSTEM级别。针对这个漏洞,我们的建议如下: https://www.zerodayinitiative.com/advisories/ZDI-18-946/ ,微软的官方补丁请参考: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8405 。该漏洞源于缺乏对用户提供的数据的充分验证,可能会导致类型混淆的问题。

要具体查看此情况,需要在运行PoC之前,在dxgkrn.sys上启用 特殊池 。类型混淆是由于在分配过程中不恰当的使用了CrossAdapter标志。在PoC代码中,使用CrossAdapter标志0来进行分配,然后将结果句柄传递第二个分配,在该分配中,它将CrossAdapter的标志设置为1。


针对多个DirectX内核漏洞的分析

下面是对蓝屏的分析:


针对多个DirectX内核漏洞的分析
针对多个DirectX内核漏洞的分析
针对多个DirectX内核漏洞的分析

其中,出现问题的代码位于DXGDEVICE::CreateAllocation中,并且在分配结束时发生典型的类型混淆:


针对多个DirectX内核漏洞的分析
D3DKMTRender类型混淆漏洞(ZDI-18-947/CVE-2018-8406)

在dxgmms2.sys中,还存在另一个漏洞,并且通过D3DKMTRender暴露。该漏洞还可能允许本地攻击者将权限提升至SYSTEM。针对这个漏洞,我们的建议如下: https://www.zerodayinitiative.com/advisories/ZDI-18-947/ ,微软的官方补丁请参考: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8406 。与第一个漏洞相同,该漏洞会导致类型混淆问题。尽管看起来相似,但这些漏洞有不同的根本原因。

同样,要具体查看此问题,需要在dxgkrnl.sys和dxgmms2.sys上启动特殊池,以查看这些漏洞。当然,还需要将内核调试程序添加到目标计算机。这种类型混淆是由于在两个不同的适配器之间混淆的分配操作造成的。

相关的PoC代码:


针对多个DirectX内核漏洞的分析

PoC的崩溃信息:


针对多个DirectX内核漏洞的分析
针对多个DirectX内核漏洞的分析

漏洞代码:


针对多个DirectX内核漏洞的分析
D3DKMTRender不受信任的指针解除引用漏洞(ZDI-18-950/CVE-2018-8400)

下一个漏洞也是通过D3DKMTRender例程暴露。该漏洞位于dxgkrnl.sys中的DGXCONTEXT::ResizeUserModeBuffers方法中。针对这个漏洞,我们的建议如下: https://www.zerodayinitiative.com/advisories/ZDI-18-950/ ,微软的官方补丁请参考: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8400 。在这种情况下,该漏洞是由于在将其作为指针解除引用之前,缺乏对用户提供的值的适当验证。产生的指针解除引用,是由于驱动程序信任用户设置的标志。以下是相关PoC的详细信息:


针对多个DirectX内核漏洞的分析

其崩溃结果如下:


针对多个DirectX内核漏洞的分析

调用来自:


针对多个DirectX内核漏洞的分析

漏洞代码:


针对多个DirectX内核漏洞的分析

显然,来自用户的这个标志不应该导致内核中的任意解除引用。

BasicRender竞态条件漏洞(ZDI-18-951/CVE-2018-8401)

针对这最后一个漏洞,由于漏洞存在于BasicRender驱动程序处理D3DKMTMarkDeviceAsError API和D3DKMTSubmitCommand API中,所以其过程有些复杂。针对这个漏洞,我们的建议如下: https://www.zerodayinitiative.com/advisories/ZDI-18-951/ ,微软的官方补丁请参考: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8401 。在这里,共享资源没有得到适当的保护,从而可能导致内存损害情况。攻击者可以借助这一漏洞,将权限提升到SYSTEM。一旦用户点击了他们不应该点击的内容,恶意软件通常会使用这种类型的权限提升来实现自动安装。微软为这一漏洞分配了CVE编号,其中说明了相同的根本原因。

针对这两种情况,其PoC代码是相关的,但有所不同。

第一个PoC的关键部分:


针对多个DirectX内核漏洞的分析

每次调用SubmitCommand时,都会通过VidSchiWorkerThread产生一个线程。对MakeDeviceError的调用会更改相同对象的状态,并产生竞态条件的问题。

导致的崩溃如下:


针对多个DirectX内核漏洞的分析

竞态条件是在同一位置的两次修改之间发生:


针对多个DirectX内核漏洞的分析

对于ZDI-18-949,尽管有着相同的根本原因,但仍然可以发现PoC代码的差异。该PoC的关键部分如下:


针对多个DirectX内核漏洞的分析

执行这一PoC,会导致Run方法崩溃:


针对多个DirectX内核漏洞的分析

漏洞代码如下:


针对多个DirectX内核漏洞的分析

在存在漏洞的代码中,第二次在Run方法中发生崩溃。

结论

WDDM和DirectX图形内核代码为Windows提供了一个非常强大和灵活的图形系统。他们通过使用许多复杂的对象,以及为用户代码创建许多新的复杂接口来实现这一点。这里给出的概念证明,应该可以让大家了解DirectX中实现的对象的复杂性,以及这一领域中可以继续研究的内容。

通过直接的静态分析,可以为您提供攻击的相关信息。当然,这是一项非常复杂的任务。另一种可能性是使用一

Viewing all articles
Browse latest Browse all 12749

Latest Images

Trending Articles





Latest Images