Skip to content

Instantly share code, notes, and snippets.

@edi33416
Last active March 28, 2024 02:42
Show Gist options
  • Save edi33416/c977eda93dcfc56be1fc20925f406f54 to your computer and use it in GitHub Desktop.
Save edi33416/c977eda93dcfc56be1fc20925f406f54 to your computer and use it in GitHub Desktop.
GDB intro layout
# gdb configuration file
# place contents in ~/.gdbinit
source /home/fawkes/ws/pwndbg/gdbinit.py
# auto-load directory in which we run gdb, so we can have a
# .gdbinit per project directory
add-auto-load-safe-path .
# path to your library. Multiple dirs can be separated by ':' as in the comment below
set directories /home/fawkes/ws/glibc/glibc-2.31/stdio-common/
#set directories /home/fawkes/ws/glibc/glibc-2.31/libio/:/home/fawkes/ws/glibc/glibc-2.31/stdio-common/
show directories
# uncomment if you want to change pwndbg sections
#set context-sections 'code backtrace regs disasm stack'
// Demo file for GDB Workshop
// This is the solution (debugged) version
#include <stdio.h>
#include <stdlib.h>
int is_prime(int value)
{
int d = 2;
while (d < (value - 1)) {
if (value % d == 0) {
return 0;
}
d++;
}
return 1;
}
int* get_n_primes(int n)
{
int *result = (int *) malloc (n * sizeof(int));
int i = 0;
int value = 2;
while (i < n) {
if (is_prime(value)) {
printf("Value %d is prime\n", value);
result[i] = value;
i++;
}
value++;
}
return result;
}
int main(int argc, char *argv[])
{
int n = 10;
int i = 0;
int sum = 0;
if (argc == 2) {
n = atoi(argv[1]);
}
int *primes = get_n_primes(n);
for (i = 0; i < n; i++) {
sum += primes[i];
}
printf("Sum of primes is %d\n", sum);
return 0;
}
// Demo file for GDB Workshop
// This is the bugged version, that will be debugged using gdb
#include <stdio.h>
#include <stdlib.h>
int is_prime(int value)
{
int d = 2;
while (d < (value - 1)) {
if (value % d == 0) {
return 0;
d++;
}
}
return 1;
}
int* get_n_primes(int n)
{
int *result = (int *) malloc (n * sizeof(int));
int i = 0;
int value = 2;
while (i < n) {
if (is_prime(value)) {
printf("Value %d is prime\n", value);
result[i] = value;
i++;
value++;
}
}
return result;
}
int main(int argc, char *argv[])
{
int n = 10;
int i = 0;
int sum = 0;
if (argc == 2) {
n = atoi(argv[2]);
}
int *primes = get_n_primes(n);
for (i = 0; i < n; i++) {
sum =+ primes[i];
}
printf("Sum of primes is %d\n", sum);
return 0;
}

GDB Demo

Tools used

GDB intro

  • make sure you compile with debug symbols: -g
gcc -g demo.c -o demo
  • gdb basics:

    • run
    • layout src - open TUI to view source code
    • backtrace
      • we can reach a function from multiple codepaths, but only one leads to our bug
    • breakpoint
    • watch
    • next instr
    • step into next instr
    • print
    • continue
    • help - the man of gdb
  • gdb basics++:

    • disassemble
    • info breakpoint
    • delete breakpoint
    • tbreak - temporary breakpoint
    • start - equivalent to tbreak at main entrypoint
    • finish - execute until selected stack frame returns
    • set CLI arguments
    set args <arg1> <arg2> ... <argN>
    
    • set and use variables
    set $i = 0
    print $i++
    
    • useful to print array elements print v[$i++]

GDB power user

  • .gdbinit

    • a config file for gdb
    • read when gdb starts
    • why it matters?
      • gdb is scriptable
      • we can place gdb commands in .gdbinit to save time
      • demo
    • a .gdbinit per project
      • add add-auto-load-safe-path . to ~/.gdbinit
    • view library code
      • enter Text User Interface (TUI) mode - Ctrl+x+a (toggle TUI mode)

        step into printf, toggle TUI, get missing source file error

      • install libc6-dbg
      • show directories - where gdb looks for source files. Instruct to look inside libc's stdio path
      • set directories in .gdbinit
  • pwndbg

    • a gdb plugin that enhances the user experience
    • discuss displayed sections
      • registers, disasm, code, stack, backtrace
    • configure your display: as per docs, use config command
    • use set <config-var> <config-value> to modify config
      • ex. set context-sections 'regs disasm stack'
      • place it in your .gdbinit
  • gdbserver

    • gdb remote debugging
    • useful to debug remote programs
      • on VMs
      • on embedded systems with constrained resources: gdb won't fit on the embedded device -> gdbserver is a lot smaller
    • on remote (target) machine
    gdbserver localhost:4444 program
    
    • on host machine, connect to target and start debugging
    # start gdb in quiet mode
    $ gdb -q
    target remote <remote-addr>:4444
    
  • variables++

    • access registers - print $rip
    • hijack control flow
    set $rip = addr
    set $rax = value
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment