My Pwndbg GDB Init Setup

My Pwndbg GDB Init Setup

This is my current .gdbinit setup for binary exploitation and reverse engineering. It loads pwndbg, switches disassembly to Intel syntax, follows child processes after fork, and automatically opens separate tmux panes for disassembly, stack, backtrace, registers, and an IPython scratch pane.

Requirements

Install these first:

  • gdb
  • pwndbg
  • tmux
  • ipython optional, only used for the scratch pane

The config assumes pwndbg is installed at:

1
/usr/share/pwndbg/gdbinit.py

If your pwndbg install path is different, change the first line of the config.

Install

Put the following content in ~/.gdbinit:

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
source /usr/share/pwndbg/gdbinit.py
set history save on
set follow-fork-mode child
set disassembly-flavor intel

set $mybase1 = 0x0000555555554000
set $mybase = 0x7ffff7ffc000

python
import os
import atexit
import pwndbg
from pwndbg.commands.context import contextoutput

if 'TMUX' in os.environ:
created_panes = []

def create_pane(split_cmd):
output = os.popen(split_cmd).read().strip()
if not output: return None, None
pane_id, tty = output.split(":")
created_panes.append(pane_id)
return pane_id, tty

p_disasm_id, p_disasm_tty = create_pane('tmux split-window -vb -P -F "#{pane_id}:#{pane_tty}" -l 75% -d "cat -"')
p_stack_id, p_stack_tty = create_pane(f'tmux split-window -v -P -F "#{{pane_id}}:#{{pane_tty}}" -l 40% -t {p_disasm_id} -d "cat -"')
p_bt_id, p_bt_tty = create_pane('tmux split-window -h -P -F "#{pane_id}:#{pane_tty}" -t -1 -l 30% -d "cat -"')
p_regs_id, p_regs_tty = create_pane(f'tmux split-window -h -P -F "#{{pane_id}}:#{{pane_tty}}" -t {p_stack_id} -l 30% -d "cat -"')
p_ipy_id, p_ipy_tty = create_pane('tmux split-window -h -P -F "#{pane_id}:#{pane_tty}" -l 30% -d "ipython"')

if p_disasm_tty: contextoutput("disasm", p_disasm_tty, True, 'top', False)
if p_stack_tty: contextoutput("stack", p_stack_tty, True, 'top', False)
if p_bt_tty: contextoutput("backtrace", p_bt_tty, True, 'top', False)
if p_regs_tty: contextoutput("regs", p_regs_tty, True, 'top', False)

if p_stack_tty: contextoutput("legend", p_stack_tty, True)
if p_regs_tty: contextoutput("expressions", p_regs_tty, True, 'top', False)

def cleanup_panes():
for pid in created_panes:
os.system(f"tmux kill-pane -t {pid} >/dev/null 2>&1")

atexit.register(cleanup_panes)
else:
print("\n[\033[33m*\033[0m] Not running inside TMUX. Standard pwndbg output will be used.")

pwndbg.config.context_disasm_lines.value = 25
pwndbg.config.context_stack_lines.value = 18
end

Usage

Start a tmux session first:

1
tmux

Then run GDB or pwndbg normally:

1
gdb ./chall

or:

1
pwndbg ./chall

When GDB starts inside tmux, the config creates panes for:

  • disasm: current instruction context
  • stack: stack view plus pwndbg legend
  • backtrace: call stack
  • regs: registers and expressions
  • ipython: scratch Python shell

When GDB exits, the created tmux panes are killed automatically through the atexit cleanup hook.

If GDB is not running inside tmux, no panes are created and pwndbg falls back to the normal inline context output.

Important Lines

1
set history save on

Keeps GDB command history across sessions.

1
set follow-fork-mode child

After fork(), GDB follows the child process. This is useful for fork-based CTF services where the vulnerable logic runs in the child.

1
set disassembly-flavor intel

Uses Intel syntax instead of AT&T syntax.

1
2
pwndbg.config.context_disasm_lines.value = 25
pwndbg.config.context_stack_lines.value = 18

Controls how much disassembly and stack context pwndbg prints.

Base Address Helpers

These two lines are personal scratch variables:

1
2
set $mybase1 = 0x0000555555554000
set $mybase = 0x7ffff7ffc000

They are not required. I use them as quick base-address anchors while debugging PIE binaries or shared libraries. You can remove them or replace them with values from piebase, vmmap, or a leak.

Example usage:

1
2
x/10i $mybase1 + 0x1234
b *($mybase1 + 0x19e3)

Adjusting The Layout

The pane sizes are controlled by tmux split-window -l:

1
2
3
'tmux split-window -vb ... -l 75% ...'
'tmux split-window -v ... -l 40% ...'
'tmux split-window -h ... -l 30% ...'

Change these percentages if the panes are too large or too small for your monitor.

If you do not want the IPython pane, remove this line:

1
p_ipy_id, p_ipy_tty = create_pane('tmux split-window -h -P -F "#{pane_id}:#{pane_tty}" -l 30% -d "ipython"')

Troubleshooting

If GDB prints Not running inside TMUX, start tmux first and launch GDB from inside it.

If pwndbg fails to load, verify the path:

1
ls /usr/share/pwndbg/gdbinit.py

If ipython fails, install it or remove the IPython pane line.

If the panes stay open after a crash, close them manually:

1
tmux kill-pane -t <pane_id>