# Setup

## Overview

The kernel module used for these exercises is based off `hxpCTF 2020` `kernel-rop` . It didn't come with source, so I rewrote it and have it uploaded [here](https://github.com/ChrisTheCoolHut/Linux_kernel_exploitation/blob/master/src/kernel-overflow.c). You can [build the kernel yourself ](https://github.com/pwncollege/pwnkernel)or use my prebuilt one [here](https://github.com/ChrisTheCoolHut/Linux_kernel_exploitation).

You will need `qemu`,`gcc`, and `gdb` to follow along with these problems.

The `launch.sh` script will rebuild the file system and launch qemu

```bash
#!/bin/bash

# build root fs
pushd fs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
popd

# launch
/usr/bin/qemu-system-x86_64 \
	-m 128M \
	-cpu kvm64,+smep,+smap \
	-no-reboot \
	-kernel linux-5.4/arch/x86/boot/bzImage \
	-initrd $PWD/initramfs.cpio.gz \
	-fsdev local,security_model=passthrough,id=fsdev0,path=$HOME \
	-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
	-nographic \
	-monitor none \
	-s \
	-append "console=ttyS0 nokaslr nopti nosmep nosmap panic=1"
```

The `-s` flag will start qemu with gdb debugging enabled on localhost port `1234` . Most gdb extensions like `gef` and `pwndbg` have trouble debugging kernels and you can disable them with the command: `gdb -nx ./bzImage`&#x20;

## Kernel-Overflow module

The module we will be exploiting for most of this series is named `kernel-overflow` and is located here \[TODO github link]. The module creates a character device named `kernel-overflow` which is accessible at `/dev/kernel-overflow` . It supports read and write operations, which ultimately lead to a leak and overflow.

## Leak

The leak happens when `read` is called on the character device with a length greater than `256` bytes. Our stack buffer `tmp` is only `256` bytes long and the length check below it is not sufficient to prevent an overread from happening. As long as our read is less than `0x1000` bytes, we can read past `tmp` and leak out the `stack cookie` and `stack saved registers`

```c
static ssize_t device_read(struct file *filp, char *buf, size_t len, loff_t *offset)
{
    int tmp[32] = {0};
    tmp[0] = 0xDEADBEEF;
    tmp[31] = 0xCAFEBABE;

    memcpy(hackme_buf, tmp, len);

    if ( len > 0x1000 )
    {
        printk("Buffer overflow detected (%d < %lu)!\n", 4096LL, len);
        BUG();
    }

    if ( copy_to_user(buf, hackme_buf, len) ) return -14LL;

    return len;
}
```

## Overflow

The overflow happens when `write` is called on the character device with a length greater than `256` bytes. Our stack buffer `tmp` is only `256` bytes long and just like the leak, the length check is not sufficient to prevent a stack overflow.

```c
static ssize_t device_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
    int tmp[32] = {0};
    tmp[0] = 0xDEADBEEF;
    tmp[31] = 0xCAFEBABE;

    if ( len > 0x1000 )
    {
        printk("Buffer overflow detected (%d < %lu)!\n", 4096LL, len);
        BUG();
    }
    check_object_size(hackme_buf, len, 0LL);

    if ( copy_from_user(hackme_buf, buf, len) ) return -14LL;

    memcpy(tmp, hackme_buf, len);

    // my gcc is optimizing out the memcpy
    // having tmp used after the copy ensures
    // that it stays in
    printk(KERN_ALERT "After %s",tmp);

    return len;
}
```
