Research and Development

The purpose of this document is to present a technical report of the CVE-2013-5065 vulnerability. A few days ago, FireEye identified a 0 day kernel exploit embedded within a PDF document actively used in the wild. The vulnerability itself is present in the NDProxy kernel driver. Whilst this is present in all versions of Windows, the vulnerability itself is only present in Windows 2003 and XP. The NDProxy driver is responsible for interfacing NDISWAN and CoNDIS WAN drivers to the TAPI services.

Binary Information

OS: Windows XP SP3
Name: ndproxy.sys
Base address: 0xF874A000
File version: 5.1.2600.6048
Default path: C:\Windows\System32\drivers\ndproxy.sys

Vulnerability

The vulnerability itself is present in the PxIODispatch() function that is reachable from a simple IO Control.

DeviceIoControl(hDev, 0x8fff23cc, buffer, sizeof(buffer), buffer, sizeof(buffer), &dwRet, 0);

The function works as follows:

  • Reads an index value using the IO control message.
  • Calls a function from a function array using the received index.
.text:F874CE92 PxIODispatch
.text:F874CE92
.text:F874CE92 var_8           = dword ptr -8
.text:F874CE92 var_4           = dword ptr -4
.text:F874CE92 arg_0           = dword ptr  8
.text:F874CE92 LockState       = _LOCK_STATE ptr  0Ch
.text:F874CE92
.text:F874CE92                 mov     edi, edi
.text:F874CE94                 push    ebp
.text:F874CE95                 mov     ebp, esp
.text:F874CE97                 push    ecx
.text:F874CE98                 push    ecx
.text:F874CE99                 and     [ebp+var_4], 0
.text:F874CE9D                 push    ebx
.text:F874CE9E                 mov     ebx, dword ptr [ebp+LockState.LockState]
.text:F874CEA1                 mov     eax, [ebx+60h]
.text:F874CEA4                 cmp     byte ptr [eax], 0Eh
.text:F874CEA7                 mov     ecx, [eax+8]
.text:F874CEAA                 push    esi
.text:F874CEAB                 mov     esi, [ebx+0Ch]                              // Data sent from the IO control.
.text:F874CEAE                 mov     dword ptr [ebp+LockState.LockState], ecx
.text:F874CEB1                 mov     ecx, [eax+4]

...

.text:F874CEEE                 cmp     eax, 8FFF23C8h                              // Checking the IO Control code.
.text:F874CEF3                 jz      loc_F874D07C
.text:F874CEF9                 cmp     eax, 8FFF23CCh                              // two possibilities.
.text:F874CEFE                 jz      loc_F874D07C

...

.text:F874D07C loc_F874D07C:                          
.text:F874D07C                 mov     edi, dword ptr [ebp+LockState.LockState]    // EDI = 0x54.
.text:F874D07F                 push    24h
.text:F874D081                 pop     edx

...

.text:F874D092                 mov     eax, [esi+14h]                              // Data sent from the IO control at 0x14.
.text:F874D095                 sub     eax, 7030101h                               // Compute an index using the given value.
.text:F874D09A                 cmp     eax, edx                                    
.text:F874D09C                 mov     [ebp+var_4], edx
.text:F874D09F                 jbe     short loc_F874D0AD                          // It must be between 0 and 0x24 included!

...

.text:F874D0AD loc_F874D0AD:                         
.text:F874D0AD                 mov     ecx, [esi+1Ch]                              // Data sent from the IO control at 0x1c.
.text:F874D0B0                 lea     eax, [eax+eax*2]                            
.text:F874D0B3                 shl     eax, 2                                      // Index * 12.
.text:F874D0B6                 cmp     ecx, dword_F8752184[eax]
.text:F874D0BC                 mov     dword ptr [ebp+LockState.LockState], eax    // Save the index.
.text:F874D0BF                 jnb     short loc_F874D0CD ; 0x54 - 0x20

...

.text:F874D0CD loc_F874D0CD:                         
.text:F874D0CD                 add     edi, 0FFFFFFE0h                             // 0x54 - 0x20.
.text:F874D0D0                 cmp     ecx, edi                                    // The value at 0x1c must be lower than 0x34.
.text:F874D0D2                 ja      short loc_F874D0C1

...

.text:F874D11B loc_F874D11B:                          
.text:F874D11B                 mov     eax, dword_F87528B4
.text:F874D120                 mov     [esi+0Ch], eax
.text:F874D123                 mov     [esi+8], ebx
.text:F874D126                 mov     dl, byte_F87528C0 
.text:F874D12C                 mov     ecx, edi       
.text:F874D12E                 call    ds:__imp_@KfReleaseSpinLock@8 
.text:F874D134                 mov     eax, [ebx+60h]
.text:F874D137                 or      byte ptr [eax+3], 1
.text:F874D13B                 mov     eax, dword ptr [ebp+LockState.LockState]    // Saved index.
.text:F874D13E                 push    esi
.text:F874D13F                 call    off_F8752188[eax]                           // Call the function at index.

The function table can be seen from the memory, from the first entry to the last one.

kd> .for (r $t0=0; @$t0<=0x24; r $t0=@$t0+1) { dd f8752188+($t0*0xc) L3 }
f8752188  f874d38a 07030102 00000010
f8752194  f874e4ce 07030103 00000008
f87521a0  f874f994 07030104 00000008
f87521ac  f874e824 07030105 000000c0
f87521b8  f874d398 07030106 0000001c
f87521c4  f874d398 07030107 00000018
f87521d0  f874d398 07030108 00000010
f87521dc  f874d38a 07030109 00000010
f87521e8  f874e89c 0703010a 000000f4
f87521f4  f874fac6 0703010b 00000018
f8752200  f874fcae 0703010c 0000004c
f875220c  f874d38a 0703010d 0000000c
f8752218  f874e944 0703010e 00000160
f8752224  f874e9b2 0703010f 0000002c
f8752230  f874eca6 07030110 00000130
f875223c  f874f5c4 07030111 00000028
f8752248  f874d38a 07030112 00000018
f8752254  f874d38a 07030113 00000034
f8752260  f874e58e 07030114 00000054
f875226c  f874fd12 07030115 000000d0
f8752278  f874f240 07030116 00000014
f8752284  f874d370 07030117 00000024
f8752290  f874ff3a 07030118 00000010
f875229c  f874d398 07030119 00000004
f87522a8  f874d398 0703011a 00000008
f87522b4  f874d38a 0703011b 0000000c
f87522c0  f874d398 0703011c 00000010
f87522cc  f874d38a 0703011d 0000000c
f87522d8  f874ed7c 0703011e 00000028
f87522e4  f874d38a 0703011f 0000000c
f87522f0  f874fd8c 07030120 00000018
f87522fc  f874d38a 07030121 0000000c
f8752308  f874edea 07030122 00000010
f8752314  f874d38a 07030123 00000034
f8752320  f874ee78 07030124 00000008
f875232c  f874f05e 00000030 00000034
f8752338  00000038 0000003c 00000040

The last function in the array (index 0×24) points to address 0×00000038. Indeed, if the index submitted through the IO Control is 0×24, this address is called.

Access violation - code c0000005 (!!! second chance !!!)
eax=000001b0 ebx=82263a78 ecx=00000000 edx=00000000 esi=81ffa720 edi=f87528bc
eip=00000038 esp=b2419c18 ebp=b2419c34 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
00000038 ??              ???

Exploitation

This vulnerability is present in Windows XP and Windows 2003. Based on tests, both versions can be leveraged into code execution.

Exploitation of this vulnerability is trivial since it is possible to map address 0×00000001 on those operating systems. Therefore the attacker just needs to insert his kernel shellcode at address 0×00000038 to get it executed. Writing a full exploit for those operating systems is left as an exercise to the reader.

Conclusion

This vulnerability has been seen to be actively used in the wild. As seen in the present blog post, exploitation of this vulnerability is easy and public exploits have already been published. It is recommended to disable NDProxy by running the following commands and rebooting the system while Microsoft issues a fix.

> sc stop ndproxy
> reg add HKLM\System\CurrentControlSet\Services\ndproxy /v ImagePath /t REG_EXPAND_SZ /d system32\drivers\null.sys /f

Disabling NDProxy however can cause side effects including issues in Remote Access Service (RAS), dial-up networking and the interruption of virtual private networking (VPN).

References

Editor’s note: We’ve corrected a slight ambiguity around which versions of Windows are affected, the initial post did not clearly differentiate between versions of Windows that had NDProxy and those that are actually vulnerable.


Request to be added to the Portcullis Labs newsletter

We will email you whenever a new tool, or post is added to the site.

Your Name (required)

Your Email (required)