Last updated: March 22, 2026

How to Use GDB for Security Debugging

GDB (GNU Debugger) is the standard debugger for Linux binaries. Security researchers use it to step through execution, inspect memory, find overflow conditions, and understand what a suspicious binary actually does at runtime. This guide focuses on security-relevant techniques: stack analysis, vulnerability identification, and controlled execution.

Installation

Debian/Ubuntu
sudo apt install -y gdb gdb-multiarch

Add GDB extensions for better security research experience
PEDA (Python Exploit Development Assistance)
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

Or pwndbg (more active development)
git clone https://github.com/pwndbg/pwndbg
cd pwndbg && ./setup.sh

Verify:

gdb --version

Starting GDB

Debug a binary
gdb ./target_binary

Debug with arguments
gdb --args ./target_binary arg1 arg2

Attach to running process
gdb -p PID

Remote debugging (target running GDB server)
gdb target_binary
(gdb) target remote 192.168.1.50:1234

Essential GDB Commands

Command             Action
-------             ------
r / run             Start execution
r arg1 arg2         Start with arguments
c / continue        Continue execution after breakpoint
s / step            Step into next instruction (source level)
si                  Step into next instruction (assembly level)
n / next            Step over next instruction (source level)
ni                  Step over next instruction (assembly level)
q / quit            Exit GDB

Setting Breakpoints

Break at function name
(gdb) break main
(gdb) break sym.process_input

Break at address
(gdb) break *0x00401180

Break at line number (if debug symbols available)
(gdb) break main.c:42

List all breakpoints
(gdb) info breakpoints

Delete breakpoint
(gdb) delete 1

Inspecting Memory and Registers

Show all register values
(gdb) info registers

Show specific register
(gdb) print $rsp
(gdb) print $rbp
(gdb) print $rip

Examine memory at address
Format - x/[count][format][size] address
Formats - x=hex, d=decimal, s=string, i=instructions
Sizes - b=byte, h=halfword, w=word, g=giant(8bytes)

16 hex bytes at stack pointer
(gdb) x/16xb $rsp

20 instructions at instruction pointer
(gdb) x/20i $rip

String at address
(gdb) x/s 0x402010

Stack inspection. 20 words from current stack pointer
(gdb) x/20wx $rsp

Analyzing Stack Frames

Show current stack frame
(gdb) info frame

Show all stack frames (call stack)
(gdb) backtrace
(gdb) bt

Move up/down stack frames
(gdb) up
(gdb) down

Show local variables in current frame
(gdb) info locals

Show function arguments
(gdb) info args

Finding Buffer Overflows

The most common security debugging task: finding where input overflows a buffer.

Testing an Overflow Condition

Generate a cyclic pattern to find the overflow offset
Using python to create a De Bruijn sequence
python3 -c "
import string
chars = string.ascii_letters + string.digits
pattern = ''
for i in range(len(chars)):
    for j in range(len(chars)):
        pattern += chars[i] + chars[j]
print(pattern[:200])
" > /tmp/pattern.txt

Run the binary with the pattern
(gdb) run $(cat /tmp/pattern.txt)

When it crashes, check where RIP/EIP points
(gdb) info registers rip
The value in RIP tells you the offset within the pattern

With pwndbg or PEDA, this is easier:

In pwndbg
(gdb) cyclic 200
Copy the output and run:
(gdb) run AAAaBAAcBAAd...

On crash:
(gdb) cyclic -l $rsp    # Find offset automatically

Inspecting a Stack Frame During a Crash

(gdb) run $(python3 -c "print('A'*200)")

On segfault:
(gdb) info registers

Typical output showing overwritten RIP:
rip  0x4141414141414141  <-- 'AAAA...' has overwritten return address

Show what's on the stack around the overflow
(gdb) x/40wx $rsp-80

Examining Function Calls

Disassemble a function
(gdb) disassemble main
(gdb) disassemble /m main    # Mix source and assembly if symbols available

Set a breakpoint before a dangerous function call
(gdb) break strcpy
(gdb) run test_input

When stopped at strcpy, examine arguments
(gdb) info args
Or manually - first arg in rdi, second in rsi (x86_64 calling convention)
(gdb) x/s $rdi    # destination buffer
(gdb) x/s $rsi    # source string
(gdb) print (int)strlen($rsi)    # length of input

Watchpoints - Monitoring Memory Changes

Watch for writes to a specific memory address
(gdb) watch *0x00404010

Watch for reads
(gdb) rwatch *0x00404010

Watch a variable (if symbols available)
(gdb) watch password_buf

When the watched location changes, GDB pauses and shows you what caused the change. invaluable for tracking how attacker-controlled input propagates through memory.

Scripting GDB with Python

Automate repetitive analysis:

gdb_audit.py. run with: gdb -x gdb_audit.py ./target

import gdb

class SecurityAudit(gdb.Command):
    def __init__(self):
        super(SecurityAudit, self).__init__("audit", gdb.COMMAND_USER)

    def invoke(self, arg, from_tty):
        # Run to main
        gdb.execute("break main")
        gdb.execute("run")

        # Check for dangerous functions
        dangerous_funcs = ['strcpy', 'gets', 'sprintf', 'system', 'exec']
        print("\n[*] Checking for dangerous function calls:")
        for fn in dangerous_funcs:
            result = gdb.execute(f"info functions {fn}", to_string=True)
            if fn in result:
                print(f"  [!] Found: {fn}")

        # Show security mitigations
        print("\n[*] Binary security properties:")
        gdb.execute("checksec")

SecurityAudit()
gdb -x gdb_audit.py ./target
(gdb) audit

Remote Debugging for Embedded Targets

On the target device (ARM, MIPS, etc.)
gdbserver 0.0.0.0:1234 ./target_binary

On your analysis machine
gdb-multiarch ./target_binary
(gdb) set architecture arm
(gdb) target remote 192.168.1.100:1234
(gdb) continue

This is essential for analyzing firmware running on embedded systems where installing GDB locally is impractical.

Quick Security Triage Commands

When you get an unknown binary, run these in sequence:

gdb ./unknown_binary

(gdb) info file        # File type and architecture
(gdb) info functions   # List all function symbols
(gdb) checksec         # Security mitigations (PEDA/pwndbg)
(gdb) break main
(gdb) run
(gdb) info registers   # Initial register state
(gdb) x/20i $rip       # First 20 instructions
(gdb) bt               # Backtrace

Related Reading


Built by theluckystrike. More at zovo.one