On the (im)possibility of MS11-083

We know all you guys are really excited about the release of MS11-083. As you expected on this blog, this posting gives you more detailed analysis and *fake* PoC exploits. Please keep in mind this analysis is not based on the fundamental and fine grained analysis, thus it could be totally wrong.

Before getting into the details, reading these links would be helpful.

http://www.reddit.com/r/netsec/comments/m52ex/ms11083_remote_kernel_exploit_via_crafted_udp/
http://blogs.technet.com/b/srd/archive/2011/11/08/assessing-the-exploitability-of-ms11-083.aspx?utm_source=twitterfeed&utm_medium=twitter
http://www.twitlonger.com/show/e30d0n

As always, DarunGrim gives a nice diffing result. It Seems like a refcount bug in MS11-083 not only involves IppRateLimitIcmp(), but also involves (mysterious) TCP & MFE handlings. (i’m sick of uploading the screen shot. Hope this would be enough for you to understand)


_IppDispatchMfeQueuedPackets@8 0 9 1 _IppDispatchMfeQueuedPackets@8 0 9 1 None
_IppRateLimitIcmp@4 0 2 4 _IppRateLimitIcmp@4 2 2 4 None
_TcpExitBHModeDuetoAckRcved@4 0 15 1 _TcpExitBHModeDuetoAckRcved@4 1 15 1 None
_TcpExitBHModeDuetoNextHopChange@4 0 15 1 _TcpExitBHModeDuetoNextHopChange@4 1 15 1 None
_TcpExitBHModeDuetoTimeout@4 0 15 1 _TcpExitBHModeDuetoTimeout@4 1 15 1 None
_TcpGetTcbConnectionObject@12 0 92 0 _TcpGetTcbConnectionObject@12 2 92 0 None
_TcpSetSockOptTcb@40 0 157 1 _TcpSetSockOptTcb@40 1 157 1 None
_TcpTryToEnterBHMode@4 0 43 31 _TcpTryToEnterBHMode@4 2 42 30 None

For IppRateLimitIcmp(), the only difference is whether to invoke dereference routines (either IppDereferenceNeighbor() or IppDereferenceLocalAddress()) depending on the connections.
For the rest of this posting, I’ll assume we are on the neighbor situation.

The data structure (let’s say context), which is passed as the 1st argument of IppRateLimitIcmp(), can be described as follows.


------------------
pContext+0 : string specifier (either "Ipla" (local address) or "Ipne" (neighbor)
pContext+4 : refCount // a reference counter
pContext+8 : ??
pContext+c : pBuf // pointer to the buffer where the usage is monitored by the refCount above
------------------

If you send a bunch of UDP packets to a closed port (only if it reached some limit number of trials), then a reference counter for context will be increased.
Then, IppRateLimitIcmp() is supposed to dereference context by 1) refCount=refCount-1 if refCount > 0, or 2) free(pContext+0xC) if refCount == 0.
However, because IppRateLimitIcmp() in the old version missed to invoke dereference routines, *desired* exploit steps would be as follows.


Step1. increase refCount until it reaches INT_MAX
Step2. increase refCount once/twice, then refCount will be 0/1 because of an integer overflow.
Step3. explicitly invoke dereferece routine (sending UDP packets will not invoke dereference routines for you because this is the cause of MS11-083!)

As far as we know, to achieve step1, we need to send 2^32 UDP packets. For this massive packet sending, Yeong Jin came up with the interesting idea by simply assuming that this massive packet sending is already done (and this is why we call this as *fake* exploit).
For step3, the cross reference of IppDereferenceNeighbor() included Ipv4pHandleEchoRequest(). Haha… Ipv4pHandleEchoRequest() would be triggered by sending simple ICMP echo requests.

Good. The working steps of *fake* exploit are as follows.


Step1. set the conditional breakpoint on IppRateLimitIcmp(), and set refCount value as 0xfffffc00 when it's fired.
Step2. send a packet to a closed port (increase refCount)
Step3. send a ECHO request (explicitly invoke a dereference routine)
Step4. go back to Step2

Note that the timing issues of Windows packet handling are important because step3 would decrease refCount.
Have a fun guys. Below we’ve attached the windbg crash dumps.


kd> bp tcpip!IppRateLimitIcmp+0x28 "j (poi(@eax+4) & 0x0`000000ff) = 0x0`00000010 'dd eax eax+4;ed eax+4 ffffffc0;dd eax eax+4;gc';'gc'"
kd> bp tcpip!IppDereferenceNeighborPrimitive+0x17 "dd eax eax+4;gc"
kd> g
85566260 656e7049 00000000
855660e0 656e7049 00000000
85566320 656e7049 00000000
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000010
85ef5300 656e7049 ffffffc0
85ef5300 656e7049 00000000
85ef5300 00000000 00000000
85ef5300 85ef5300 00000000
85ef5300 85ef5300 00000000
85ef5300 85ef5300 00000000
85ef5300 85ef5300 00000000
85ef5300 85ef5300 00000000
85ef5300 85ef5300 00000000

*** Fatal System Error: 0x000000d1
(0x00000000,0x00000002,0x00000001,0x8709C1BE)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

Connected to Windows 7 7600 x86 compatible target at (Thu Nov 10 10:25:31.728 2011 (UTC - 5:00)), ptr64 FALSE
Loading Kernel Symbols
...............................................................
................................................................
........................
Loading User Symbols

Loading unloaded module list
.....
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck D1, {0, 2, 1, 8709c1be}

Probably caused by : E1G60I32.sys ( E1G60I32!RxProcessReceiveInterrupts+108 )

Followup: MachineOwner
---------

nt!RtlpBreakWithStatusInstruction:
828864d4 cc int 3
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: 00000000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: 8709c1be, address which referenced memory

Debugging Details:
------------------

WRITE_ADDRESS: 00000000

CURRENT_IRQL: 2

FAULTING_IP:
tcpip!IpFlcReceivePackets+13f
8709c1be 830701 add dword ptr [edi],1

DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT

BUGCHECK_STR: 0xD1

PROCESS_NAME: System

TRAP_FRAME: 829416f4 -- (.trap 0xffffffff829416f4)
ErrCode = 00000002
eax=00000020 ebx=84fb0c90 ecx=85ade4b0 edx=84fbb008 esi=84fad000 edi=00000000
eip=8709c1be esp=82941768 ebp=829417ec iopl=0 nv up ei ng nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010292
tcpip!IpFlcReceivePackets+0x13f:
8709c1be 830701 add dword ptr [edi],1 ds:0023:00000000=????????
Resetting default scope

LAST_CONTROL_TRANSFER: from 828f7f95 to 828864d4

STACK_TEXT:
829412bc 828f7f95 00000003 5d20c96e 00000065 nt!RtlpBreakWithStatusInstruction
8294130c 828f8a91 00000003 00000000 8709c1be nt!KiBugCheckDebugBreak+0x1c
829416d4 828617cb 0000000a 00000000 00000002 nt!KeBugCheck2+0x68b
829416d4 8709c1be 0000000a 00000000 00000002 nt!KiTrap0E+0x2cf
829417ec 8709bbf5 85b9ac30 00000000 00000001 tcpip!IpFlcReceivePackets+0x13f
82941868 8709bd66 85bd2d00 85ade410 00000000 tcpip!FlpReceiveNonPreValidatedNetBufferListChain+0x746
8294189c 828ab0ca 85ade410 5d20c366 84170e28 tcpip!FlReceiveNetBufferListChainCalloutRoutine+0x11e
82941904 8709bdee 8709bc48 8294192c 00000000 nt!KeExpandKernelStackAndCalloutEx+0x132
82941940 86ef318d 85bd2d02 85ade400 00000000 tcpip!FlReceiveNetBufferListChain+0x7c
82941978 86ee1670 85bcd008 85ade410 00000000 ndis!ndisMIndicateNetBufferListsToOpen+0x188
829419a0 86ee15e7 00000000 854ca0e0 85aefe10 ndis!ndisIndicateSortedNetBufferLists+0x4a
82941b1c 86e9421d 854ca0e0 00000000 00000000 ndis!ndisMDispatchReceiveNetBufferLists+0x129
82941b48 86e8cca5 854ca0e0 85ade410 00000000 ndis!ndisMDispatchReceiveNetBufferListsWithLock+0x60
82941b64 86ee1a2e 854ca0e0 85ade410 00000000 ndis!ndisMTopReceiveNetBufferLists+0x2d
82941b8c 86e8cc1e 854ca0e0 85ade410 00000000 ndis!ndisMIndicateReceiveNetBufferListsInternal+0x62
82941bb4 8cb797f4 854ca0e0 85ade410 00000000 ndis!NdisMIndicateReceiveNetBufferLists+0x52
82941bfc 8cb7877e 00000000 85aedcf0 00000002 E1G60I32!RxProcessReceiveInterrupts+0x108
82941c14 86ee1309 015cc160 00000000 82941c40 E1G60I32!E1000HandleInterrupt+0x80
82941c50 86e8c9f4 85aedd04 00aedcf0 00000000 ndis!ndisMiniportDpc+0xe2
82941c78 828834f5 85aedd04 85aedcf0 00000000 ndis!ndisInterruptDpc+0xaf
82941cd4 82883358 82944d20 8294e280 00000000 nt!KiExecuteAllDpcs+0xf9
82941d20 82883178 00000000 0000000e 00000000 nt!KiRetireDpcList+0xd5
82941d24 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x38

STACK_COMMAND: kb

FOLLOWUP_IP:
E1G60I32!RxProcessReceiveInterrupts+108
8cb797f4 8b45e8 mov eax,dword ptr [ebp-18h]

SYMBOL_STACK_INDEX: 10

SYMBOL_NAME: E1G60I32!RxProcessReceiveInterrupts+108

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: E1G60I32

IMAGE_NAME: E1G60I32.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 483de743

FAILURE_BUCKET_ID: 0xD1_E1G60I32!RxProcessReceiveInterrupts+108

BUCKET_ID: 0xD1_E1G60I32!RxProcessReceiveInterrupts+108

Followup: MachineOwner
---------

Byoungyoung Lee, Yeong Jin Jang

Advertisements

5 thoughts on “On the (im)possibility of MS11-083

  1. Pingback: MS11-083 – Hacka Windows genom stängda portar | SAFESIDE-bloggen

  2. Pingback: MS11-083 Analysis | h4x0r.co.uk

  3. Pingback: Microsoft UDP Vulnerability: A Tester’s Perspective on MS11-083 « Network Technology Lab

  4. Pingback: Reverse Engineering Tools Part 1: BinDiff - Insinuator

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s