A source level debugger based on `ptrace` for *NIX systems and developed by the GNU project.
GDB is primarily designed for debugging software during development with source available. However, it can also be used to debug without source code and debug symbols available.
It is available on most platforms and included by default in the tool chains of most Unix like operating systems. There are text interfaces as well as graphical ones such as Eclipse integration, the venerable DDD or KDBG.
You can find the comprehensive documentation here.
The default interfaces are terminal based.
But you can also use the following GDB commands on the
(gdb) prompt to switch the layouts on the fly (use
help layout to get more information):
layout src(only useful with source and symbols)
There is the default
layout src which can be invoked using the
-tui command line switch.
Default when not using any kind of command line switches.
layout asm together with
This is by far the most useful
layout for reverse engineering, during which debug symbols are usually unavailable. Behold:
Beautiful isn't it? You can see the current values of registers, see the assembly at your current program counter, see where the break point was set and so on. And if you prefer the Intel assembly syntax like I do you issue a:
set disassembly-flavor intel
and it looks like this:
Debugging without debug symbols
Normally GDB will attempt to load the debug symbols from the executable itself or in the search paths it was told about. If it doesn't find any symbols or you are reversing/analyzing a target executable without symbols, you can use the following line:
to enable an automatic
display for the program counter (
$pc). So you see what you are going to execute. Starting with GDB 7 you can also use the following setting to achieve virtually the same:
set disassemble-next-line on
If you merely want to see the current instruction use:
which is short for
If you wanted to make sure you don't get surprised by something running before you get control in GDB, you should use:
which will give you an output similar to (shortened for brevity):
(gdb) info file Symbols from "/home/username/source/hello". Local exec file: `/home/username/source/hello', file type elf64-x86-64. Entry point: 0x400410 0x0000000000400238 - 0x0000000000400254 is .interp 0x0000000000400254 - 0x0000000000400274 is .note.ABI-tag 0x0000000000400274 - 0x0000000000400298 is .note.gnu.build-id 0x0000000000400298 - 0x00000000004002b4 is .gnu.hash 0x00000000004002b8 - 0x0000000000400318 is .dynsym 0x0000000000400318 - 0x0000000000400355 is .dynstr 0x0000000000400356 - 0x000000000040035e is .gnu.version 0x0000000000400360 - 0x0000000000400380 is .gnu.version_r 0x0000000000400380 - 0x0000000000400398 is .rela.dyn 0x0000000000400398 - 0x00000000004003c8 is .rela.plt 0x00000000004003c8 - 0x00000000004003e0 is .init ...
and you are interested to set
breakpoints at the lines for the
Entry point: and the one with
.init (a runtime function running before the entry point):
(gdb) b *0x400410 Breakpoint 1 at 0x400410 (gdb) b *0x00000000004003c8 Breakpoint 2 at 0x4003c8
Notice how we use the asterisk (
*) to specify an address for the
break point command.
Refining what assembly we see
(gdb) x/5i $pc => 0x400410 <_start>: xor %ebp,%ebp 0x400412 <_start+2>: mov %rdx,%r9 0x400415 <_start+5>: pop %rsi 0x400416 <_start+6>: mov %rsp,%rdx 0x400419 <_start+9>: and $0xfffffffffffffff0,%rsp
display allow us to specify the number of instructions we want to see like this to show 5 instructions:
we can also tell it to show starting from before the current program counter:
last but not least we can change from AT&T syntax to Intel syntax:
set disassembly-flavor intel
(gdb) x/10i $pc-3 0x40041a <_start+10>: and esp,0xfffffff0 => 0x40041d <_start+13>: push rax 0x40041e <_start+14>: push rsp 0x40041f <_start+15>: mov r8,0x4005a0 0x400426 <_start+22>: mov rcx,0x400510 0x40042d <_start+29>: mov rdi,0x4004f4 0x400434 <_start+36>: call 0x400400 <__libc_start_main@plt> 0x400439 <_start+41>: hlt 0x40043a <_start+42>: nop 0x40043b <_start+43>: nop