Windows 7 x64 Kernel Exploitation – Stack Overflow (3/3)

In this (short) post, we will explore triggering a stack overflow vulnerability in the kernel. This is a classic exploitation case.

The Vulnerability: TriggerStackOverflow

Similar to the last post, we first inspect the vulnerable function in code. This is a classic stack overflow vulnerability, which should be familiar to all of you:

NTSTATUS TriggerStackOverflow(IN PVOID UserBuffer, IN SIZE_T Size) {
 NTSTATUS Status = STATUS_SUCCESS;
 ULONG KernelBuffer[BUFFER_SIZE] = {0};

// #define BUFFER_SIZE 512 (common.h)

PAGED_CODE();

__try {
 // Verify if the buffer resides in user mode
 ProbeForRead(UserBuffer, sizeof(KernelBuffer), (ULONG)__alignof(KernelBuffer));

DbgPrint("[+] UserBuffer: 0x%p\n", UserBuffer);
 DbgPrint("[+] UserBuffer Size: 0x%X\n", Size);
 DbgPrint("[+] KernelBuffer: 0x%p\n", &KernelBuffer);
 DbgPrint("[+] KernelBuffer Size: 0x%X\n", sizeof(KernelBuffer));

#ifdef SECURE
 // Secure Note: This is secure because the developer is passing a size
 // equal to size of KernelBuffer to RtlCopyMemory()/memcpy(). Hence,
 // there will be no overflow
 RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, sizeof(KernelBuffer));
#else
 DbgPrint("[+] Triggering Stack Overflow\n");

// Vulnerability Note: This is a vanilla Stack based Overflow vulnerability
 // because the developer is passing the user supplied size directly to
 // RtlCopyMemory()/memcpy() without validating if the size is greater or
 // equal to the size of KernelBuffer
 RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);
#endif
 }
 __except (EXCEPTION_EXECUTE_HANDLER) {
 Status = GetExceptionCode();
 DbgPrint("[-] Exception Code: 0x%X\n", Status);
 }

return Status;
}

However, upon inspecting the disassembly, there is a slight discrepancy: instead of calling RtlCopyMemory, the following code sequence is present:

In this case, our exploitation is absolutely no different to a traditional stack overflow, with two key differences.

Exploitation Realities…

Under Win32, it is possible to cleanly return to a nice stack frame. Under 64-bit, this seems more difficult (impossible?) and I’m not sure why – my shellcode doesn’t return cleanly, ever. At the end of the shellcode, we don’t return: we simply enter an infinite loop and lock one CPU.

Due to the above, we can’t spawn a new thread. Instead, we need to spawn a new child process, and elevate *it’s* privileges, instead of our own. This is an easy modification of the last shellcode we used. The observant reader will notice this at the end of our shellcode, represented as \xEB\xFE.

Finishing Touches

Our exploitation approach is, in this case, as follows:

  • Create a cmd.exe child process
  • Prepare our token thief shellcode with our child’s PID
  • Send IOCTL with a buffer long enough to trigger an overflow
  • Return to our shellcode, which gives our child a SYSTEM pid, and then loops infinitely.
  • ??? (probably do bad stuff as SYSTEM)
  • Need to force a shutdown, because process can’t exit otherwise.

In practice:

You’ll notice there’s a delay of 3 seconds, while we wait for a “stable” cmd.exe. This is a lesson learned during my exploitation attempts – if you attempt to modify cmd.exe’s privilege token too quickly, you can get a blue screen.

This exploit is a little (alot!) more stable than the arbitrary overwrite, as we aren’t wrecking HalDispatchTable. As before, the code is available in the download pack with the first post.

I hope you enjoyed this mini-series – the next steps are to upgrade this to Windows 10, and investigate other types of kernel exploitation primitives. I’m sure I’ve missed plenty of stuff – please leave comments if I’ve missed something in my blind stumbling around, and there’s a better way to do things 😀

About Norman

Sometimes, I write code. Occasionally, it even works.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s