MAD Bugs: Claude Wrote a Full FreeBSD Remote Kernel RCE with Root Shell (CVE-2026-4747)

3 min read Original article ↗

Timeline:

Total time: ~8 hours wall clock. The human was AFK for much of it; Claude’s actual working time was ~4 hours.

Claude actually wrote two exploits using two different strategies. Both worked on the first try. Here’s what it looks like:

Check out the full exploit and the write-up. Claude wrote everything itself. Here are the prompts we used (excuse the typos):

Going from a vulnerability advisory to a working remote root shell required Claude to solve six distinct problems. It’s worth noting that FreeBSD made this easier than it would be on a modern Linux kernel: FreeBSD 14.x has no KASLR (kernel addresses are fixed and predictable) and no stack canaries for integer arrays (the overflowed buffer is int32_t[]).

  1. Lab setup: Stand up a FreeBSD VM with NFS, Kerberos, and the vulnerable kernel module, all configured so the overflow is reachable over the network. Claude knew the VM needed 2+ CPUs because FreeBSD spawns 8 NFS threads per CPU, and the exploit kills one thread per round. This included setting up remote debugging so Claude could read kernel crash dumps.

  2. Multi-packet delivery: The shellcode doesn’t fit in one packet. Claude devised a 15-round strategy: make kernel memory executable, then write shellcode 32 bytes at a time across 14 packets. In another exploit privately shared with us, Claude used a different strategy: writing a public key to .ssh/authorized_keys instead of a reverse shell, which shortened the exploit to 6 rounds.

  3. Clean thread exit: Each overflow hijacks an NFS kernel thread. Claude used kthread_exit() to terminate each thread cleanly, keeping the server alive for the next round.

  4. Offset debugging: The initial stack offsets from disassembly were wrong. Claude sent De Bruijn patterns (a common technique, but a term we hadn't heard of before reading the writeup), read the crash dumps, and corrected the offsets.

  5. Kernel-to-userland transition: NFS threads can’t run userland programs. Claude created a new process via kproc_create(), used kern_execve() to replace it with /bin/sh, and cleared the P_KPROC flag so the process could transition to user mode.

  6. Hardware breakpoint bug: The child process kept crashing with a debug exception. Claude traced this to stale debug registers inherited from DDB and fixed it by clearing DR7 before forking.

Computers have always been able to find bugs in software. Fuzzers like AFL and syzkaller have been discovering kernel vulnerabilities for over a decade. But finding a bug and exploiting it are very different things. Exploit development requires understanding OS internals, crafting ROP chains, managing memory layouts, debugging crashes, and adapting when things go wrong. This has long been considered the frontier that only humans can cross.

Each new AI capability is usually met with “AI can do Y, but only humans can do X.” Well, for X = exploit development, that line just moved.

Discussion about this post

Ready for more?