Windows TCP/IP远程执行代码漏洞分析( 二 )

第一个循环用于验证各个header的有效性,首先获取第一个option包,length为0x4,实际字节数为length*8=0x20个字节,首先更新_net_buffer结构,根据实际字节数计算option的偏移,解析到后面的option2,后面依次根据option.length 解析到option3, option4 ……

Windows TCP/IP远程执行代码漏洞分析

文章插图
 
所以并没有处理'x18x22',因此绕过了【1】处case:0x18中对length的验证 。所以如果Option1.length设为3时,构造图中的包由于长度0x22校验不通过,会当成无效包被舍弃 。
第二个循环处理各个option包,但在case:0x19 的Ipv6pUpdateRDNSS函数中,计算ipv6地址个数是通过(length-1)/2,这样导致length=0x4时和length=0x3时计算的结果一样,都是根据ipv6地址个数*8+8(Type/Length/ Reserved/Lifetime),所以跳过0x18个字节解析到'x18x22',将其当成了type=0x18的option包,并且没有了长度的验证 。
Windows TCP/IP远程执行代码漏洞分析

文章插图
 
综上,漏洞是由于检查和解析包时根据length计算的偏移不同,导致绕过检查,解析到攻击者伪造的option包,造成栈溢出 。
0x03 漏洞利用具体调试利用过程如下:
(1)首先进入循环1中的【2】处,判断length实际字节数是否小于0x18,然后调用NdisAdvanceNetBufferDataStart,更新_NET_BUFFER结构,得到下一个Option的偏移,依次处理后面的Option:
Windows TCP/IP远程执行代码漏洞分析

文章插图
 
调用NdisAdvanceNetBufferDataStart前:
kd> dt ndis!_NET_BUFFER @r14+0x000 Next: (null)+0x008 CurrentMdl: 0xffffe20b`aea77e70 _MDL+0x010 CurrentMdlOffset : 0x10+0x018 DataLength: 0x188+0x018 stDataLength: 0x188+0x020 MdlChain: 0xffffe20b`b0a9c220 _MDL+0x028 DataOffset: 0x70+0x000 Link: _SLIST_HEADER+0x000 NetBufferHeader: _NET_BUFFER_HEADER+0x030 ChecksumBias: 0+0x032 Reserved: 0+0x038 NdisPoolHandle: 0xffffe20b`ae45cb40 Void+0x040 NdisReserved: [2] (null)+0x050 ProtocolReserved : [6] 0x00000198`00000000 Void+0x080 MiniportReserved : [4] (null)+0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0+0x0a8 SharedMemoryInfo : (null)+0x0a8 ScatterGatherList : (null) kd> dt ndis!_MDL 0xffffe20b`aea77e70+0x000 Next: 0xffffe20b`aea77b10 _MDL+0x008 Size: 0n56+0x00a MdlFlags: 0n4+0x00c AllocationProcessorNumber : 0xffff+0x00e Reserved: 0xffff+0x010 Process: (null)+0x018 MappedSystemVa: 0xffffe20b`aea77eb0 Void+0x020 StartVa: 0xffffe20b`aea77000 Void+0x028 ByteCount: 0x30+0x02c ByteOffset: 0xeb0kd> db 0xffffe20b`aea77eb0+0x10ffffe20b`aea77ec019 04 00 00 00 00 03 84-30 30 30 30 30 30 30 30........00000000// <--- Option1ffffe20b`aea77ed030 30 30 30 30 30 30 30-18 22 fd 81 00 00 03 8400000000."......ffffe20b`aea77ee000 bf 09 02 73 6d 41 72-00 00 03 00 dd bf 04 04....smAr........调用NdisAdvanceNetBufferDataStart后:
kd> dt ndis!_NET_BUFFER @r14+0x000 Next: (null)+0x008 CurrentMdl: 0xffffe20b`aea77b10 _MDL+0x010 CurrentMdlOffset : 0+0x018 DataLength: 0x168+0x018 stDataLength: 0x168+0x020 MdlChain: 0xffffe20b`b0a9c220 _MDL+0x028 DataOffset: 0x90+0x000 Link: _SLIST_HEADER+0x000 NetBufferHeader: _NET_BUFFER_HEADER+0x030 ChecksumBias: 0+0x032 Reserved: 0+0x038 NdisPoolHandle: 0xffffe20b`ae45cb40 Void+0x040 NdisReserved: [2] (null)+0x050 ProtocolReserved : [6] 0x00000198`00000000 Void+0x080 MiniportReserved : [4] (null)+0x0a0 DataPhysicalAddress : _LARGE_INTEGER 0x0+0x0a8 SharedMemoryInfo : (null)+0x0a8 ScatterGatherList : (null) kd>dt ndis!_MDL 0xffffe20b`aea77b10+0x000 Next: 0xffffe20b`aea78890 _MDL+0x008 Size: 0n56+0x00a MdlFlags: 0n4+0x00c AllocationProcessorNumber : 0xe20b+0x00e Reserved: 0xffff+0x010 Process: (null)+0x018 MappedSystemVa: 0xffffe20b`aea77b50 Void+0x020 StartVa: 0xffffe20b`aea77000 Void+0x028 ByteCount: 0x30+0x02c ByteOffset: 0xb50kd> db 0xffffe20b`aea77b50ffffe20b`aea77b5019 05 00 00 00 00 03 84-41 41 41 41 41 41 41 41........AAAAAAAA// <--- Option2ffffe20b`aea77b6041 41 41 41 41 41 41 41-42 42 42 42 42 42 42 42AAAAAAAABBBBBBBBffffe20b`aea77b7042 42 42 42 42 42 42 42-19 05 00 00 00 00 03 84BBBBBBBB........(2)进入循环2中的【4】处:
Windows TCP/IP远程执行代码漏洞分析

文章插图
 
进入Ipv6UpdateRDNSS,处理第一个type为0x19,length为4的option,Ipv6pUpdateRDNSS 中计算IPv6 地址数量是通过下面代码实现的:
Windows TCP/IP远程执行代码漏洞分析

文章插图
 
调试结果如下:
Windows TCP/IP远程执行代码漏洞分析

文章插图
 
rbx 保存option 包的起始位置,[rbx+1] 取的是length字段的值,此时为4,esi的值为1,ecx的值为2,所以这段汇编的计算的ipv6地址个数为(length-1)/2 =1 .


推荐阅读