kASLR

kASLR (Kernel Address Space Layout Randomization) is a security feature that randomises the kernel's memory layout to try and mitigate exploitation techniques.

To create our ROP chain we need to defeat kASLR. When we are running code in medium integrity we can call the EnumDeviceDrivers Win32 API.

In our exploit code we need to add the psapi.h header:

#include <psapi.h>

The EnumDeviceDrivers Win32 API retrieves the loaded address for each device driver in the system. Luckily for us the kernel module is the first that is loaded:

#define ARRAY_SIZE 1024

uint64_t GetKernelBase()
{
    LPVOID drivers[ARRAY_SIZE];
    DWORD cbNeeded;
    EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded);
    return (uint64_t)drivers[0];
}

The GetKernelBase() function retrieves the base address of the kernel module in memory.

It uses the EnumDeviceDrivers function to enumerate the loaded device drivers and retrieves the base addresses of the drivers into the drivers array. The function then returns the base address of the first driver, which is assumed to be the kernel module.

We can take this base address and add our offsets we discovered in the previous section to create our rop gadgets:

// get the kernel base address
uint64_t kernelBase = GetKernelBase();
printf("[+] Kernel base is: 0x%p\n", kernelBase);

// rop gadgets
uint64_t POP_RCX = kernelBase + 0x3c66ce;
uint64_t MOV_CR4_RCX = kernelBase + 0x3d6325;

The exploit buffer can be formed as such:

In this code snippet, the ROP chain is being constructed in the buffer array. The index variable on line 2 keeps track of the current index in the ROP chain.

First, the rop pointer is calculated (on line 9) by adding the offset value to the base address of buffer. This points to the location in the buffer where the ROP chain will be constructed.

Next, specific ROP gadgets are placed in the ROP chain, lines 12 through 14.

The return address to the alloc shellcode is set in the ROP chain on lin 17.

Debugging

We can debug our exploit so far. If we have defeated kASLR, DEP and SMEP we should be able to execute our shellcode, albeit a chain of nop instructions.

The entire code is shown below:

Compile the code, copy it to the target host, ensure the driver is running and attach the debugger.

We are going to step through the ROP chain, first we can add a breakpoint to our first gadget. Break into the host and add the following breakpoint:

Continue the debugger with the g command, then run the exploit on the target host, the breakpoint should get hit:

Enter the p command twice to execute our first gadget then examine the rcx register:

We can see that our intender cr4 value has been placed in rcx. Next, look at the value in cr4:

As expected, this shows that SMEP is enabled. Enter the p command twice to execute our second gadget then re-examine the cr4 register:

This shows that SMEP has been disabled. If we look at the next instruction we will observe that our shellcode in user mode is about to be executed:

Press g to continue, and the debugger should hit our int3 breakpoint:

This is good news! We have defeated DEP, kASLR and SMEP to execute our shellcode in user space. All we have left to do is to exploit this with some privilege escalation shellcode.

We will need to reboot the target host, if we continue execution the OS will crash. Issue the .reboot command to reboot the OS.

Demo

Work in progress

Last updated