一直以来都在使用tmux作为终端复用的工具,非常喜欢它可以自由切换、分割当前终端的功能。现在自己每次都是通过ssh登录到调试机,然后使用tmux创建一个session在后台,这样就算因为网络原因ssh断掉,当前终端正在进行的工作也不会断掉。 最基础的流程就是:
tmux new -s test
:创建一个名为test的session
Ctrl + B,然后"
:水平切割当前的pane
Ctrl + B,然后%
:垂直切割当前pane 更多操作可以参考这个教程:Tmux 使用教程 - 阮一峰的网络日志
最近在看pwndbg的FEATURES.md时,发现其支持一个特性:将其section重定向到任意的tty 。那么通过这个功能就可以实现将pwndbg的各个section重定向到终端由tmux切割出来的不同pane上,从而最大化利用当前的屏幕(也更好看)。
也有人在pwndbg的基础上开发出了另外一个插件splitmind ,其官方库中给出的一个实现效果如下,在一个由tmux分割的终端上,让pwndbg调试信息区域按照使用人员最喜欢的方式排列、输出。
如上的实现配置文件gdb.init如下,其大概原理就是:在tmux的一个window中,会默认打开一个名为main的gdb调试pane,然后基于该main的上、下、左、右可以自由进行窗口的切割和划分,并将pwndbg相应的section重定向到切割出来的pane中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 source /home/user/pwndbg/gdbinit.py set context-clear-screen on set follow-fork-mode parent source /home/user/splitmind/gdbinit.py python import splitmind (splitmind.Mind() .tell_splitter(show_titles=True) .tell_splitter(set_title="Main") .right(display="backtrace", size="25%") .above(of="main", display="disasm", size="80%", banner="top") .show("code", on="disasm", banner="none") .right(cmd='tty; tail -f /dev/null', size="65%", clearing=False) .tell_splitter(set_title='Input / Output') .above(display="stack", size="75%") .above(display="legend", size="25") .show("regs", on="legend") .below(of="backtrace", cmd="ipython", size="30%") ).build(nobanner=True) end set context-code-lines 30 set context-source-code-lines 30 set context-sections "regs args code disasm stack backtrace"
例如:.above(of="main", display="disasm", size="80%", banner="top")
,就是对main进行切割,展示pwndbg的disasm区域,并且控制所占据的大小为80%。
pwndbg所支持的section如下,在gdb中由context-sections
变量控制:
regs:寄存器
disasm:反汇编
code:源代码
ghidra:Ghidra相关(未使用过)
stack:栈
backtrace:调用栈
expressions:表达式跟踪,非常强大,可用于动态根据某个变量、内存、或者是自定义的值类型 与之配合的还有一些其他的gdb调试环境变量,例如
context-code-lines
:在disasm中展示的反汇编行数
context-source-code-lines
:在code中展示的源代码行数
context-stack-lines
:在stack中展示的栈行数 等等,这些都可以在pwndbg/pwndbg/commands/context.py
去查询含义以及默认值。了解section和控制section大小的环境变量可以让我们更好自定义属于自己的gdb界面。
在如上的基础上,我定制了自己的一个gdb配置,能达到的效果就是,在gdb启动的时候选择模式,并按照自己的习惯展示gdb调试信息:
s:源代码模式,可用于直接调试源码
d:汇编模式,用于调试反汇编
m:同时显示源码和汇编语句
s:源码模式,如下
d:汇编模式,如下
m:混合模式,如下
那么直接给出我的gdb配置文件,也给出了相应的注释,更多的配置还可以参考我个人的GitHub配置文件库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 # 加载pwndbg和gdbinit插件 source /home/utest/app/pwndbg/gdbinit.py source /home/utest/app/splitmind/gdbinit.py # 调试过程是否每次输入一条指令都清屏,我选择否这样可以在main区域看到程序输出 set context-clear-screen off set debug-events off # python执行区域 python sections = "regs" # sections控制所要展示的所有区域,先初始化只有寄存器regs mode = input("source/disasm/mixed mode:?(s/d/m)") or "d" # 读取调试模式 import splitmind # 导入splitmind库 spliter = splitmind.Mind() # 创建一个spliter spliter.select("main").right(display="regs", size="50%") legend_on = "code" if mode == "d": legend_on = "disasm" sections += " disasm" spliter.select("main").above(display="disasm", size="70%", banner="none") gdb.execute("set context-code-lines 30") elif mode == "s": sections += " code" spliter.select("main").above(display="code", size="70%", banner="none") gdb.execute("set context-source-code-lines 30") else: sections += " disasm code" spliter.select("main").above(display="code", size="70%") spliter.select("code").below(display="disasm", size="40%") gdb.execute("set context-code-lines 8") gdb.execute("set context-source-code-lines 20") sections += " args stack backtrace expressions" spliter.show("legend", on=legend_on) spliter.show("stack", on="regs") spliter.show("backtrace", on="regs") spliter.show("args", on="regs") spliter.show("expressions", on="args") # 自定义的一些gdb环境变量 gdb.execute("set context-stack-lines 10") gdb.execute("set context-sections \"%s\"" % sections) spliter.build() end