Skip to content
Agentmart
Submit a tool

ctf-kernel-exploitation

Solve CTF kernel exploitation challenges — Linux kernel pwn, QEMU TCG bugs, modprobe_path overwrite, remote kernel CTFs with PoW/WebSocket terminal.

Skill by Wang200935

IndexedMIT★ 4
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/wang200935-ctf-kernel-exploitation

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Solve CTF kernel exploitation challenges — Linux kernel pwn, QEMU TCG bugs, modprobe_path overwrite, remote kernel CTFs with PoW/WebSocket terminal.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/ctf-kernel-exploitation

What's inside

Skill name
ctf-kernel-exploitation
Description
Solve CTF kernel exploitation challenges — Linux kernel pwn, QEMU TCG bugs, modprobe_path overwrite, remote kernel CTFs with PoW/WebSocket terminal.
License
MIT
Metadata
hermes_origin: import
Instructions
332 lines in SKILL.md · view on GitHub

Files (9)

  • SKILL.md
  • kernel-offset-extraction.md · references/
  • linux-6.12.85-verified-addresses.md · references/
  • netcat-raw-binary-upload-pitfall.md · references/
  • qemu-backported-iret-fix.md · references/
  • qemu-tcg-technique.md · references/
  • remote-ctf-solver-pattern.md · references/
  • symbol-extraction-stripped-vmlinux.md · references/
  • wand-stack-pivot-technique.md · references/

SKILL.md (first lines)

# CTF Kernel Exploitation

Kernel exploitation CTF challenges: privilege escalation from unprivileged user to root inside a QEMU VM. Two major families: (A) actual kernel vulnerabilities (UAF, heap overflow in kernel modules), and (B) QEMU emulator bugs that let userspace bypass kernel protections.

## When to Load
- Any CTF challenge tagged "kernel", "pwn", "misc 0day", or involving a bzImage + rootfs.cpio
- The user asks about exploiting a Linux kernel, QEMU escape, or kernel privilege escalation
- The challenge provides a QEMU run script and kernel/rootfs files

## Core Approach

### Step 1: Analyze the challenge files
```
unzip dist.zip
cat run.sh          # QEMU flags: KVM vs TCG, protections
cat rootfs/init     # System config, kptr_restrict, setuid binaries
file vmlinux        # ELF or compressed?
```

### Step 2: Extract kernel offsets
For modprobe_path technique, find the virtual address:
```python
# Parse vmlinux ELF, find "/sbin/modprobe" string, compute virt addr
# modprobe_path is in .data section
# offset from kernel text base (0xffffffff81000000) is the key value
```

### Step 3: Choose exploit strategy

**Strategy A: QEMU TCG iret/far-call** (most common for misc/kernel CTFs)
- Works on QEMU < 9.1 in TCG mode (not KVM)
- `sgdt` → GDT address → TSS → IST shared stack
- `iretq` with RSP=physical_addr → reads physical memory (page fault trick)
- `call far` shellcode → writes byte to physical memory
- Overwrite `modprobe_path` → trigger unknown binary → script reads /flag

**Strategy B: Kernel module vulnerability** (custom .ko provided)
- Reverse engineer the module
- Exploit the specific bug (UAF, overflow, race condition)
- Standard kernel exploitation: heap spray, overwrite cred structure, etc.

**Strategy C: Kernel ROP via custom module stack-pivot (wand.ko pattern)**
A clean pattern seen in AIS3 CTFs: a custom miscdevice module provides `ioctl` that:
1. Copies user-controlled data into a kernel stack buffer (e.g., `magic_core[168]`)
2. Pivots RSP to that buffer: `mov %0, %%rsp`
3. Jumps to a hardcoded `swapgs_restore_addr` (e.g., KPTI trampoline): `jmp *%1`
4. The trampoline does `swapgs; iretq` — the iretq frame is user-controlled from the buffer

**Key constraint**: limited ROP space (e.g., 168 bytes total, minus 40-byte iretq frame = 128 bytes for ROP chain = 16 qwords).

**Exploit ROP chain layout** (ring0 → root → ring3):
```
buffer[0]:   pop rdi; ret           # first gadget (RIP in iretq frame, CS=0x10)
buffer[1]:   0                      # rdi = 0 for prepare_kernel_cred(NULL)
buffer[2]:   prepare_kernel_cred     # returns new root cred in rax
buffer[3]:   <rax->rdi gadget>      # MOV RDI, RAX essential — see Pitfalls
buffer[4]:   commit_creds            # elevate to root
buffer[5]:   swapgs_restore_addr     # swapgs; iretq back to ring3
buffer[6]:   user_rip                # shellcode
buffer[7]:   0x33                    # user CS
buffer[8]:   user_rflags (0x202)     # interrupt flag set
buffer[9]:   user_rsp
buffer[10]:  0x2b                    # user SS
...
buffer[16]:  iretq frame: RIP=pop_rdi_ret, CS=0x10, RFLAGS, RSP=&buffer[1], SS=0x18
```

**init_cred bypass**: If no rax→rdi gadget exists, commit `init_cred` directly:
```
pop rdi; ret → &init_cred → commit_creds → swapgs_restore → user shellcode
```
Skips `prepare_kernel_cred` entirely. Needs `init_cred` address (a global `struct cred` in .data with full capabilities, uid=0).

### Step 4: Remote connection (if applicable)
Most kernel CTFs use: HTTP PoW → WebSocket → terminal inside VM
- Solve PoW (SHA-256, typically 20-bit difficulty)
- Connect WebSocket with token + pow_token
- Handle queue/status/ready/error messages
- Interact with terminal (busybox shell)

### Step 5: Upload and run exploit
- Binary must be **statically linked** (VM has only busybox)
- Compress with gzip, encode as base64
- Upload in chunks via `printf` or `echo -n`
- Decode: `base64 -d /tmp/e.b64 | gzip -d > /tmp/e`
- VM session timeout is typically 300s — keep total operation under this

## Key Pitfalls

### `xchg eax, edi` / 32-bit swap is USELESS for kernel addresses
`xchg eax, edi; ret` (bytes `97 c3`) is common but only swaps **lower 32 bits** and **zero-extends to 64 bits**. If RAX holds `0xffff88800a1b2c00` (kernel heap cred pointer), after `xchg eax, edi`, RDI becomes `0x000000000a1b2c00` — a **userspace address**, not a valid kernel pointer. Always search for a **64-bit** rax→rdi gadget:
- `48 89 c7 c3` = `mov rdi, rax; ret` (rare in kernel .text)
- `48 97 c3` = `xchg rax, rdi; ret` (extremely rare)
- `50 5f c3` = `push rax; pop rdi; ret` (occasionally found)
- Fallback: use `init_cred` bypass (see Strategy C)

### KPTI trampoline address verification
The `swapgs_restore_addr` hardcoded in the module (e.g., `0xffffffff820015d0`) may NOT point to `swapgs; iretq`. Always **disassemble** around that address with `objdump -d` to verify. In Linux 6.12 with KPTI, the code at that offset may be MSR writes (`wrmsr`) for page-table switching, not the expected `swapgs` instruction. The actual `swapgs; iretq` sequence may be elsewhere in the trampoline.

### commit_creds and prepare_kernel_cred are NOT exported
Since kernel ~5.x, these functions have no `EXPORT_SYMBOL`. They are **absent from `__ksymtab`**. Do not waste time searching __ksymtab — use:
- **Symbol extraction from stripped vmlinux** (see `references/symbol-extraction-stripped-vmlinux.md`)
- **QEMU boot with modified initramfs** (dump `/proc/kallsyms` before `kptr_restrict=1` is set)
- **ENDBR64 function boundary scan** (modern IBT kernels start every function with `f3 0f 1e fa`)

### EFI-stub bzImage extraction
Modern kernels with `CONFIG_EFI_STUB=y` produce bzImages that are valid PE executables (start with `MZ`). The compressed kernel is inside the `.text` PE section, **not** at the traditional `(setup_sects+1)*512` offset. Use:
```python
# Parse PE header to find .text section, then gzip offset within it
# Verified for Linux 6.12.85: gzip at bzImage offset 21188 (0x52C4)
# Decompresses to 43,911,280 byte ELF
```
The `extract-vmlinux` script from kernel source may fail on EFI-stub images — parse PE sections manually.

### Docker QEMU TCG mode is IMPRACTICALLY slow
Booting a full Linux kernel in Docker with QEMU TCG (no KVM inside containers on macOS) can take 10-30+ minutes. **Key tactic**: the slow part is `apt-get install qemu-system-x86` (pulls in graphical dependencies). Pre-build a Docker image with QEMU or reuse the same container for multiple boots. For symbol extraction, prefer:
- Static binary analysis (ENDBR64 scan, byte-pattern gadget search)
- **Modify initramfs to dump kallsyms before kptr_restrict** — most reliable method; trivial init script change repack with cpio+gzip
- Building kernel from source to get System.map (~20 min but guaranteed correct)

From Wang200935/security-agent-skills, MIT.

More from Wang200935/security-agent-skills

Signals

Stars
4
Forks
1
Open issues
0
Last commit (this folder)
Aug 12, 2026 (2 months ago)
Last release
Aug 13, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from Wang200935

Cite this page

ctf-kernel-exploitation skill. Agent Mart. https://agentmart.dev/skills/wang200935-ctf-kernel-exploitation (last updated 2026-10-24)