Quick Notes: GDB Cheatsheet

Below is a smattering of gdb hints, tips, and tricks. Some might even be useful during this course. If you’d like to contribute to this cheatsheet, let me know! The course shell server loads GEF by default, which makes GDB friendlier for exploit development and binary analysis. If you build your own local environment later, install GEF if you want the same commands and output shown in class.

Arguments:

  • Use gdb -ex COMMAND to start GDB and execute the given COMMAND. For example, gdb -ex r will load the binary in gdb and then execute the run command.
  • Use gdb --pid <pid> to attach to a running process

Basics:

  • Use “-g” when compiling with GCC to enable debug symbols, providing more information to GDB.
  • To switch to Intel syntax: set disassembly-flavor intel
  • Use set {int}0x8049700=0xdeadbeef to write the value 0xdeadbeef to address 0x8049700.
  • Remember you can use int3 in your shellcode (op code 0xcc) to cause a breakpoint.
  • Execute shell commands, e.g., shell clear will clear the screen.
  • Use the dir command to specify the local directory containing the source files.

GEF quick reference:

  • context redraws the GEF register, stack, code, and backtrace panes.
  • checksec shows binary protections such as NX, PIE, RELRO, and stack canaries. You can also run checksec ./binary before starting the program.
  • vmmap shows the process memory map and page permissions.
  • xinfo <address> explains where an address lives and what permissions that page has. Registers work here too, e.g., xinfo $rsp.
  • pattern create <length> creates a cyclic pattern for finding overwrite offsets, and pattern search <value> finds the matching offset.
  • search-pattern <value> searches process memory for a value or address.

Running the binary:

  • run and r will run the current program.
  • kill will kill the current program.
  • Reload the binary: file foo, useful if you pop a shell with execv from inside of gdb.
  • Run the current program with input from a file: r < input.in
  • Run the current program with command line args: r foo bar
  • Or run with arbitrary arguments: r < <(python exploit.py)

Working with breakpoints:

  • Setting by function symbol: break *main or b *main.
  • Setting by source code function: break main
  • By offset in function: b *main+10
  • By address: break *0x400D02
  • By line number in file: break foo.c:12
  • List current break points: info break
  • delete <num> deletes a breakpoint by number
  • clear delete all breakpoints
  • enable <num> enables a breakpoint by number
  • disable <num> disables a breakpoint by number

Stepping:

  • si will step instruction by instruction going into function calls whereas
  • ni will step over function calls.
  • step will execute until the next source line, going into function calls.
  • next will execute until the next source line, not going into functions.
  • finish will execute until the current function returns
  • continue will continue normal execution.
  • Be careful though, si and ni seem to skip over int3 instructions.
  • f 4 will jump to the fourth stack frame. This is useful when an error occurs within a library function and you’d like to see what arguments were passed from the calling function(s).

Working with the heap:

  • heap chunks (gef only) will give a list of the current heap chunks.
  • heap bins (gef only) will summarize the current state of all heap bins.

Working with registers:

  • Getting values: info registers or i r
  • Setting values: set $eax=0

Getting information:

  • info functions
  • disassemble main or disass main to disassemble a function.
  • This command will disassemble the function that contains the instruction at address 0x08… disassemble 0x08...
  • aslr will tell you if ASLR is enabled from GDB’s perspective. Note that the output may be different before running the binary. You can disable ASLR with aslr off.
  • Use vmmap to view memory regions and permissions.
  • View the mapped address space: info proc mappings
  • Print out the string representation of the bytes at a given address: x/s 0x4005d0
  • Print out a word of memory relative to the stack pointer: x/wx $esp+0x5c
  • x foo will give you the location of function foo.
  • p system will give you the address of the libc function system.
  • Use backtrace to find out where you where in a program when it crashed, e.g., after a segmentation fault. Caveat, if your bug smashes the stack then the backtrace won’t be able to make much sense of where you are.
  • Use backtrace full to show the call stack and print the value of local variables.
  • To find what address caused a segmentation fault: p $_siginfo._sifields._sigfault.si_addr. If it shows (void *) 0x0 (or a small number), then you have a NULL pointer dereference.
  • Use find 0x7ffffffde000, 0x7ffffffff000-1, 'a', 'a', 'a', 'a' to search for the string that starts with the pattern aaaa—assuming the stack range given by vmmap is 0x7ffffffde000 to 0x7ffffffff000. Note that the subtraction of 1 from the end address is necessary to avoid the error “Unable to access 7169 bytes of target memory at 0x7fffffffd400, halting search.”

Pagination:

  • set pagination on
  • set pagination off
  • show pagination

Creating Hooks

Create a hook to print some information on every break point:

define hook-stop
info registers
x/24wx $esp
x/2i $eip
end

This hook will print all of the register values, the stack, and the next two instructions.

Viewing struct values nicely:

set $foo = (struct bar *) 0x804a008

#get the address
print $foo

#get a value of the struct's members
print *$foo

#get the value of an attribute
print $foo->name

#examine the memory at the address stored in the attribute
x $foo->name