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.
Example: 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
- How to Use radare2 for Binary Analysis
- How to Use Ghidra for Reverse Engineering
- How to Use strace for Security Analysis
Built by theluckystrike — More at zovo.one