Windows 内核提权漏洞分析:CVE-2020-1034

 

简介

在9月的补丁中,包含了几个允许内核提权的漏洞。但没有公布与他们相关的细节或分析。在这篇文章中,将介绍对CVE-2020-1034漏洞的研究。

 

补丁对比

受影响的模块是ntoskrnl.exe。我下载了这个模块的补丁和未修补版本。我在Windows 10 1903 x64上进行了分析。下面是18362.1049与18362.1082版本进行比较的结果。

很明显,EtwpNotifyGuid被修改过了。我仔细查看了这个函数,发现了一个重要的改变。

所以决定进一步研究。

 

漏洞分析

首先,我研究了NtTraceControl,它是EtwpNotifyGuid的网关。这是NtTraceControl的描述。

导致调用EtwpNotifyGuid的函数代码是0x11。在实际调用之前还需要进行一些检查,如下图所示:

然后,我分析了这个函数。如果我们仔细查看EtwpNotifyGuid,会发现一些有意思的地方,注意补丁的地方。

RDI寄存器包含输入缓冲区的地址。地址rdi + 0Ch处的byte决定是否创建一个UmReplyObject。
让我们看看r12b寄存器的值来自哪里。

r12b的初始值为4。但被重置为1。因此,当ptr [rdi+0Ch]的值等于1时,rdi + 18h处的qword将设置为新创建的UmReplyObject的地址。否则,qword将保持不变。这可能会带来危险的后果。因为输入永远不能被信任。

我将rdi+18h的qword设置为任意值,并查看发生了什么。如我所料,我得到了一个BSOD。

我非常兴奋。我进一步进行了分析。输入缓冲区被传递给EtwpSendDataBlock和EtwpQueueNotification。

查看EtwpQueueNotification,我发现了引用UmReplyObject的位置。

bl的值为零。如果rbp + 0Ch处的byte不为0,那么在rbp+18h的qword被读取为一个指向对象的指针,并增加了对象的引用。

我了解了问题的根本原因。罪魁祸首是rbp + 0C处的byte比较不一致。

在EtwpNotifyGuid中进行比较时,将该值与1进行比较,以决定是否创建一个新的UmReplyObject。但是在最后的比较中,该值与零进行了比较。

第一个比较可能类似于以下C代码中的内容:

if (*(bool*)(rdi+0x0C) == true)

第二个可能如下所示:

if (*(bool*)(rbp+0x0C))

看到不一致了吗?如果值不是1或0,该怎么办?任意值将作为对象地址。然后,ObfReferenceObject被调用,这意味着操作qword ptr [[InputBuffer + 0x18] – 0x30] ++被执行。因此实现了任意地址增量。

这是Poc代码:

 

如何利用

这是一个非常好的漏洞,利用非常简单。

在Win10 RS3或以下的内核上,我们可以使用两个adjacent palettes技术。
在Win10 RS4或以上版本的内核上,我们可以操作进程token的Privilege字段。

 

总结

如果对布尔(boolean)指针的值执行显式布尔检查,则是危险的。我花了很多时间来重现这个漏洞。令人惊讶的是,windows内核竟然包含这种漏洞。我不会透露全部的exploit代码,因为它可能会被恶意的滥用。

(完)