The modprobe_path overwrite is the clean, data-only way to escalate. But sometimes you have control flow, not a write-what-where, and the canonical kernel payload is two calls: make a fresh root credential, install it on the current task.
|
prepare_kernel_cred(0) allocates a cred with root ids; commit_creds swaps it
onto the running task. After it returns you're root — you just have to get back to
userland in one piece and execve("/bin/sh").
- arch
- amd64-64-little
- control
- a kernel stack overflow -> kernel ROP
- SMEPon
- SMAPon
- KPTIon
- KASLRon
the four walls, and the door in each#
Every kernel mitigation here removes one easy version of the attack and leaves a narrower one:
- SMEPon
- SMAPon
- KPTIon
- KASLRon
- SMEP — the kernel can't execute userland pages. So you can't point kernel
ripat a userland function (ret2usris dead); you ROP inside the kernel instead, with gadgets from the kernel image. - SMAP — the kernel can't casually read userland either, so stage your data in kernel memory or registers, not a userland buffer it'll dereference.
- KASLR — the kernel base is randomized; you need a leak (an
%pK/dmesg/info-leak bug) to rebase every gadget and symbol. - KPTI — userland and kernel run on separate page tables, so you can't just
iretqback; you return through the kernel's own trampoline,swapgs_restore_regs_and_return_to_usermode, which switchesCR3for you.
the chain#
Save the userland state first (CPU cs/ss/rflags/rsp and a target rip), because
the trampoline's iretq will restore exactly that and drop you back into your own
process — now privileged:
|
uid=0
commit_creds returns, the trampoline iretqs back into win(), and the
saved userland context is intact — except for the one thing that changed:
notes from the trenches#
prepare_kernel_cred(0)is version-sensitive. On kernels ≥ 6.2 passing a task pointer changed semantics; the0/NULLform still yields root creds in the versions most CTF modules ship, but check your target's source — some pwns switch to&init_creddirectly.- The trampoline offset matters. Enter
swapgs_restore_regs_and_return_to_usermodepast itsmov rdi, rsp/ register-pop preamble, at theswapgs; iretqtail, with the stack laid out exactly howiretqwants it (rip cs rflags rsp ss). - Leak before you leap. With KASLR on, every address above is
base + offset; without a leak you have nothing. The info-leak bug is usually the hard 80% of the exploit, the cred swap the easy 20%.
Two function calls separate an unprivileged task from root. The mitigations don't forbid those calls — they just make you assemble them from kernel gadgets, rebase everything off a leak, and tiptoe back across the KPTI boundary to enjoy the result.