简介
在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代码,因为它可能会被恶意的滥用。