Loading
0

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

kd> p
tcpip!TcpDeliverDataToClient+0x2ea:
fffff80a`72c21a8a 0f858dfeffff    jne     tcpip!TcpDeliverDataToClient+0x17d (fffff80a`72c2191d)
kd> p
tcpip!TcpDeliverDataToClient+0x2f0:
fffff80a`72c21a90 48837e2000      cmp     qword ptr [rsi+20h],0
来看一下这一段伪代码。
while ( 1 )
{
v70 = v10;
v69 = TcpSatisfyReceiveRequests(v7);
if ( v24 >= v23 )
{
}
else
{
v25 = (char *)ReceiveDpcTable + 24 * v21;
v26 = v23 - v24;
v27 = v7[2];
v70 = v26;
*(_QWORD *)(*(_QWORD *)(v27 + 128) + (v21
v28 = *((_DWORD *)v25 + 5);
if ( v28 & 1 )
*((_DWORD *)v25 + 5) = v28 | 4;
else
TcpStartRcvWndTuningTimer(vars38);
v6[4] -= v26;
v29 = v6[9];
v6[3] = 0i64;
if ( v26 + v29 )
{
TcpAdvanceTcbRcvWnd(v7, (unsigned int)(v26 + *((_DWORD *)v6 + 18)));
v6[9] = 0i64;
}
else
{
v6[9] = 0i64;
}
}
if ( !(v6[3] + v6[4]) )
break;
在伪代码最后的位置,会对两个值进行判断,如果两个值之和为0,则条件成立,程序会跳出循环,刚才的跟踪我们可以发现,v6就是结构体,v6[4]的值来源于它自身减v26,而v26就是它自身,最后它的值为0,而刚才跟踪v6[3]的值也为0(如果知道结构体就好清楚v6到底是什么了T.T)。
经过对比调试,发现在正常的处理SMB Tree Connect包和触发BSOD的不正常情况下有一处关键的跳转逻辑,这里是一处if语句判断,成立则break跳出while循环,不成立,会继续执行。

那么不正常的情况呢?之前的处理和之前的分析一样,我们加大Data的值到1200,但是在返回后。
kd> p
tcpip!TcpDeliverDataToClient+0x2b9:
fffff80a`72c21a59 48297b20        sub     qword ptr [rbx+20h],rdi
kd> r rdi
rdi=0000000000000404
kd> dd rbx+20
ffffc10c`a0643e78  00000504
显而易见,在我们加大Data长度的时候,到相减位置结构体对应位置的值是504,也就是1284,正好是Data的长度1200字节 + 刚才分析到的84字节,而此时rdi的值只有0x404,也就是944长度,这是一个Max值,如果Data长度超过0x404,这里会认为还有数据,因此相减后v6[4]的值不为0。
也就是说在SMB Tree Connect数据交互过程中,TcpDeliverDataToClient中关于这个地方的逻辑处理是,会根据数据包的长度,如果数据包长度小于0x404,则相减时v26的值是长度本身,然后会break。如果数据包长度大于0x404,则v26的值为max值,也就是0x404,相减不为0,则不会break。
kd> p
tcpip!TcpDeliverDataToClient+0x2bd:
fffff80a`72c21a5d 4533ed          xor     r13d,r13d
kd> dd rbx+20
ffffc10c`a0643e78  00000100
这造成了一个问题,就是刚才到的break位置由于v6[4]不为0,所以不执行break,而是进入后续的处理。
kd> p
tcpip!TcpDeliverDataToClient+0x2e2:
fffff80a`72c21a82 488b4320        mov     rax,qword ptr [rbx+20h]
kd> p
tcpip!TcpDeliverDataToClient+0x2e6:
fffff80a`72c21a86 48034318        add     rax,qword ptr [rbx+18h]
kd> p
tcpip!TcpDeliverDataToClient+0x2ea:
fffff80a`72c21a8a 0f858dfeffff    jne     tcpip!TcpDeliverDataToClient+0x17d (fffff80a`72c2191d)
kd> p
tcpip!TcpDeliverDataToClient+0x17d:
fffff80a`72c2191d 49833f00        cmp     qword ptr [r15],0
kd> p
tcpip!TcpDeliverDataToClient+0x181:
fffff80a`72c21921 0f85e9010000    jne     tcpip!TcpDeliverDataToClient+0x370 (fffff80a`72c21b10)
接下来,程序会回到while入口位置,接下来会进入之前提到没有进入的if语句处理,这是由于刚才没有break结束循环的原因,此时会进入if语句的处理,函数中所调用的函数都是Complete,猜测都是和结束数据包相关处理有关。

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