pwnfreehard

throughthewall

b01lersc

Task: exploit a Linux kernel firewall module in a QEMU guest with PTI, KASLR, SMEP, and SMAP enabled. Solution: turn a stale kmalloc-1024 rule object into a pipe_buffer KASLR leak, then use msg_msg corruption for arbitrary read and unlink-based writes to swap current->cred pointers to init_cred.

$ ls tags/ techniques/
uaf_reusepipe_buffer_ops_leakmsg_msg_arbitrary_readlist_del_unlink_writecred_pointer_swap

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

throughthewall — b01lersc (BCTF 2026)

Description

Goal: Exploit the firewall module!

We are given a kernel-pwn challenge with three files: bzImage, initramfs.cpio.gz, and start.sh. The guest boots with pti=on, kaslr, SMEP, SMAP, and -smp 2, and the goal is to gain root inside the VM and read /flag.txt.

Files and environment

The provided launcher is:

qemu-system-x86_64 \ -m 256M \ -nographic \ -kernel ./bzImage \ -append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti=on kaslr" \ -no-reboot \ -cpu qemu64,+smep,+smap \ -smp 2 \ -initrd ./initramfs.cpio.gz \ -monitor /dev/null \ -s

Important initramfs observations:

  • /dev/firewall is world-writable.
  • /dev/ptmx exists, but devpts is not mounted, so the usual tty_struct ptmx spray path is not practical.
  • SysV message queues are available.
  • Pipes are available.
  • dmesg is readable via klogctl, which turns kernel log output into a very strong infoleak source.

Vulnerable interface

The challenge module is firewall.ko, exposing four ioctls:

#define FW_ADD_RULE 0x41004601 #define FW_DEL_RULE 0x40044602 #define FW_EDIT_RULE 0x44184603 #define FW_SHOW_RULE 0x84184604

Each firewall rule is a 0x400-byte object, so the interesting allocations live in kmalloc-1024.

The core bug is in delete: the module does kfree(rules[idx]) but does not clear rules[idx]. After that, both edit and show still operate on the stale pointer. That gives a stable use-after-free on a very sprayable cache size.

Analysis

1. Strong heap pointer leak from kernel logs

The module logs raw heap pointers with %px in fw_del_rule and fw_show_rule. Because dmesg is readable, every delete gives us the exact address of the freed firewall object.

That matters a lot: instead of guessing which allocation reclaimed the freed slot, we can free a rule, read the log, and then inspect the stale object with FW_SHOW_RULE until we recognize the replacement structure.

...

$ grep --similar

Similar writeups