skip to content
Posts · April 2025

Linux Kernel Exploitation - Setup


In this post, I will explain how to build and debug the Linux kernel.

How to Build the Linux Kernel with Buildroot

  • Install Buildroot.

  • Run the following commands to configure Buildroot:

    Terminal window
    make list-defconfigs # List available configurations
    make qemu_x86_64_defconfig # Select default configurations for QEMU x86_64
    make menuconfig # Modify configurations if needed
    • Select Filesystem images -> ext2/3/4 root file system and select ext2/3/4 variant -> ext3.

    If you want to change the kernel version, follow these steps:

    • Select Kernel -> Kernel version -> Custom Version.
    • Select Kernel version and set the version as you want.
    • Select Toolchain -> Custom Kernel Header Series and choose the appropriate version.
  • Run make linux-menuconfig and configure the kernel:

    • Select Kernel hacking -> Kernel debugging.
    • Select Compile-time checks and compiler options -> Debug information -> Rely on the toolchain's implicit default DWARF version.
    • Optionally, enable any other configurations you want.
  • Run make busybox-menuconfig and configure BusyBox:

    • Select Shells -> cttyhack.
    • Select Runtime utilities -> setuidgid.
  • Run make -j$(nproc) to build.

You can find bzImage and rootfs.ext3 in <PATH_TO_BUILDROOT>/output/images and vmlinux with debug symbols at <PATH_TO_BUILDROOT>/output/linux-<VERSION>/vmlinux.

How to Build the Linux Kernel without Buildroot

  • Download and extract the kernel source code (for example, from here).

    • Run make menuconfig and configure as you want.
    • Run make build -j$(nproc) to build.

    If you want to build the kernel with Clang/LLVM, follow the instructions here.

    If you want to enable CONFIG_CFI_CLANG, you may need to compile Clang/LLVM with compiler-rt enabled. follow the instructions here.

  • Download and extract the Busybox source code(for example, from here).

    • Run make menuconfig and configure as you want. Make sure to select Settings -> Build static binary file (no shared lib).
    • Run make install to build. Make sure not to use sudo. You can find the compiled binaries in <PATH_TO_BUSYBOX>/_install.
  • Create the ext3 root file system image:

    Terminal window
    dd if=/dev/zero of=rootfs.ext3 bs=1M count=16
    mkfs.ext3 -F rootfs.ext3
    mkdir -p mnt
    sudo mount -o loop rootfs.ext3 ./mnt
    sudo chown -R 1000:1000 ./mnt
    cp -a <PATH_TO_BUSYBOX>/_install/* ./mnt
    mkdir -p ./mnt/{dev,etc,proc,root,run,sys}

How to Run the Linux Kernel with QEMU

  • Install QEMU.
  • Run mkdir -p mnt and sudo mount -o loop <PATH_TO_ROOTFS> ./mnt.
  • Run sudo chown -R 1000:1000 ./mnt.
  • Create /init:
    #!/bin/sh
    if (exec 0</dev/console) 2>/dev/null; then
    exec 0</dev/console
    exec 1>/dev/console
    exec 2>/dev/console
    fi
    mkdir /home
    echo 'root:x:0:0:root:/root:/bin/sh' > /etc/passwd
    echo 'root:x:0:' > /etc/group
    chmod 644 /etc/passwd
    chmod 644 /etc/group
    adduser ctf --disabled-password 2>/dev/null
    chown -R root:root /
    chmod 700 -R /root
    chown ctf:root /home/ctf
    chmod 777 /home/ctf
    chmod 755 /dev
    chmod u+s /bin/su
    mount -t proc -o nodev,noexec,nosuid proc /proc
    mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
    mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
    ln -sf /proc/mounts /etc/mtab
    echo 1 > /proc/sys/kernel/kptr_restrict
    echo 1 > /proc/sys/kernel/dmesg_restrict
    echo 1 > /proc/sys/kernel/perf_event_paranoid
    setsid cttyhack setuidgid 1000 sh
  • Create run.sh:
    #!/bin/sh
    qemu-system-x86_64 \
    -m 64M \
    -cpu qemu64 \
    -kernel bzImage \
    -drive file=rootfs.ext3,format=raw \
    -snapshot \
    -nographic \
    -monitor /dev/null \
    -no-reboot \
    -smp 1 \
    -append "root=/dev/sda rw init=/init console=ttyS0 nokaslr nopti loglevel=3 oops=panic panic=-1"
  • Run sudo umount ./mnt.
  • Run ./run.sh.

How to Debug the Linux Kernel with QEMU and GDB

  • Run QEMU with the -gdb tcp::1234 option.
  • Run GDB and execute target remote localhost:1234.