利用pwntools脚本联动内置gdb函数优雅的调试docker中的pwn程序
字数 1074 2025-08-29 22:41:10

利用pwntools脚本联动内置gdb函数优雅调试docker中的pwn程序

背景与问题描述

在CTF的PWN模块中,我们经常需要使用gdb来联动exp脚本调试pwn程序。pwntools的内置函数gdb.attach()在本地调试时非常方便,但存在以下问题:

  1. 本地环境与pwn程序编译时的原生环境存在差异
  2. 特殊架构(如mips)或使用C++库的程序,使用patchelf替换libc库效果不佳
  3. 之前尝试的pipe+tmux组合方案存在输入阻塞问题
  4. 在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. 调试技巧

  1. 运行脚本后会弹出两个窗口:

    • 一个是gdbserver窗口(无需操作)
    • 另一个是gdb窗口(与正常使用gdb.attach(p)相同)
  2. 在pause时需要先下断点再让exp运行,否则可能停不在预期位置

  3. 在gdb中使用:

    b *0x??????
    c
    

    然后才能让exp继续运行

  4. 通过CTRL+D退出gdb后,两个窗口都会关闭,此时可以重新运行脚本进行调试

注意事项

  1. 确保docker容器已正确配置并运行
  2. 端口9999未被占用
  3. 确保pwn文件已正确复制到容器中
  4. 调试时注意断点设置时机
  5. 该方法截至2025年4月15日仍然有效

优势总结

  1. 无需在docker内安装复杂的pwngdb插件
  2. 支持任意docker能运行的镜像系统
  3. 调试体验与本地调试几乎无差别
  4. 特别适合临时docker环境调试pwn程序
  5. 解决了pipe+tmux方案的输入阻塞问题
利用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文件,内容如下: 2. 构建Docker镜像 3. 创建并运行Docker容器 参数说明: --privileged : 赋予容器足够权限 -p 9999:9999 : 开放端口用于调试 --name pwn_debug_env : 为容器命名 4. 复制pwn文件到容器中 在宿主机执行: 5. 在容器中运行pwn程序 在docker容器的/tmp目录下创建run.sh文件并运行: 然后给执行权限并运行: 6. 修改exp脚本 在exp脚本中添加以下函数: 7. 调用方法 在exp脚本中正常使用: 或者: 8. 调试技巧 运行脚本后会弹出两个窗口: 一个是gdbserver窗口(无需操作) 另一个是gdb窗口(与正常使用 gdb.attach(p) 相同) 在pause时需要先下断点再让exp运行,否则可能停不在预期位置 在gdb中使用: 然后才能让exp继续运行 通过CTRL+D退出gdb后,两个窗口都会关闭,此时可以重新运行脚本进行调试 注意事项 确保docker容器已正确配置并运行 端口9999未被占用 确保pwn文件已正确复制到容器中 调试时注意断点设置时机 该方法截至2025年4月15日仍然有效 优势总结 无需在docker内安装复杂的pwngdb插件 支持任意docker能运行的镜像系统 调试体验与本地调试几乎无差别 特别适合临时docker环境调试pwn程序 解决了pipe+tmux方案的输入阻塞问题