Breaking Bits
  • What this gitbook is
  • Vulnerability Discovery
    • Reverse Engineering
      • Modern Vulnerability Research Techniques on Embedded Systems
      • Remote Dynamic Blackbox Java App Analysis
    • Emulation
      • QEMU Usermode Tracing
      • Building QEMU on Ubuntu
    • Fuzzing with AFL
    • Automated Vulnerability Discovery
      • Buffer Overflows
      • Analyzing Functions
    • Automatic Exploit Generation
      • Automatic Rop Chain Generation
  • CTF
  • Battelle Shmoocon 2024
    • Time Jump Planner
  • Spaceheros CTF 2022
    • RE: Shai-Hulud
  • UMDCTF 2020
    • UMDCTF 2020: Evil Santa's Mysterious Box of Treats
  • UMDCTF 2022
    • Tracestory
  • Spaceheroes CTF 2023
    • Everything-is-wrong
  • US CyberGames RE-Cruise 4
  • Firmware Emulator
  • Interactive Firmware Emulator Usage
  • Recreating CVE-2015-1187 in the DIR-820L
  • Exploit Development
    • Linux kernel exploit development
      • Setup
      • Interacting with Kernel Modules
      • Kernel stack cookies
      • Kernel Address Space Layout Randomization (KALSR)
      • Supervisor mode execution protection (SMEP)
      • Kernel page table isolation (KPTI)
      • Supervisor Mode Access Prevention (SMAP)
Powered by GitBook
On this page
  • Overview
  • Kernel-Overflow module
  • Leak
  • Overflow

Was this helpful?

  1. Exploit Development
  2. Linux kernel exploit development

Setup

PreviousLinux kernel exploit developmentNextInteracting with Kernel Modules

Last updated 3 years ago

Was this helpful?

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 . You can or use my prebuilt one .

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

#!/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

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

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.

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;
}
here
build the kernel yourself
here