BlueKeep 漏洞利用分析

做者:SungLin@知道创宇404实验室
时间:2019年9月18日html

0x00 信道的建立、链接与释放

通道的数据包定义在MCS Connect Inittial PDU with GCC Conference Create Request中,在rdp链接过程以下图所示:git

BlueKeep 漏洞利用分析

信道建立数据包格式以下:github

BlueKeep 漏洞利用分析

在MCS Connect Inittial中属于Client Network Data数据段,MS_T120将会在链接一开始的时候经过函数termdd!_IcaRegisterVcBin建立一个虚拟通道id是0x1f大小为0x18的结构体,以后就调用termdd!IcaCreateChannel开始建立大小为0x8c的信道结构体以后将会与虚拟通道id是0x1f绑定,也就是这个结构体将会被咱们利用windows

BlueKeep 漏洞利用分析

信道的定义字段主要是名字加上配置,配置主要包括了优先级等api

BlueKeep 漏洞利用分析

在server对MCS Connect Inittial应答包,将会依次给出对应虚拟通道的id值:数组

BlueKeep 漏洞利用分析

在rdp内核中依次注册的值对应应该是0、一、二、3, MS_T120信道将会经过咱们发送的用户虚拟id为3的值再一次绑定,首先经过termdd!_IcaFindVcBind找到了刚开始注册的虚拟通道id是0x1f,以下所示:服务器

BlueKeep 漏洞利用分析

可是在termdd!_IcaBindChannel时,却将咱们自定义的id值为3与信道结构体再一次绑定在一块儿了,此信道结构体就是MS_T120ide

BlueKeep 漏洞利用分析

同时咱们本身的用户id将内部绑定的0x1f给覆盖了函数

BlueKeep 漏洞利用分析

咱们往信道MS_T120发送数据主动释放其分配的结构体,其传入虚拟通道id值为3经过函数termdd!IcaFindChannel在channeltable中查找返回对应的信道结构体:spa

BlueKeep 漏洞利用分析

下图为返回的MS_T120信道结构体,其中0xf77b4300为此信道可调用的函数指针数组:

BlueKeep 漏洞利用分析

在这个函数指针数组中主要存放了三个函数,其中对应了termdd!IcaCloseChannel、termdd!IcaReadChannel、termdd!IcaWriteChannel

BlueKeep 漏洞利用分析

咱们传入释放MS_T120信道的数据以下,字节大小为0x12,主要数据对应了0x02

BlueKeep 漏洞利用分析

以后将会进入nt! IofCompleteRequest函数,经过apc注入后,将会经过nt! IopCompleteRequest和nt!IopAbortRequest进行数据请求的响应,最终在termdd!IcaDispatch完成咱们发送数据的的请求,_BYTE v2就是咱们发送的数据,因此咱们发送的数据0x02将会最终调用到IcaClose函数进入IcaCloseChannel函数,最后主动释放掉了MS_T120信道结构体

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

0x01 经过RDPDR信道进行数据占位

咱们先来了解下rdpdr信道,首先rdpdr信道是文件系统虚拟通道扩展,该扩展在名为rdpdr的静态虚拟通道上运行。目的是将访问从服务器重定向到客户端文件系统,其数据头部将会主要是两种标识和PacketId字段组成:

BlueKeep 漏洞利用分析

在这里咱们恰好利用到了rdpde客户端name响应的数据来进行池内存的占位

BlueKeep 漏洞利用分析

在彻底创建链接后,将会建立rdpdr信道的结构体

BlueKeep 漏洞利用分析

在window7中,在创建完成后接收到server的rdpdr请求后,经过发送客户端name响应数据,将会调用到termdd! IcaChannelInputInternal中的ExAllocatePoolWithTag分配非分页池内存,而且其长度是咱们能够控制的,基本知足了UAF利用的需求:

BlueKeep 漏洞利用分析

但是在windowsxp中,直接发送client name request将会致使内存分配失败,直接进入termdd! _IcaCopyDataToUserBuffer,而且在Tao Yan and Jin Chen[1]一文中也提到了经过发送client name request在触发必定的条件后将会绕过termdd!_IcaCopyDataToUserBuffer而进入ExAllocatePoolWithTag分配咱们想要的非分页内存,而打破条件以下:

BlueKeep 漏洞利用分析

咱们先来看看最开始信道结构体的建立,咱们能够发现从一开始建立信道结构体的时候,将会出现两个标志,而这两个标志是按照地址顺序排列的,而在上面须要打破的条件中,只要channelstruct +0x108的地址存放的是同一个地址,循环就会被break

BlueKeep 漏洞利用分析

咱们发送一个正常的rdpdr的name request数据包,头部标识是0x7244和0x4e43

BlueKeep 漏洞利用分析

通过termdd!_IcaCopyDataToUserBuffer以后,将会进入nt!IofCompleteRequest,在响应请求后进入rdpdr!DrSession::ReadCompletion,此函数处理逻辑以下,其将会遍历一个链表,从链表中取出对应的vftable函数数组

BlueKeep 漏洞利用分析

遍历第一次取出第一张函数数组

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

传入咱们发送的数据后,经过函数数组调用rdpdr!DrSession::RecognizePacket进行读取

BlueKeep 漏洞利用分析

判断头部标志是否为(RDPDR_CTYP_CORE)0x7244
BlueKeep 漏洞利用分析

接着将会读取函数vftable第二个地址,进行转发

BlueKeep 漏洞利用分析
以下图能够看到rdpdr的数据包处理逻辑

BlueKeep 漏洞利用分析

rdpdr通过一系列数据包处理后最终进入了咱们关心的地方,将会传入channelstruct经过调用termdd! _IcaQueueReadChannelRequest进行标志位的处理

BlueKeep 漏洞利用分析

最初rdpdr的channelstruct的标志位以下

BlueKeep 漏洞利用分析

通过函数termdd! _IcaQueueReadChannelRequest对此标志的处理后变成以下,因此下一个数据依然会进入termdd!_IcaCopyDataToUserBuffer,致使咱们进行池喷射的失败

BlueKeep 漏洞利用分析

回到rdpdr头部处理函数rdpdr!DrSession::RecognizePacket,咱们发如今链表遍历失败后将会进行跳转,最后将会进入读取失败处理函数rdpdr!DrSession::ChannelIoFailed,而后直接return了

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

咱们构造一个头部异常的数据包发送,头部标志咱们构造的是0x7240,将会致使rdpdr!DrSession::RecognizePacket判断失败,以后将会继续遍历链表依次再取出两张函数数组

BlueKeep 漏洞利用分析

最后两个函数数组依次调用rdpdr!DrExchangeManager::RecognizePacket和rdpdr!DrDeviceManager::RecognizePacket,都会判断错误的头部标志0x7240,最后致使链表遍历完后进行错误跳转,直接绕过了termdd! _IcaQueueReadChannelRequest对标志位的修改,将会打破循环

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

最后咱们连续构造多个错误的数据包后将会进入ExAllocatePoolWithTag,分配到咱们须要的非分页内存!

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

0x02 win7 EXP 池喷射简要分析

首先被释放的MS_T120池大小包括是0x170,池的标志是TSic

BlueKeep 漏洞利用分析

分析Win7 exp 能够知道数据占位是用的rdpsnd信道,做者没有采用rdpdr信道,应该也和喷射的稳定性有关,rdpsnd喷射是再创建完了rdpdr初始化后开始的,在free掉MS_T120结构体前,发送了1044个数据包去申请0x170大小的池内存,这样作能够说应该是为了防止以后被free掉的内存被其余程序占用了,提升free后内存被咱们占用的生存概率

BlueKeep 漏洞利用分析

占位被free的实际数据大小为0x128,利用的中转地址是0xfffffa80ec000948

BlueKeep 漏洞利用分析

以后开始池喷射,将payload喷射到能够call [rax] == 0xfffffa80ec000948的地方,喷射的payload大小基本是0x400,总共喷射了200mb的数据大小,咱们先来看下喷射前带标志TSic总共占用池内存大小是58kib左右

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

喷射完后带TSic标志池内存大小大约就是201mb,池内存喷射基本是成功的,个人win7是sp1,总共内存大小是1GB,再喷射过程当中也没有其余干扰的,因此喷射很顺利

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

图中能够发现基本已经很稳定的0x400大小的池喷射payload,地址越高0x400大小的内存基本就很稳定了

BlueKeep 漏洞利用分析

最后断开链接时候,被free的内存已经被咱们喷射的0x128大小的数据给占用了
BlueKeep 漏洞利用分析

执行call指令后稳定跳转到了咱们的payload,成功执行!

BlueKeep 漏洞利用分析

参考连接:
[0] https://github.com/rapid7/metasploit-framework/pull/12283
[1] https://unit42.paloaltonetworks.com/exploitation-of-windows-cve-2019-0708-bluekeep-three-ways-to-write-data-into-the-kernel-with-rdp-pdu/
[2] https://wooyun.js.org/drops/%E7%BE%8A%E5%B9%B4%E5%86%85%E6%A0%B8%E5%A0%86%E9%A3%8E%E6%B0%B4%EF%BC%9A%20%E2%80%9CBig%20Kids%E2%80%99%20Pool%E2%80%9D%E4%B8%AD%E7%9A%84%E5%A0%86%E5%96%B7%E6%8A%80%E6%9C%AF.html

相关文章
相关标签/搜索