AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Ctf Kernel Exploitation

skill-wang200935-security-agent-skills-ctf-kernel-exploitation · by Wang200935

Solve CTF kernel exploitation challenges — Linux kernel pwn, QEMU TCG

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-wang200935-security-agent-skills-ctf-kernel-exploitation

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-wang200935-security-agent-skills-ctf-kernel-exploitation)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
20d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Ctf Kernel Exploitation? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

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:

# 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 rdi gadget> # MOV RDI, RAX essential — see Pitfalls

buffer[4]: commitcreds # elevate to root buffer[5]: swapgsrestoreaddr # swapgs; iretq back to ring3 buffer[6]: userrip # shellcode buffer[7]: 0x33 # user CS buffer[8]: userrflags (0x202) # interrupt flag set buffer[9]: userrsp buffer[10]: 0x2b # user SS ... buffer[16]: iretq frame: RIP=poprdiret, CS=0x10, RFLAGS, RSP=&buffer[1], SS=0x18


**init_cred bypass**: If no rax→rdi gadget exists, commit `init_cred` directly:

pop rdi; ret → &initcred → commitcreds → 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)
  • Using pre-built Ubuntu kernel debug packages for the same version

Ubuntu QEMU 6.2.0 has BACKPORTED iret/far-call fix

CRITICAL: Ubuntu 22.04 ships QEMU 6.2.0 (qemu-system-x86 from apt) with a backported security patch that fixes the ring3→ring0 iretq privilege-escalation bug. The upstream fix landed in QEMU 9.1, but Ubuntu backported it. The ring3→ring0 iretq exploit will SIGSEGV immediately on Ubuntu-packaged QEMU. This means local testing in Docker with ubuntu:22.04 gives false negatives.

Verification: A minimal iretq test (RSP=userspace, CS=0x10) gets SIGSEGV (exit 139) on Ubuntu's QEMU 6.2.0. On unpatched QEMU (e.g., compiled from source before 9.1, or older distro packages), the same test succeeds.

Workaround for local testing: The remote CTF server may use a DIFFERENT QEMU version. For local testing, either:

  • Use a Docker image with unpatched QEMU (Alpine, Debian, or compile from source)
  • Test on the remote directly (mind the 1-hour cooldown)
  • Use a non-Ubuntu QEMU package

Physical address calculation

The CORRECT formula:

uint64_t modprobe_phys = (kbase + MODPROBE_PATH_OFF) - 0xffffffff80000000ULL;

DO NOT add an extra PHYSICALSTART (0x1000000) — PAGEOFFSET already accounts for the mapping.

Binary upload timing

  • Send all upload chunks without intermediate reads (shell echo interferes)
  • After READY, wait 10-15s for VM to finish booting
  • Use gzip -d not gunzip (busybox compatibility)
  • Don't use 2>/dev/null during decode — errors must be visible
  • Terminal prompt detection is unreliable; use fixed waits instead

Static compilation for Linux target

On macOS, use Docker:

# Alpine (musl): gcc -static -Os -s -o exp exp.c
# Alpine musl lacks REG_ERR/REG_RSP in ucontext — use raw gregs index 19 for REG_ERR on x86_64
docker run --rm -v $PWD:/work -w /work alpine sh -c '
  apk add --no-cache gcc musl-dev && gcc -static -Os -s -o exp exp.c'

Alpine musl may lack REG_ERR/REG_RSP defines, and `` is absent. Workarounds:

  • ferr = ((ucontext_t*)ctx)->uc_mcontext.gregs[19]; — raw index 19 for REGERR on x8664
  • Remove `` include; the phys_read/iretq exploit doesn't need LDT

WebSocket lifecycle

  • The VM session timeout starts from VM boot, not from READY
  • Don't read terminal output during upload — it captures stale echoes
  • Send all commands (upload, decode, run, flag) in one burst, then read
  • Total operation MUST fit in ~300s window

Verified Offsets Reference

For common kernel builds, modprobe_path offset from kbase:

  • Linux 6.1.81 (AIS3 build): 0x2877760
  • Linux 6.12.85 (AIS3 2026): full verified address table in references/linux-6.12.85-verified-addresses.md. Key addresses: modprobe_path@0xffffffff82b44f60, commit_creds@0xffffffff810c1dd0, prepare_kernel_cred@0xffffffff810c2060, init_cred@0xffffffff82a52ba0

Physical addresses from kallsyms 'A' symbols

Kallsyms entries with type A (Absolute) are physical addresses, not virtual! Critical for QEMU TCG phys_read exploits:

000000000000b000 A gdt_page          ← GDT at physical 0xb000
0000000000006000 A cpu_tss_rw        ← TSS at physical 0x6000

Use these directly as physical addresses for iretq RSP targets. Do NOT subtract PAGE_OFFSET from 'A' symbols — they are already physical.

Netcat-based CTFd remote protocol (non-WebSocket)

Some CTFd instancers use a raw netcat protocol instead of WebSocket:

→ Server: PoW prompt ("Prefix: ")
→ Client: PoW answer
→ Server: "CTFd token:" prompt  
→ Client: ctfd_
→ Server: "NEED_UPLOAD_EXPLOIT (y/n)"
→ Client: y
→ Server: (accepts exploit as RAW BINARY, boots VM)

Token is rate-limited: "This account can verify only once every 1 hour." Plan attempts carefully. The exploit binary is provided as a raw disk image (becomes /dev/sda in VM, copied to /tmp/e by init script).

PITFALL — raw binary, NOT base64: Sending base64-encoded data after 'y' causes "[X] Invalid URL." The server expects the raw binary (ELF file bytes) directly on the socket. It shows a progress bar (backspace characters) while receiving. After upload, the VM boots — set socket timeout to 300+ seconds (not 60) to capture the full VM boot + exploit output. The 60s default is too short; the exploit runs but you miss the flag. See references/netcat-raw-binary-upload-pitfall.md.

PITFALL — base64 echo confusion: If you send base64 INSTEAD of first answering 'y', the server reads 'f' (first char of base64) as the answer, defaults to 'n', echos the base64, and boots WITHOUT your exploit ("No exploit supplied"). Always send 'y\\n' BEFORE the binary data.

Apple Silicon + Docker QEMU = broken (Rosetta)

On Apple Silicon Macs, docker run --platform linux/amd64 with QEMU inside the container fails with rosetta error: Unimplemented syscall number 282. Rosetta 2 does not support the full x86_64 syscall table needed by QEMU's system emulation. For local kernel exploitation testing on Apple Silicon:

  • Native macOS QEMU via Homebrew (may fail to build for x86_64 target)
  • UTM.app or similar virtualization
  • Test on the remote CTF server directly (mind the cooldown)
  • Use a remote x86_64 cloud VM

Key gadget byte patterns (search .text section after objcopy -O binary -j .text)

| Gadget | Bytes | Notes | |--------|-------|-------| | pop rdi; ret | 5f c3 | Common, many instances | | xchg eax, edi; ret | 97 c3 | 32-bit only — zero-extends, useless for kernel addrs | | mov rdi, rax; ret | 48 89 c7 c3 | Rare in kernel .text | | push rax; pop rdi; ret | 50 5f c3 | Best rax→rdi gadget | | xchg rax, rdi; ret | 48 97 c3 | Extremely rare | | swapgs; iretq | 0f 01 f8 48 cf | May be split in KPTI trampoline | | ENDBR64 (function start) | f3 0f 1e fa | IBT-enabled kernels (CONFIGX86KERNEL_IBT=y) |

2025-2026 Kernel Exploitation Update: New CVEs & Techniques

Critical Kernel CVEs for CTF (2025-2026)

| CVE | Component | CVSS | Description | CTF Relevance | |---|---|---|---|---| | CVE-2024-1086 (Flipping Pages) | nftables | 7.8 | UAF in netfilter, decade-old bug, actively exploited by ransomware groups | Heap exploitation in kernel, msg_msg spray, cred overwrite | | CVE-2025-21756 (Attack of the Vsock) | vsock subsystem | 8.8 | VM escape via vsock transport reassignment, refcount UAF | VM escape challenges, container breakout | | CVE-2021-22555 | netfilter | 7.8 | Privilege escalation, added to CISA KEV Oct 2025 (4 years post-disclosure) | Classic kernel pwn, still used in CTF | | OverlayFS bugs | OverlayFS | varies | Container escape via OverlayFS | Container escape CTF category | | pipebuffer UAF | pipe subsystem | varies | UAF in pipe_buffer structure | Modern kernel heap exploitation |

nf_tables UAF Exploitation (CVE-2024-1086 "Flipping Pages")

The most significant kernel exploit of 2025 — a decade-old UAF in nf_tables:

  1. Trigger: Double-free via NFT_MSG_NEWRULE + NFT_MSG_DELRULE race
  2. Heap spray: Use msg_msg structure for controlled heap allocation at freed object's slab
  3. Arbitrary read/write: Overwrite msg_msg.m_ts for OOB read, msg_msg.next for arbitrary read
  4. Privilege escalation: Overwrite task_struct.cred or use setresuid ROP
  5. KASLR bypass: single_start leak via /proc/self/stat or msg_msg partial overwrite

vsock VM Escape (CVE-2025-21756)

For CTF challenges involving VM escape:

  1. vsock transport reassignment causes refcount corruption
  2. UAF on vsock_sock structure after transport module unload
  3. Kernel memory corruption → arbitrary code execution with root privileges
  4. PoC published alongside disclosure

QEMU Updates (2025-2026)

  • QEMU 9.1+ fixed the ring3→ring0 iretq privilege escalation bug (Ubuntu backported fix to 6.2.0)
  • QEMU TCG mode still used in CTFs without KVM — check version before attempting iretq exploits
  • Apple Silicon + Docker + QEMU: Still broken (Rosetta doesn't support full x8664 syscall table). Use remote testing or cloud x8664 VM.
  • New: --cpu kvm64 includes PCID → KPTI is ON by default. Only pti=off/nopti cmdline disables it.

Modern Kernel Hardening (2025-2026)

| Mitigation | Status | Bypass | |---|---|---| | KPTI | Default on (x8664, QEMU kvm64) | Page table switch during syscall; use entry Sears trampoline or fw_cfg DMA | | KASLR | Default on | EntryBleed leak (CVE-2022-4543), /proc/kallsyms before kptr_restrict | | IBT (Indirect Branch Tracking) | CONFIGX86KERNELIBT=y | ENDBR64 function boundary scan; only bti c/endbr64 are valid indirect branch targets | | CFI (Control Flow Integrity) | Growing adoption | COOP (Counterfeit Object-Oriented Programming) — use existing virtual function chains | | MTE (Memory Tagging) | AArch64 only | Tag mismatch detection; spray matching tags or find tag corruption primitive | | Sealed libc | glibc 2.38+ | mprotect all libc pages RO after init — probe writability first | | LKRG (Runtime Guard) | RLC-Hardened only | Behavior-based detection; detect cred modification or privilege escalation |

Practical Kernel CTF Resources (2025-2026)

  • linux-kernel-exploitation GitHub: github.com/xairy/linux-kernel-exploitation — comprehensive link collection (6.5k stars)
  • kernelCTF VRP (Google): Continuous kernel exploitation challenge with experimental mitigations
  • RVAsec 2025: "Linux Kernel Exploitation for Beginners" — training using kernel CTFs as entry point
  • Reddit r/ExploitDev: Community kernel exploitation CTF labs
  • Google kernelCTF: First blood on experimental mitigation instance — single byte OOB → privilege escalation

modprobepath AFALG Bypass (2025 — searchbinaryhandler Patch)

As of Linux v6.14-rc1 (patch fa1bdca98d74), the search_binary_handler() flow that called request_module() has been completely removed. Executing a dummy file with unknown magic bytes (e.g., \xff\xff\xff\xff) no longer triggers modprobe_path on upstream kernels. The old technique is dead on mainline.

New trigger: AF_ALG socket bind()

The AF_ALG socket subsystem calls request_module("algif-%s", type) in alg_bind() when sa->salg_type doesn't match any known crypto type. This reaches call_modprobe() without needing a dummy file.

// Trigger — no capabilities required, no file needed
int sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
struct sockaddr_alg sa = {0};
strcpy((char*)sa.salg_type, "V4bel"); // dummy string
bind(sock, (struct sockaddr*)&sa, sizeof(sa));

Fileless

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.