Kernel Address Space Layout Randomization (KALSR)
Last updated
Last updated
KASLR acts as a kernel space mitigation to make control flow jacking attacks harder by randomizing the base address of the kernel on boot. By randomizing the base address, we can no longer hard code values to jump to in kernel memory. Just like userspace ASLR, we need some form of leak to know where to jump to next.
Without KASLR you can see through /proc/kallsyms that kernel space addresses are the same across boots. For this example, users have access to /proc/kallsyms , which gives us function pointer leaks.
Since this randomization happens only once on boot, any function pointer leak while the kernel is booted can be used to determine the kernel base address! This means we can read our kernel symbols with cat /proc/kallsyms
and we can use those in our exploit. Alternatively, I've written a function below to open /proc/kallsyms and extract out the commitcreds and preparekernel_cred functions
We don't always have access to /proc/kallsyms . Often we need to leak out a useful address to determine the kernel base address. A very popular address to leak is the tty_operations
address through the tty_struct
. We can leak this address when our problem/module will allocate an object around 0x2e8 in size and performs an overread. I've written an example kernel module that we'll use to leak the kernel base address below:
The important thing to note with this module is that we allocate 0x400 bytes, but in the device_read
function, we accept any number of bytes for a read. We can trigger a leak by calling read
on the file descriptor, but without knowing what's next to it, we can't be certain that we're leaking anything useful.
That's where /dev/ptmx comes into play! This handy character device allocates a struct through kmalloc and places in the heap with a function pointer that we can leak right near the beginning of it. The struct looks a little something this:
The magic value in the header makes it even more useful for leaking, since we can always determine if our leak was successful or not! For my code example, my plan of attack is to open the kernel-leak module, then open the /dev/ptmx so that we allocate our heap buffer first, then the ttystruct buffer. Then I'll perform the read on the kernel-leak buffer to overread past our buffer into the ttystruct buffer.
Why do we care about the tty_operations pointer? It points to ptm_unix98_ops
which has a hardcoded offset from our kernel base! We can find our kernel base address by looking through /proc/kallsyms really quick and grepping for startup_64
Then we can take out tty_operations address and subtract it by our base address to get our offset!
0xFFFFFFFFA966B880 - 0xffffffffa8600000
gave me an offset of 0x106b880
which I can now apply to our tty_operations leak. Full exploit here