CVE:CVE-2008-4114
CNNVD:CNNVD-200809-231
Windows是微软发布的非常流行的操作系统。
Windows的srv.sys驱动处理畸形WRITE_ANDX SMB报文的方式存在内核拒绝服务漏洞，如果未经认证的远程攻击者能够向使用命名管道端点的接口发送WRITE_ANDX报文的话，就可以触发这个漏洞。
Srv.sys是用于处理SMB报文的驱动。报文被解析后，会通过合适的驱动路由。以下是srv.sys解析报文某些重要字段的方式：
Módulo: srv.sys Vista SP1
PAGE:00048583 movzx ecx, word ptr [ebx+17h] ; Packet. DataOffset
PAGE:00048587 mov [ebp+var_50], ecx
PAGE:0004858A mov eax, [esi+78h]; Packet
PAGE:0004858D add eax, ecx; Packet.Data[]
PAGE:0004858F mov [ebp+VirtualAddress], eax
PAGE:00048592 mov eax, [esi+6Ch]
PAGE:00048595 mov eax, [eax+10h]
PAGE:00048598 sub eax, ecx; Real packet len - DataOffset PAGE:0004859A movzx edi, word ptr [ebx+15h];
Packet.DataLen PAGE:0004859E cmp edi, eax
PAGE:000485A0 jbshort loc_485A4
PAGE:000485A2 mov edi, eax
在这部份代码中，驱动应添加检查，以防在偏移与报文真实大小不一致时仍然继续。之后srv.sys构建(或重新使用)FILESYSTE_CONTROL IRP(0xD)，其IOCTL为0x119FF8(FSCTL_PIPE_INTERNAL_WRITE, METHOD_BUFFERED)，然后通过调用IofCallDriver将这个IRP发送给正确的驱动。IRP包含有报文，但如果考虑到报文的内部字段，这并不意味IRP在内存使用方面保持一致。
Módulo: srv.sys Vista SP1
PAGE:00048C90 pushebx ; int
PAGE:00048C91 pushebx ; int
PAGE:00048C92 pushebx ; int
PAGE:00048C93 pushebx ; int
PAGE:00048C94 pushedi ; int
PAGE:00048C95 push[ebp+VirtualAddress] ; int
PAGE:00048C98 push119FF8h ; int
PAGE:00048C9D push0Dh ; char
PAGE:00048C9F pushesi ; int
PAGE:00048CA0 mov eax, [ebp+FileInformation]
PAGE:00048CA3 pushdword ptr [eax+38h] ; FileObject
PAGE:00048CA6 pushdword ptr [esi+80h] ; Irp
PAGE:00048CAC call_SrvBuildIoControlRequest@44 ; SrvBuildIoControlRequest(x,x,x,x,x,x,x,x,x,x,x)
PAGE:00048D23 mov edx, [esi+80h]
PAGE:00048D29 mov ecx, [ebp+var_44]
PAGE:00048D2C callds:__imp_@IofCallDriver@8 ; IofCallDriver
这个IRP由npfs!NpCommonFileSystemControl处理。
Módulo: npfs.sys Vista SP1
PAGE:0001885C loc_1885C:; CODE XREF: NpCommonFileSystemControl(x,x)+E7 j
PAGE:0001885C cmp eax, 119FF8h
PAGE:00018861 jzshort loc_18896
PAGE:00018896 loc_18896:; CODE XREF: NpCommonFileSystemControl(x,x)+139 j
PAGE:00018896 lea eax, [ebp+var_C]
PAGE:00018899 pusheax
PAGE:0001889A pushedx
PAGE:0001889B push[ebp+Irp]
PAGE:0001889E call_NpInternalWrite@12 ; NpInternalWrite(x,x,x)
在这个例程中，到达npfs!NpWriteDataQueue可能触发bug。
Npfs从列表获得包含有某些与连接相关的尚未完成IRP的项。
Módulo: npfs.sys Vista SP1
PAGE:0001A187 pushesi
PAGE:0001A188 push[ebp+arg_0]
PAGE:0001A18B call_NpGetNextRealDataQueueEntry@8 ; NpGetNextRealDataQueueEntry(x,x)
驱动对检索到的项执行检查。由于这个检查，无法在memcpy调用中触发溢出：
Módulo: npfs.sys Vista SP1
loc_1A1F6:; CODE XREF: NpWriteDataQueue(x,x,x,x,x,x,x,x,x,x)+92 j
PAGE:0001A1F6 mov ecx, [ebx]; Packet.DataLen
PAGE:0001A1F8 cmp ecx, edi;Entry.BufferLen ( 0x400 )
PAGE:0001A1FA jnb short loc_1A1FE
PAGE:0001A1FC mov edi, ecx
PAGE:0001A1FE
PAGE:0001A1FE loc_1A1FE:; CODE XREF: NpWriteDataQueue(x,x,x,x,x,x,x,x,x,x)+A0 j
PAGE:0001A1FE cmp dword ptr [eax+10h], 1
PAGE:0001A202 jzshort loc_1A22D
PAGE:0001A204 testedi, edi
PAGE:0001A206 jbe short loc_1A22D
PAGE:0001A208 push5246704Eh ; Tag
PAGE:0001A20D pushedi ; NumberOfBytes
PAGE:0001A20E push0 ; PoolType
PAGE:0001A210 call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
换句话说，对于任何memcpy可能拷贝的字节数，都会动态分配相同数量的字节数。因此，无法强制溢出的情况。
最后是触发bug的代码段：
PAGE:0001A23E push edi ; size_t
PAGE:0001A23F mov eax, [ebp+arg_8] ; &Packet + Packet.DataOffset
PAGE:0001A242 sub eax, [ebx] ; (&Packet + Packet.DataOffset) Packet.DataLength
PAGE:0001A244 add eax, [ebp+arg_C] ; &Packet + (Curr
solution:Upgrade microsoft windows_2000 to a higher version than *:sp4,and avoid the version *:sp4; Upgrade microsoft windows_server_2003 to a higher version than *,*:sp1,*:sp2,and avoid the version *:sp1,*:sp2; Upgrade microsoft windows_server_2008 to a higher version than *; Upgrade microsoft windows_vista to a higher version than *:gold,*:sp1,gold,sp1,and avoid the version *:gold,*:sp1,gold,sp1; Upgrade microsoft windows_xp to a higher version than *,*:sp2,*:sp3,and avoid the version *:sp2,*:sp3