利用pwntools脚本联动内置gdb函数优雅的调试docker中的pwn程序
字数 1074 2025-08-29 22:41:10
利用pwntools脚本联动内置gdb函数优雅调试docker中的pwn程序
背景与问题描述
在CTF的PWN模块中,我们经常需要使用gdb来联动exp脚本调试pwn程序。pwntools的内置函数gdb.attach()在本地调试时非常方便,但存在以下问题:
- 本地环境与pwn程序编译时的原生环境存在差异
- 特殊架构(如mips)或使用C++库的程序,使用patchelf替换libc库效果不佳
- 之前尝试的pipe+tmux组合方案存在输入阻塞问题
- 在docker内重新安装pwn环境+pwngdb插件较为麻烦
解决方案概述
本方案提供了一种对任意docker能运行的镜像系统都能无缝调试pwn程序的方法,特别适合在解题时建立临时docker环境调试pwn程序。
环境准备
- 操作系统: Ubuntu 24.04
- 虚拟机: VirtualBox 7.1.6
- 已安装基础pwn环境和docker环境
- 当前用户已加入docker用户组
详细步骤
1. 创建Dockerfile
在当前目录下创建Dockerfile文件,内容如下:
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y gdb gdbserver python3 python3-pip git make gcc net-tools vim && \
pip3 install pwntools
WORKDIR /tmp
2. 构建Docker镜像
docker build -t pwn_debug .
3. 创建并运行Docker容器
docker run -it --privileged -p 9999:9999 --name pwn_debug_env pwn_debug /bin/bash
参数说明:
--privileged: 赋予容器足够权限-p 9999:9999: 开放端口用于调试--name pwn_debug_env: 为容器命名
4. 复制pwn文件到容器中
在宿主机执行:
docker cp ./your_pwn_file pwn_debug_env:/tmp/
5. 在容器中运行pwn程序
在docker容器的/tmp目录下创建run.sh文件并运行:
#!/bin/bash
gdbserver 0.0.0.0:9999 ./your_pwn_file
然后给执行权限并运行:
chmod +x run.sh
./run.sh
6. 修改exp脚本
在exp脚本中添加以下函数:
def gdbremote(p, gdbscript=None):
gdb_script = """
set follow-fork-mode parent
set detach-on-fork off
"""
if gdbscript:
gdb_script += gdbscript
with open("/tmp/gdb.sh", "w") as f:
f.write(gdb_script)
os.system(f"tmux split-window -h 'gdb -x /tmp/gdb.sh -ex \"target remote 127.0.0.1:9999\"'")
7. 调用方法
在exp脚本中正常使用:
p = process("./your_pwn_file")
gdbremote(p)
或者:
p = remote("127.0.0.1", 9999)
gdbremote(p)
8. 调试技巧
-
运行脚本后会弹出两个窗口:
- 一个是gdbserver窗口(无需操作)
- 另一个是gdb窗口(与正常使用
gdb.attach(p)相同)
-
在pause时需要先下断点再让exp运行,否则可能停不在预期位置
-
在gdb中使用:
b *0x?????? c然后才能让exp继续运行
-
通过CTRL+D退出gdb后,两个窗口都会关闭,此时可以重新运行脚本进行调试
注意事项
- 确保docker容器已正确配置并运行
- 端口9999未被占用
- 确保pwn文件已正确复制到容器中
- 调试时注意断点设置时机
- 该方法截至2025年4月15日仍然有效
优势总结
- 无需在docker内安装复杂的pwngdb插件
- 支持任意docker能运行的镜像系统
- 调试体验与本地调试几乎无差别
- 特别适合临时docker环境调试pwn程序
- 解决了pipe+tmux方案的输入阻塞问题