Loading
0

SMBv3远程拒绝服务(BSOD)漏洞分析

漏洞分析
刚开始,我天真的以为是CopyData引发的某些异常,后来发现我错了,其实这个漏洞可以看成利用tcpip.sys中的某些逻辑特性,以及mrxsmb20.sys中对于相关结构的检查不够严格导致的空指针引用BSOD,而整个漏洞形成,我是利用正常和不正常的对比才终于发现。在分析的过程中,大量不透明的结构体引用让我有点尴尬,期待更熟悉SMB的大牛能够继续丰富分析。
正常的SMB2 Tree Connect包是不会触发异常的。

首先我们来看一下正常的逻辑调用,关键函数在tcpip.sys中的TcpDeliverDataToClient,这个函数负责处理接收到的数据包,在一个while(1)循环中。
char __fastcall TcpDeliverDataToClient(PKSPIN_LOCK SpinLock, KSPIN_LOCK *a2, _QWORD *a3, _QWORD **a4)
{
while ( 1 )
{
……
v22 = (unsigned int)vars30;
v23 = TcpIndicateData(v7, v6, v5, &v72);
v24 = v71;
if ( !(v6[3] + v6[4]) )
break;
……
在这个循环中,刚进入循环位置有一个if语句,后面我们会提到,在接收到TreeConnect包之后,不会进入if语句,而是执行下面的函数调用,在TcpIndicateData函数内部会调用到之前提到的Smb2TreeConnect_Receive,注意这一切现在都是在我们发送一个正常数据包时完成的。(接下来我们会分析到为什么是正常的)
在这个函数入口下条件断点。
kd> bp tcpip!TcpDeliverDataToClient ".if(poi(rbx+20)==0x1E4){;}.else{g;}"
kd> g
tcpip!TcpDeliverDataToClient:
fffff801`f18017a0 4055            push    rbp
kd> dd rbx+20 L1
ffffb304`06865c58  000001e4
命中时,rbx会存放一个结构体,这个结构体按照IDA的反馈来看是一个KSPIN_LOCK自旋锁,windows内核同步处理的一种机制,这个暂且不管,注意一下rbx结构体+20位置的值,是1e4,这个值转换成10进制就是484,正好是我们发送的400个C的Data数据加刚才我们提到的头部84字节的长度。
接下来进入TcpIndicateData函数后会命中Smb2TreeConnect_Receive函数开始进行接收处理。
kd> p
tcpip!TcpDeliverDataToClient+0x209:
fffff801`f18019a9 e8e2810100      call    tcpip!TcpIndicateData (fffff801`f1819b90)
kd> dd rbx
ffffb304`06865c38  aa9ce398 fffff801 00000000 00000000
ffffb304`06865c48  00000000 00000000 00000000 00000000
ffffb304`06865c58  000001e4 00000000 00000000 00000000
ffffb304`06865c68  00000000 00000000 00000000 00000000
ffffb304`06865c78  06865c60 ffffb304 00000000 00000000
ffffb304`06865c88  00000000 00000000 00000000 00000000
ffffb304`06865c98  00000000 00000000 00000000 00000000
ffffb304`06865ca8  00000000 00000000 00000000 00000001
kd> p
Breakpoint 1 hit
mrxsmb20!Smb2TreeConnect_Receive:
fffff801`f3fbc4b0 48895c2420      mov     qword ptr [rsp+20h],rbx
处理过程很长,这里我直接略过,在处理结束后会多层ret后返回到TcpDeliverDataToClient函数中,仍然处于while循环中。
kd> bp tcpip!TcpIndicateData+0x268
kd> g
Breakpoint 3 hit
tcpip!TcpIndicateData+0x268:
fffff80a`72c39df8 c3              ret
kd> p
tcpip!TcpDeliverDataToClient+0x20e:
fffff80a`72c219ae 833defa51a0001  cmp     dword ptr [tcpip!MICROSOFT_TCPIP_PROVIDER_Context+0x24 (fffff80a`72dcbfa4)],1
kd> p
tcpip!TcpDeliverDataToClient+0x215:
fffff80a`72c219b5 448bf0          mov     r14d,eax
这里我列举一下返回过程的逐层调用逻辑,因为kb回溯不到。Smb2TreeConnect_Receive -> SmbReceiveInd -> VctIndRecv -> SmbWskReceiveEvent -> afd!WskProTLEventReceive -> tcpip!TcpIndicateData -> tcpip!TcpDeliverDataToClient。
接下来就是关键了,首先会执行一处sub汇编指令。
kd> p
tcpip!TcpDeliverDataToClient+0x2b9:
fffff80a`72c21a59 48297b20        sub     qword ptr [rbx+20h],rdi
kd> r rdi
rdi=00000000000001e4
kd> dd rbx+20 L1
ffffc10c`9fe79e78  000001e4
这个相减之后,会将rbx结构体对应的长度变成0,随后,会到达一处cmp操作,这处cmp操作会将这个值作为一个判断条件。
kd> p
tcpip!TcpDeliverDataToClient+0x2de:
fffff80a`72c21a7e 4c896b48        mov     qword ptr [rbx+48h],r13
kd> p
tcpip!TcpDeliverDataToClient+0x2e2:
fffff80a`72c21a82 488b4320        mov     rax,qword ptr [rbx+20h]
kd> dd rbx+18 L1
ffffc10c`9fe79e70  00000000
kd> dd rbx+20 L1
ffffc10c`9fe79e78  00000000
kd> p
tcpip!TcpDeliverDataToClient+0x2e6:
fffff80a`72c21a86 48034318        add     rax,qword ptr [rbx+18h]

分页阅读: 1 2 3 4 5
【声明】:8090安全小组门户(https://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。