Windows tcp/ip核弹级漏洞复现

admin 2024年9月5日14:26:50评论65 views字数 5416阅读18分3秒阅读模式

一、内核调试环境

VMware 17 以上请下载https://github.com/4d61726b/VirtualKD-Redux

主机环境:

Windbg(尽量默认路径安装,后边省的改设置)

Virtualkd:https://sysprogs.com/legacy/virtualkd/

双击自解压

Vmware虚拟机环境:

Windows10(有漏洞版本)

Wireshark(监测数据包用)

Virtualkd也下载一份,双击启动target/vminstall.exe(详情见https://sysprogs.com/legacy/virtualkd/tutorials/install/),点击install,全部默认选是,自动重启虚拟机,进入debug模式

Windows tcp/ip核弹级漏洞复现

主机上启动 vmmon64.exe

Windows tcp/ip核弹级漏洞复现

虚拟机打开target64目录下的vminstall.exe,默认设置确定

重启后显示

Windows tcp/ip核弹级漏洞复现

在这个界面按F8,选择“禁用驱动程序签名强制”(关键嗷,不然主机这边挂不上调试)

Windows tcp/ip核弹级漏洞复现

主机上OS和Debugger都是yes,证明成功挂上调试

Windows tcp/ip核弹级漏洞复现

主机windbg出现int 3,并且虚拟机卡住,这时在windbg命令行输入g继续运行

Windows tcp/ip核弹级漏洞复现

二、获取pdb符号文件

在使用windbg输入命令调试时,如果一直busy,可以先break一下,输入命令后再g继续运行

Windows tcp/ip核弹级漏洞复现

在windbg设置符号路径,确保WinDbg能够访问微软的符号服务器

.sympath srv*C:Symbols*https://msdl.microsoft.com/download/symbols

其中C:Symbols是本地符号缓存目录,可以自己更换,请在没有中文目录下创建

接下来强制重新加载tcpip.sys

.reload /f tcpip.sys

最后重新下载符号

.reload

Windows tcp/ip核弹级漏洞复现

在重新加载后,可以使用lm t n指令查看所有已加载的模块以及地址范围

Windows tcp/ip核弹级漏洞复现

此时查看上边设置的符号缓存目录,发现已经下载了对应的pdb符号文件,用ida反编译时就能看到符号啦!(这里的pdb文件是虚拟机中tcpip.sys的符号文件,不是主机的)

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

三、静态分析

First of all,先给虚拟机做个快照,现在虚拟机是存在漏洞且可调试的完美状态,为了方便后续验证漏洞,所以务必先做快照(挖洞好习惯,多打快照)。

其次,尽量漏洞版本系统是2024年6月之后8月14日之前的win10,因为这个期间微软也会调整或修复其他问题,会出现一些干扰函数,所以尽量选择漏洞前后的两个版本进行diff。

1.给主机和虚拟机系统更新Windows10.0-KB5041773-x64补丁,这个补丁主要修复了CVE-2024-38063,可以在C:WindowsWinSxS目录下找到修复后的tcpip.sys(用右上角搜索搜tcpip.sys,查看签名时间为8月10日的文件)

2.使用ida中的BinDiff插件diff修复前后的tcpip.sys(注意i64文件目录不能有中文),主要看第一列相似度,发现新加了一个函数Feature_Servicing_tcpip_autoportreuse__private_IsEnabledDeviceUsage(Feature_xxx__private_IsEnabledDeviceUsage大多为补丁函数,但不确定是针对ipv6漏洞的补丁函数,下边还要继续分析)。

Windows tcp/ip核弹级漏洞复现

3.由于有函数符号,直接在diff列表中搜索ipv6,发现一个ipv6函数相似度不是100%,双击进去看一下

Windows tcp/ip核弹级漏洞复现

4.在该函数的最下边,发现了Feature_2365398330__private_IsEnabledDeviceUsage()函数,通过比对漏洞版本的tcpip.sys,差的0.06确实在if判断这里

Windows tcp/ip核弹级漏洞复现

5.进入该Feature函数,一个标志位&0x10,判断了第五位是不是0;如果第五位不是0,那就执行else语句,进行回滚(这里简单分析,一会还要动调)。

Windows tcp/ip核弹级漏洞复现

6.回到Ipv6pProcessOptions函数继续分析,相较于修复前多了一个IsEnabledDeviceUsage判断,推断产生漏洞的原因就在于IppSendErrorList()。在修补之前,Ipv6pProcessOptions函数调用IppSendErrorList()来处理处理失败的数据包或请求丢弃的数据包,这会遍历整个net_buffer_list(传入的第三个参数),处理其中的每一个数据包;而修复后,在某种条件下只会处理当前的数据包。这也证明之前引发溢出的漏洞并不是单一数据包产生的,我们需要发送多个会被抛弃或或待被处理的ipv6数据包,才能组合触发漏洞。

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

四、动态调试

PS:在动调前先测试主机和虚拟机能不能ping通,使用ping ipv6地址相互ping,开始可能会失败一两次,但如果持续失败,请直接关闭虚拟机内所有防火墙和主机的域防火墙。

1.通过windbg对补丁函数下断点

bp tcpip!Feature_2365398330__private_IsEnabledDeviceUsage

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

2.为了减小工作量,这里对Ipv6pProcessOptions进行下断,使用python简单fuzz发送ipv6数据包(对头部多个字段同时进行fuzz),等待几秒钟,发现有ipv6数据包触发了Ipv6pProcessOptions函数,复制该数据包的hexstream备用。

Windows tcp/ip核弹级漏洞复现

3.查看函数逻辑,发现能不能进LABEL_36全靠这个if判断,这里是个||运算,所以两个条件满足一个即可,我们先查看*(_DWORD *)(v6 + 24)的内容,如果该值可控,那很方便就能进入LABEL_36了。

Windows tcp/ip核弹级漏洞复现

4.通过在cmp [rdi+18h], eax下断,发现*(_DWORD *)(v6 + 24)的值为0x28是IPV6载荷字节数(payload length),可以尝试减小payload数据量或伪造有效载荷长度从而进入补丁函数。

Windows tcp/ip核弹级漏洞复现

5.跟进查看,主要目的是获取Feature_2365398330__private_featureState的内容,这是本次漏洞修复检测的核心。看到Feature_2365398330__private_featureState的内容是0x157,这条路径可以暂放,回到Ipv6pProcessOptions尝试满足另一个条件。

Windows tcp/ip核弹级漏洞复现

6.回到另一个条件,取到的DataBuffer值为0x10,DataBuffer[1]的值是0x00,所以v9(r14d)的值为0x08,也就是说payload length要小于8才能进入这个分支到达LABEL_36。

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

7.搞清了如何触发Ipv6pProcessOptions中的IppSendErrorList ,接下来分析在上一章中我们分析出IppSendErrorList第三个参数是net_buffer_list的指针,这里我们下个条件断点,当第一万次击中断点时再断。使用python多线程发送一万个plen小于8的ipv6数据包,分析查看net_buffer_list链表内容。

Windows tcp/ip核弹级漏洞复现

8.通过ida得知IppSendErrorList第三个参数是r8,在触发IppSendErrorList断点时查看r8寄存器的值为ffffb6816a27c3c0,使用dt查看该单链表结构内容。这里第一次让我感到奇怪,明明使用多线程发送了一万个数据包,但list中却只有一个数据包,单链表的next指针指向了null。对这种现象有两种解释:其一是由于我给虚拟机分配了8个cpu内核,导致虚拟机处理这些数据包太快,同时python发包速率有上限,所以list只有最新的数据包;其二是发送的数据包没有被放在一个列表中。经过降低虚拟机核心数,终于在list链表中看到其他数据包。但这还不够,接下来需要分析IppSendError函数进行了哪些操作,导致产生了“数据下溢”。

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

五、触发漏洞

1.进入IppSendError函数进行分析,发现这个函数主要做了两件事:一是检查数据包的有效性,根据传入的数据包信息,更新数据包的状态,调整数据包各个字段大小;二是生成发送ICMP 错误消息。最可疑的代码就是将net_buffer_list中的DataOffsetDelta置为0,这是IppSendError函数中除了将list的status字段设置为0xC000021B以外出现的修改list内容的代码,而且还是很关键的偏移量字段。当net_buffer_list->DataOffsetDelta字段&0x40等于0时,会进入else中执行把DataOffsetDelta置零操作。也许问题就出现在这里,IppSendError函数会经过IppSendErrorList循环调用,对当前net_buffer_list上的所有数据包的DataOffsetDelta都进行置零操作,单个数据包当然不会受到影响,但如果链上的数据包需要合并或其它操作,那可能会导致偏移错位,读写到错误的数据。

Windows tcp/ip核弹级漏洞复现

Windows tcp/ip核弹级漏洞复现

2.有师傅说DataOffsetDelta应该是packet_size,但经过动调调试以及NetioRetreatNetBufferList函数参数定义,被置零的字段应该就是DataOffsetDelta,这个字段对应了当前数据包待被处理的buffer起始地址,每个阶段偏移会被赋予不同值,最大为整个数据包长度(包含头部)。同时发现DataOffsetDelta在Ipv6pReceiveRoutingHeader函数和Ipv6pReceiveFragment函数中都有被调用。

Ipv6pReceiveRoutingHeader函数中v7被赋值为DataOffsetDelta-0x28(ipv6头长),只要保证Next Header字段为43(有路由头部)就会进入该代码块,虽然极其容易触发,但由于Ipv6pReceiveRoutingHeader函数被调用在IppSendError函数之前,赋值为零在减0x28之后,所以基本无法利用。

Windows tcp/ip核弹级漏洞复现

Ipv6pReceiveFragment函数在下边使用了(a1->DataOffsetDelta[0]-0x30),也就是说如果可以触发这里,v41会被赋值为0xFFD0(无符号int16),ExAllocatePoolWithTagPriority函数会为重组数据包分配0xFFD0大小的内存。说明一下,代码中减去0x30是因为IPv6头长0x28 + IPv6 分片头长0x8。这里看起来是个可以利用的点,而且成色很好,由于ExAllocatePoolWithTagPriority函数分配的内存是未初始化的,上边我们提到IppSendError函数会发送ICMP 错误消息,所以返回的ICMP数据包中很有可能包含内核地址(多次申请释放0xFFD0和0x28大小的内存,甚至可能泄露出net_buffer_list上的地址和数据)。

Windows tcp/ip核弹级漏洞复现

3.还是分析的太慢了,边hw边分析了一周,ynwarcs发布了POC(https://github.com/ynwarcs/CVE-2024-38063),Marcus发布了分析文章https://www.malwaretech.com/2024/08/exploiting-CVE-2024-38063.html。ynwarcs发布的POC选择了使用Ipv6pReassemblyTimeout函数来触发这个漏洞,我将结合该POC阐述利用思路。

4.有点乱?我们捋捋思路。已经确定漏洞产生原因是由于IppSendError对list上不该把DataOffsetDelta置零的数据包进行了置零操作,而要想将数据包放在一个list上且有合并操作,那就一定涉及处理分片数据包。Ipv6pReceiveFragment函数既处理和合并分片数据包,还使用了被IppSendError函数置零的DataOffsetDelta进行申请内存操作,组装分片数据包产生0xffd0的重组数据包。

虽然0xffd0的重组数据包很大,但目前还没有造成堆栈溢出,Ipv6pReceiveFragment很小心的使用了十六位无符号数,所以还要想办法把这个0xffd0大小的数据包copy到另一段比较小的堆栈中。

5.ynwarcs找到了用于触发堆溢出的函数Ipv6pReassemblyTimeout。该函数在ipv6数据包重组失败或异常一段时间后被调用,他的代码很少,但在中间部分使用了memmove函数复制缓冲区,顺着这里往上看,它使用IppNetAllocate申请了一块大小为(0xFFD0+8+0x28)再加上一个不超过0x40的值,由于这里是十六位无符号数,所以相加后一定是一个处于0x00和0x50之间的数,远小于0xFFD0,所以下边使用memmove复制内存时会产生溢出。

Windows tcp/ip核弹级漏洞复现

六、【强运】的回响

至于为什么这么晚才写完分析,因为我一直在尝试找一条不同的触发路径,也fuzz了很多ipv6数据包及其组合,虽然没能触发该漏洞,但幸运的是其中一个组合触发了另一个漏洞。虽然这么多年过去了,但这些经典的网络驱动上依然存在着很多问题(蓝海嗷),后续如果有分析文章我会第一时间发布文章,感谢看到这里~。

Windows tcp/ip核弹级漏洞复现

原文始发于微信公众号(山海之关):Windows tcp/ip核弹级漏洞复现

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月5日14:26:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Windows tcp/ip核弹级漏洞复现https://cn-sec.com/archives/3133192.html

发表评论

匿名网友 填写信息