告别print调试:在VSCode里用pwntools的context.log_level和gdb.attach高效排错
·
告别print调试:在VSCode里用pwntools的context.log_level和gdb.attach高效排错
在二进制漏洞利用(Pwn)领域,调试过程往往比编写利用脚本本身更加耗时。传统print调试不仅效率低下,还容易遗漏关键信息。本文将介绍如何利用pwntools的 context.log_level 和 gdb.attach() 功能,结合VSCode打造高效的本地调试工作流。
1. 为什么需要更好的调试方法
调试二进制漏洞利用脚本时,开发者常面临以下痛点:
- 信息不全 :print语句只能输出预设的变量值,无法获取程序运行时的完整状态
- 效率低下 :每次修改脚本后需要重新运行,无法实时观察内存变化
- 断点困难 :传统方法难以在关键指令处暂停执行并检查寄存器状态
pwntools提供的调试工具链能完美解决这些问题:
# 开启debug日志输出
context.log_level = 'debug'
# 动态附加GDB调试器
gdb.attach(io)
pause() # 暂停执行等待调试器连接
2. 配置VSCode调试环境
2.1 安装必要插件
在VSCode中安装以下扩展:
- Python :官方Python支持
- Native Debug :提供GDB调试支持
- Hex Editor :方便查看二进制数据
2.2 配置launch.json
在VSCode中创建或修改 .vscode/launch.json :
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "GDB Attach",
"type": "gdb",
"request": "attach",
"executable": "./target_binary",
"target": ":1234",
"remote": true,
"cwd": "${workspaceRoot}"
}
]
}
3. 使用context.log_level替代print调试
context.log_level 提供了多个日志级别:
| 日志级别 | 输出内容 | 适用场景 |
|---|---|---|
| debug | 所有通信细节 | 详细调试 |
| info | 关键操作信息 | 日常使用 |
| warn | 警告信息 | 错误排查 |
| error | 错误信息 | 紧急问题 |
典型用法:
from pwn import *
# 设置全局日志级别
context.log_level = 'debug'
# 也可以针对特定操作设置
with log.progress('Exploiting...') as p:
p.status('Sending payload')
io.send(payload)
相比print调试的优势:
- 自动记录所有通信 :无需手动添加print语句
- 结构化输出 :不同级别信息以不同颜色显示
- 时间戳 :方便分析执行时序问题
4. 动态GDB调试技巧
4.1 基本使用方法
在脚本中插入调试点:
# 在需要调试的位置插入
gdb.attach(io, '''
break *0x401234
continue
''')
pause() # 等待调试器连接
4.2 实用GDB命令
常用调试命令组合:
# 查看寄存器状态
info registers
# 查看栈内容
x/20xg $rsp
# 查看内存映射
info proc mappings
# 设置硬件断点
hbreak *0x401234
4.3 自动化调试脚本
可以预定义GDB脚本:
gdb_script = '''
set follow-fork-mode child
break *vuln_function+0x10
commands
info registers
x/10i $rip
continue
end
continue
'''
gdb.attach(io, gdb_script)
5. 实战调试案例
假设我们有一个简单的栈溢出漏洞程序 vuln ,以下是完整的调试流程:
- 首先编写基础利用脚本:
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
io = process('./vuln')
payload = b'A'*40 + p64(0x401156) # 填充+返回地址
io.sendlineafter(b'> ', payload)
io.interactive()
- 在关键位置添加调试点:
# 在发送payload前暂停
gdb.attach(io, '''
break *main+45
continue
''')
pause()
io.sendlineafter(b'> ', payload)
- 在VSCode中:
- 先启动Python调试会话
- 当脚本执行到
pause()时,启动GDB Attach配置 - 在GDB中检查寄存器、内存状态
6. 高级调试技巧
6.1 条件断点
gdb.attach(io, '''
break *0x401234 if $rdi == 0xdeadbeef
continue
''')
6.2 内存监控
gdb.attach(io, '''
watch *(int*)0x7fffffffe010
continue
''')
6.3 多进程调试
gdb.attach(io, '''
set follow-fork-mode child
break *0x401234
continue
''')
在实际项目中,我发现最有效的调试策略是结合日志级别和条件断点。例如,先使用 context.log_level='debug' 定位大致问题区域,然后在关键地址设置条件断点进行精细调试。这种方法相比纯print调试效率提升了至少3倍,特别是在处理复杂的内存破坏漏洞时。
更多推荐

所有评论(0)