Fundamentals 40 min read

Master Debugging Stripped Executables with GDB: A Step‑by‑Step Guide

This comprehensive guide explains why debugging stripped binaries is crucial, walks through installing GDB, shows how to disassemble code, set address‑based breakpoints, inspect memory, handle signals, use advanced features like backtraces, conditional breakpoints, watchpoints, remote debugging, and even basic heap analysis for C/C++ programs.

Deepin Linux
Deepin Linux
Deepin Linux
Master Debugging Stripped Executables with GDB: A Step‑by‑Step Guide

In software development, debugging is a critical skill, especially when dealing with stripped executables that lack symbol tables, which can occur due to special compiler options or third‑party libraries. Without symbols, developers face a "dark forest" of unknown function calls and variable changes, but GDB can illuminate the program’s behavior.

Debugging stripped binaries is also essential in security analysis, where malware and reverse engineering rely on inspecting program execution to understand attack mechanisms and devise defenses.

1. Interview Question Interpretation

Question: How to use GDB to debug an executable without debugging information?

Approach: Even without symbols, basic debugging is possible. Install GDB, start it with the program, and use commands like break (address or offset), run, next, step, and print to set breakpoints, step through code, and inspect memory or registers.

2. GDB Basics

2.1 What is GDB?

GDB (GNU Debugger) is a powerful open‑source debugger for C, C++, and other languages, widely used since 1986.

Official website: https://www.gnu.org/software/gdb/

Supported languages: Ada, C, C++, Objective‑C, Pascal, etc.

Works for local and remote debugging.

2.2 Installation and Startup

Linux (Debian/Ubuntu): sudo apt -y install gdb RedHat/CentOS/Fedora: sudo yum -y install gdb macOS (Homebrew): brew install gdb (additional permissions may be required) Windows (MinGW): install GDB component and add to PATH.

Start GDB with gdb program, optionally with a core file or PID.

2.3 Differences Between Symbolic and Stripped Debugging

With symbols, you can set breakpoints by line number or function name. Without symbols, you must use addresses or offsets, making debugging more challenging.

2.4 Core File Debugging

A core file records a program’s memory image at crash. Enable core dumps with ulimit -c unlimited and debug with gdb program core, then use bt to view the stack.

3. Common GDB Commands

3.1 Start and Exit

gdb <program>

– start GDB and load the executable. q – quit GDB.

3.2 Viewing Source

list

or 1 – show 10 lines of source. 1<line> – show lines around a specific line. 1<function> – show source of a function.

3.3 Breakpoints

Set breakpoints with break <line|function|address>. Conditional breakpoints: break ... if condition. Temporary breakpoints: tbreak. Function breakpoints: rbreak. Delete with clear or delete. Enable/disable with enable / disable.

3.4 Watchpoints

Monitor variable changes: watch var. Read watch: rwatch var. Read/write watch: awatch var.

3.5 Catchpoints

Catch events like exceptions, exec, fork, load, unload, etc., using catch <event>.

3.6 Signal Handling

Control how GDB handles signals with handle SIGNAL MODE where MODE can be stop, nostop, print, noprint, pass, nopass, etc.

3.7 Stack Inspection

Use backtrace ( bt) to view call stack, frame to select a frame, info args, info locals for arguments and locals, and info registers for registers.

3.8 Memory and Register Examination

Examine memory with x /nfu address where n is count, f format (x, d, u, o, t, a, c, f), and u unit size (b, h, w, g).

4. Debugging Workflow

Typical steps: start program, set breakpoints, run, inspect state, modify execution environment.

5. Debugging Stripped Executables with GDB

5.1 Preparation

Compile a simple C program without -g (e.g., gcc example.c -o example) to produce a stripped binary.

5.2 Disassembly

Load the binary in GDB ( gdb example) and disassemble functions ( disassemble main) to obtain instruction addresses.

Dump of assembler code for function main:
 0x0804841d <+0>: push %ebp
 0x0804841e <+1>: mov %esp,%ebp
 ...
 0x0804845e <+65>: ret
End of assembler dump.

5.3 Setting Breakpoints by Address

Use the disassembly addresses to set breakpoints, e.g., break *0x08048453 before the printf call, or break *0x0804843e at the addition instruction.

5.4 Debugging Commands

Run with run ( r), continue with continue ( c). Since variables lack symbols, inspect memory with x /1dw address after determining the variable’s stack location from the disassembly.

Step through with next ( n) or step ( s) to follow execution flow.

5.5 Common Issues

Breakpoint not hit: Verify address accuracy; compiler optimizations may change instruction layout. Re‑compile without optimizations or adjust addresses.

Unable to view variables: Use memory examination ( x) based on stack analysis, or set multiple breakpoints to observe changes.

6. Advanced GDB Features

6.1 Backtrace

Use bt to view the call stack with function names and arguments, aiding in pinpointing where an error originated.

(gdb) bt
#0 function_c (num=6) at test.c:5
#1 function_b (num=5) at test.c:9
#2 function_a () at test.c:13
#3 main () at test.c:17

6.2 Dynamic Memory Inspection

Load a heap‑analysis script (e.g., source /path/to/gdbheap.py) and attach to a running process ( attach <pid>) to view heap allocations, detect leaks, and spot illegal accesses.

(gdb) monitor heap

6.3 Conditional Breakpoints & Watchpoints

Set breakpoints that trigger only when a condition is true, e.g., break func if i >= size. Use watchpoints ( watch var, rwatch var, awatch var) to stop execution when a variable changes or is accessed.

6.4 Remote Debugging

Run gdbserver :<port> /path/to/program on the target machine, then on the host machine connect with gdb local_program followed by target remote <host>:<port>. This enables full GDB functionality over the network.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DebuggingC programmingreverse engineeringgdbcore dumpstripped executable
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.