两个程序交互场景下如何使用GDB跟踪调试目标二进制程序?
解决方案
方案1:Pwntools原生调试(推荐)
直接通过pwntools托管程序启动和GDB附加,无需额外做端口转发,自动处理多步交互逻辑,支持任意字节payload构造:
- 编写exp脚本示例如下:
from pwn import * # 加载目标程序 p = process('./programA') # 附加GDB并预设断点,将0xXXXXXXXX替换为你要断住的溢出触发地址 gdb.attach(p, gdbscript=''' b *0xXXXXXXXX continue ''') # 按交互流程自动发送对应数据 p.sendafter(b'请输入姓名', b'test_user') p.sendafter(b'请输入选项编号', b'1') p.sendafter(b'请输入待分配的用户姓名长度', b'32') # 构造包含非ASCII特殊字符的payload,这里示例为30字节填充+2字节溢出覆盖 payload = b'A'*30 + p16(0xffffdd80) p.sendafter(b'请输入缓冲区字符串内容', payload) # 触发断点后可在GDB中查看寄存器、内存值 p.interactive()
- 运行脚本后会自动加载GDB调试界面,payload触发断点后即可直接查看寄存器值和内存变化。
方案2:原生端口绑定+GDB附加
如果你要保留原来的nc绑定端口的逻辑,可直接通过进程附加的方式让GDB接管程序运行:
- 先运行端口绑定命令:
nc -lnp 7777 -e ./programA - 新开终端查询programA的进程PID:
ps aux | grep programA - 启动GDB附加到对应进程:
gdb ./programA [查询到的PID] - 在GDB中设置断点后输入
continue让程序继续运行,用你的程序B连接127.0.0.1:7777发送payload即可触发断点调试。
如果需要更稳定的交互避免输入输出乱序,可改用socat做流量转发:
- 启动socat生成虚拟终端绑定端口:
socat TCP-LISTEN:7777,reuseaddr,fork PTY,link=/tmp/prog_io,raw,echo=0 - 启动GDB加载程序,运行时重定向输入输出到虚拟终端:
gdb ./programA (gdb) run < /tmp/prog_io > /tmp/prog_io 2>&1
- 程序B连接端口发送数据即可,GDB调试不受影响。
C语言等效库推荐
和pwntools功能对齐的C语言开发库可选:
- libpwntools:C语言版pwn开发库,封装了套接字通信、字节序转换、payload构造、GDB附加等常用功能,API设计和Python版pwntools高度一致,适合编写高性能漏洞利用代码。
- libsocket:轻量级套接字封装库,无额外依赖,如果你只需要套接字通信功能,自己实现payload构造逻辑的话可以选用。
内容的提问来源于stack exchange,提问作者Amine Bensalem
相关产品推荐
相关产品推荐

