gdb-gef

So throughout this project, we will be using a lot of different tools. The purpose of this module is to show you some of the basics of three of those tools. We will start with gdb-gef.

First off, gdb is a debugger (specifically the gnu debugger). Gef is an a gdb wrapper, designed to give us some extended features (https://github.com/hugsy/gef). To install it, you can find the instructions on the github page. it's super simple.

A debugger is software that allows us to perform various types of analysis of a process as it's running, and alter it in a variety of different ways.

Now you can tell if you have it installed by just looking at gdb. For instance this is the look of gdb if you have gef installed:

$ gdb
GNU gdb (Ubuntu 8.2.91.20190405-0ubuntu3) 8.2.91.20190405-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
GEF for linux ready, type `gef' to start, `gef config' to configure
75 commands loaded for GDB 8.2.91.20190405-git using Python engine 3.7
[*] 5 commands could not be loaded, run `gef missing` to know why.
gef➤  

If you don't have it installed this is what vanilla gdb looks like:

$    gdb
GNU gdb (Ubuntu 8.2.91.20190405-0ubuntu3) 8.2.91.20190405-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb)

Running

To run the binary titan in gdb:

gdb ./titan
GNU gdb (Ubuntu 8.2.91.20190405-0ubuntu3) 8.2.91.20190405-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
75 commands loaded for GDB 8.2.91.20190405-git using Python engine 3.7
[*] 5 commands could not be loaded, run `gef missing` to know why.
Reading symbols from ./titan...
(No debugging symbols found in ./titan)
gef➤  r
Starting program: /tmp/titan
hi

If you are running a process in gdb, and wish to drop to the debugger console, you can do so by pressing Cotrol + C:

gef➤  r
Starting program: /tmp/titan
hi
^C
Program received signal SIGINT, Interrupt.
0x00007ffff7ed6f81 in __GI___libc_read (fd=0x0, buf=0x555555559670, nbytes=0x400) at ../sysdeps/unix/sysv/linux/read.c:26
26    ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0xfffffffffffffe00
$rbx   : 0x00007ffff7faea00  →  0x00000000fbad2288
$rcx   : 0x00007ffff7ed6f81  →  0x5777fffff0003d48 ("H="?)
$rdx   : 0x400             
$rsp   : 0x00007fffffffdef8  →  0x00007ffff7e59e50  →  <_IO_file_underflow+336> test rax, rax
$rbp   : 0xd68             
$rsi   : 0x0000555555559670  →  0x0000000000000000
$rdi   : 0x0               
$rip   : 0x00007ffff7ed6f81  →  0x5777fffff0003d48 ("H="?)
$r8    : 0x00007ffff7fb1580  →  0x0000000000000000
$r9    : 0x00007ffff7fb6500  →  0x00007ffff7fb6500  →  [loop detected]
$r10   : 0x00007ffff7faeca0  →  0x0000555555559a70  →  0x0000000000000000
$r11   : 0x246             
$r12   : 0x00007ffff7faf960  →  0x0000000000000000
$r13   : 0x00007ffff7fb0560  →  0x0000000000000000
$r14   : 0x00007ffff7faf848  →  0x00007ffff7faf760  →  0x00000000fbad2a84
$r15   : 0x00007ffff7fb0560  →  0x0000000000000000
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdef8│+0x0000: 0x00007ffff7e59e50  →  <_IO_file_underflow+336> test rax, rax     ← $rsp
0x00007fffffffdf00│+0x0008: 0x00007ffff7faf960  →  0x0000000000000000
0x00007fffffffdf08│+0x0010: 0x00007ffff7faea00  →  0x00000000fbad2288
0x00007fffffffdf10│+0x0018: 0x00007ffff7fb0560  →  0x0000000000000000
0x00007fffffffdf18│+0x0020: 0x000000000000000a
0x00007fffffffdf20│+0x0028: 0x0000000000000000
0x00007fffffffdf28│+0x0030: 0x0000000000000008
0x00007fffffffdf30│+0x0038: 0x00007ffff7faea00  →  0x00000000fbad2288
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0x7ffff7ed6f75 <read+5>         or     eax, 0x85008b00
   0x7ffff7ed6f7a <read+10>        shl    BYTE PTR [rbp+0x13], 0x31
   0x7ffff7ed6f7e <read+14>        ror    BYTE PTR [rdi], 0x5
 → 0x7ffff7ed6f81 <read+17>        cmp    rax, 0xfffffffffffff000
   0x7ffff7ed6f87 <read+23>        ja     0x7ffff7ed6fe0 <__GI___libc_read+112>
   0x7ffff7ed6f89 <read+25>        ret    
   0x7ffff7ed6f8a <read+26>        nop    WORD PTR [rax+rax*1+0x0]
   0x7ffff7ed6f90 <read+32>        push   r12
   0x7ffff7ed6f92 <read+34>        mov    r12, rdx
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "titan", stopped, reason: SIGINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7ed6f81 → __GI___libc_read(fd=0x0, buf=0x555555559670, nbytes=0x400)
[#1] 0x7ffff7e59e50 → _IO_new_file_underflow(fp=0x7ffff7faea00 <_IO_2_1_stdin_>)
[#2] 0x7ffff7e5b182 → __GI__IO_default_uflow(fp=0x7ffff7faea00 <_IO_2_1_stdin_>)
[#3] 0x7ffff7e4d1fa → __GI__IO_getline_info(fp=0x7ffff7faea00 <_IO_2_1_stdin_>, buf=0x7fffffffdfee "", n=0x8, delim=0xa, extract_delim=0x1, eof=0x0)
[#4] 0x7ffff7e4d2e8 → __GI__IO_getline(fp=0x7ffff7faea00 <_IO_2_1_stdin_>, buf=0x7fffffffdfee "", n=<optimized out>, delim=0xa, extract_delim=0x1)
[#5] 0x7ffff7e4c1ab → _IO_fgets(buf=0x7fffffffdfee "", n=<optimized out>, fp=0x7ffff7faea00 <_IO_2_1_stdin_>)
[#6] 0x555555555190 → main()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  

Breakpoints

Let's take a look at the main function:

gef➤  disas main
Dump of assembler code for function main:
   0x0000000000401142 <+0>:    push   rbp
   0x0000000000401143 <+1>:    mov    rbp,rsp
   0x0000000000401146 <+4>:    sub    rsp,0x20
   0x000000000040114a <+8>:    mov    rax,QWORD PTR fs:0x28
   0x0000000000401153 <+17>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000401157 <+21>:    xor    eax,eax
   0x0000000000401159 <+23>:    lea    rdi,[rip+0xea4]        # 0x402004
   0x0000000000401160 <+30>:    call   0x401030 <puts@plt>
   0x0000000000401165 <+35>:    mov    rdx,QWORD PTR [rip+0x2ed4]        # 0x404040 <stdin@@GLIBC_2.2.5>
   0x000000000040116c <+42>:    lea    rax,[rbp-0x12]
   0x0000000000401170 <+46>:    mov    esi,0x9
   0x0000000000401175 <+51>:    mov    rdi,rax
   0x0000000000401178 <+54>:    call   0x401050 <fgets@plt>
   0x000000000040117d <+59>:    nop
   0x000000000040117e <+60>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000401182 <+64>:    xor    rax,QWORD PTR fs:0x28
   0x000000000040118b <+73>:    je     0x401192 <main+80>
   0x000000000040118d <+75>:    call   0x401040 <__stack_chk_fail@plt>
   0x0000000000401192 <+80>:    leave  
   0x0000000000401193 <+81>:    ret    
End of assembler dump.

Let's say we wanted to break on the call to puts. We can do this by setting a breakpoint for that instruction.

Like this:

gef➤  b *main+30
Breakpoint 1 at 0x401160

Or like this:

gef➤  b *0x401160
Note: breakpoint 1 also set at pc 0x401160.
Breakpoint 2 at 0x401160

When we run the binary and it tries to execute that instruction, the process will pause and drop us into the debugger console:

gef➤  r
Starting program: /tmp/titan

Breakpoint 1, 0x0000000000401160 in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0               
$rbx   : 0x0               
$rcx   : 0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rdx   : 0x00007fffffffe0f8  →  0x00007fffffffe412  →  "SHELL=/bin/bash"
$rsp   : 0x00007fffffffdfe0  →  0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rbp   : 0x00007fffffffe000  →  0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rsi   : 0x00007fffffffe0e8  →  0x00007fffffffe407  →  "/tmp/titan"
$rdi   : 0x0000000000402004  →  0x3b031b0100006968 ("hi"?)
$rip   : 0x0000000000401160  →  <main+30> call 0x401030 <puts@plt>
$r8    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r9    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r10   : 0x1               
$r11   : 0x206             
$r12   : 0x0000000000401060  →  <_start+0> xor ebp, ebp
$r13   : 0x00007fffffffe0e0  →  0x0000000000000001
$r14   : 0x0               
$r15   : 0x0               
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdfe0│+0x0000: 0x00000000004011a0  →  <__libc_csu_init+0> push r15     ← $rsp
0x00007fffffffdfe8│+0x0008: 0x0000000000401060  →  <_start+0> xor ebp, ebp
0x00007fffffffdff0│+0x0010: 0x00007fffffffe0e0  →  0x0000000000000001
0x00007fffffffdff8│+0x0018: 0x42586df821034f00
0x00007fffffffe000│+0x0020: 0x00000000004011a0  →  <__libc_csu_init+0> push r15     ← $rbp
0x00007fffffffe008│+0x0028: 0x00007ffff7df0b6b  →  <__libc_start_main+235> mov edi, eax
0x00007fffffffe010│+0x0030: 0x00007ffff7fab4d8  →  0x00007ffff7df0450  →  <init_cacheinfo+0> push r15
0x00007fffffffe018│+0x0038: 0x00007fffffffe0e8  →  0x00007fffffffe407  →  "/tmp/titan"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x401153 <main+17>        mov    QWORD PTR [rbp-0x8], rax
     0x401157 <main+21>        xor    eax, eax
     0x401159 <main+23>        lea    rdi, [rip+0xea4]        # 0x402004
 →   0x401160 <main+30>        call   0x401030 <puts@plt>
   ↳    0x401030 <puts@plt+0>     jmp    QWORD PTR [rip+0x2fe2]        # 0x404018 <puts@got.plt>
        0x401036 <puts@plt+6>     push   0x0
        0x40103b <puts@plt+11>    jmp    0x401020
        0x401040 <__stack_chk_fail@plt+0> jmp    QWORD PTR [rip+0x2fda]        # 0x404020 <__stack_chk_fail@got.plt>
        0x401046 <__stack_chk_fail@plt+6> push   0x1
        0x40104b <__stack_chk_fail@plt+11> jmp    0x401020
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
puts@plt (
   $rdi = 0x0000000000402004 → 0x3b031b0100006968 ("hi"?),
   $rsi = 0x00007fffffffe0e8 → 0x00007fffffffe407 → "/tmp/titan",
   $rdx = 0x00007fffffffe0f8 → 0x00007fffffffe412 → "SHELL=/bin/bash"
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "titan", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401160 → main()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  

In the debugger console is where we can actually use the debugger to provide various types of analysis, and change things about the binary. For now let's keep looking at breakpoints. To show all breakpoints:

gef➤  info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000401160 <main+30>
    breakpoint already hit 1 time
2       breakpoint     keep y   0x0000000000401170 <main+46>

To delete a breakpoint Num 2:

gef➤  delete 2

We can also set breakpoints for functions like puts:

gef➤  b *puts
Breakpoint 1 at 0x401030
gef➤  r
Starting program: /tmp/titan

Breakpoint 1, __GI__IO_puts (str=0x402004 "hi") at ioputs.c:35
35    ioputs.c: No such file or directory.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0               
$rbx   : 0x0               
$rcx   : 0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rdx   : 0x00007fffffffe0f8  →  0x00007fffffffe412  →  "SHELL=/bin/bash"
$rsp   : 0x00007fffffffdfd8  →  0x0000000000401165  →  <main+35> mov rdx, QWORD PTR [rip+0x2ed4]        # 0x404040 <stdin@@GLIBC_2.2.5>
$rbp   : 0x00007fffffffe000  →  0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rsi   : 0x00007fffffffe0e8  →  0x00007fffffffe407  →  "/tmp/titan"
$rdi   : 0x0000000000402004  →  0x3b031b0100006968 ("hi"?)
$rip   : 0x00007ffff7e4dcc0  →  <puts+0> push r14
$r8    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r9    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r10   : 0x3               
$r11   : 0x00007ffff7e4dcc0  →  <puts+0> push r14
$r12   : 0x0000000000401060  →  <_start+0> xor ebp, ebp
$r13   : 0x00007fffffffe0e0  →  0x0000000000000001
$r14   : 0x0               
$r15   : 0x0               
$eflags: [zero carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdfd8│+0x0000: 0x0000000000401165  →  <main+35> mov rdx, QWORD PTR [rip+0x2ed4]        # 0x404040 <stdin@@GLIBC_2.2.5>     ← $rsp
0x00007fffffffdfe0│+0x0008: 0x00000000004011a0  →  <__libc_csu_init+0> push r15
0x00007fffffffdfe8│+0x0010: 0x0000000000401060  →  <_start+0> xor ebp, ebp
0x00007fffffffdff0│+0x0018: 0x00007fffffffe0e0  →  0x0000000000000001
0x00007fffffffdff8│+0x0020: 0xf2a5b1c2e2ab0300
0x00007fffffffe000│+0x0028: 0x00000000004011a0  →  <__libc_csu_init+0> push r15     ← $rbp
0x00007fffffffe008│+0x0030: 0x00007ffff7df0b6b  →  <__libc_start_main+235> mov edi, eax
0x00007fffffffe010│+0x0038: 0x00007ffff7fab4d8  →  0x00007ffff7df0450  →  <init_cacheinfo+0> push r15
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0x7ffff7e4dcb1 <popen+145>      ret    
   0x7ffff7e4dcb2                  nop    WORD PTR cs:[rax+rax*1+0x0]
   0x7ffff7e4dcbc                  nop    DWORD PTR [rax+0x0]
 → 0x7ffff7e4dcc0 <puts+0>         push   r14
   0x7ffff7e4dcc2 <puts+2>         push   r13
   0x7ffff7e4dcc4 <puts+4>         mov    r13, rdi
   0x7ffff7e4dcc7 <puts+7>         push   r12
   0x7ffff7e4dcc9 <puts+9>         push   rbp
   0x7ffff7e4dcca <puts+10>        push   rbx
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "titan", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7e4dcc0 → __GI__IO_puts(str=0x402004 "hi")
[#1] 0x401165 → main()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  

Viewing Things

So one thing that gdb is really useful for is viewing the values of different things. Once we are dropped into a debugger while the process is viewing, let's view the contents of the rdi register:

Breakpoint 1, 0x0000000000401160 in main ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0               
$rbx   : 0x0               
$rcx   : 0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rdx   : 0x00007fffffffe0f8  →  0x00007fffffffe412  →  "SHELL=/bin/bash"
$rsp   : 0x00007fffffffdfe0  →  0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rbp   : 0x00007fffffffe000  →  0x00000000004011a0  →  <__libc_csu_init+0> push r15
$rsi   : 0x00007fffffffe0e8  →  0x00007fffffffe407  →  "/tmp/titan"
$rdi   : 0x0000000000402004  →  0x3b031b0100006968 ("hi"?)
$rip   : 0x0000000000401160  →  <main+30> call 0x401030 <puts@plt>
$r8    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r9    : 0x00007ffff7fb0a40  →  0x0000000000000000
$r10   : 0x1               
$r11   : 0x206             
$r12   : 0x0000000000401060  →  <_start+0> xor ebp, ebp
$r13   : 0x00007fffffffe0e0  →  0x0000000000000001
$r14   : 0x0               
$r15   : 0x0               
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdfe0│+0x0000: 0x00000000004011a0  →  <__libc_csu_init+0> push r15     ← $rsp
0x00007fffffffdfe8│+0x0008: 0x0000000000401060  →  <_start+0> xor ebp, ebp
0x00007fffffffdff0│+0x0010: 0x00007fffffffe0e0  →  0x0000000000000001
0x00007fffffffdff8│+0x0018: 0x0a17c82ca27b0d00
0x00007fffffffe000│+0x0020: 0x00000000004011a0  →  <__libc_csu_init+0> push r15     ← $rbp
0x00007fffffffe008│+0x0028: 0x00007ffff7df0b6b  →  <__libc_start_main+235> mov edi, eax
0x00007fffffffe010│+0x0030: 0x00007ffff7fab4d8  →  0x00007ffff7df0450  →  <init_cacheinfo+0> push r15
0x00007fffffffe018│+0x0038: 0x00007fffffffe0e8  →  0x00007fffffffe407  →  "/tmp/titan"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x401153 <main+17>        mov    QWORD PTR [rbp-0x8], rax
     0x401157 <main+21>        xor    eax, eax
     0x401159 <main+23>        lea    rdi, [rip+0xea4]        # 0x402004
 →   0x401160 <main+30>        call   0x401030 <puts@plt>
   ↳    0x401030 <puts@plt+0>     jmp    QWORD PTR [rip+0x2fe2]        # 0x404018 <puts@got.plt>
        0x401036 <puts@plt+6>     push   0x0
        0x40103b <puts@plt+11>    jmp    0x401020
        0x401040 <__stack_chk_fail@plt+0> jmp    QWORD PTR [rip+0x2fda]        # 0x404020 <__stack_chk_fail@got.plt>
        0x401046 <__stack_chk_fail@plt+6> push   0x1
        0x40104b <__stack_chk_fail@plt+11> jmp    0x401020
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
puts@plt (
   $rdi = 0x0000000000402004 → 0x3b031b0100006968 ("hi"?),
   $rsi = 0x00007fffffffe0e8 → 0x00007fffffffe407 → "/tmp/titan",
   $rdx = 0x00007fffffffe0f8 → 0x00007fffffffe412 → "SHELL=/bin/bash"
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "titan", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401160 → main()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  p $rdi
$1 = 0x402004

So we can see that the register rdi holds the value 0x402004, which is a pointer. Let's see what it points to:

gef➤  x/g 0x402004
0x402004:    0x3b031b0100006968
gef➤  x/s 0x402004
0x402004:    "hi"

So we can see that it points to the string hi, which will be printed by puts (since puts takes a single argument which is a char pointer). One thing in gdb when you examine things with x, you can specify what you want to examine it as. Possible things include as a string x/s, as a qword x/g, or as a dword x/w.

let's view the contents of all of the registers:

gef➤  info registers
rax            0x0                 0x0
rbx            0x0                 0x0
rcx            0x4011a0            0x4011a0
rdx            0x7fffffffe0f8      0x7fffffffe0f8
rsi            0x7fffffffe0e8      0x7fffffffe0e8
rdi            0x402004            0x402004
rbp            0x7fffffffe000      0x7fffffffe000
rsp            0x7fffffffdfe0      0x7fffffffdfe0
r8             0x7ffff7fb0a40      0x7ffff7fb0a40
r9             0x7ffff7fb0a40      0x7ffff7fb0a40
r10            0x1                 0x1
r11            0x206               0x206
r12            0x401060            0x401060
r13            0x7fffffffe0e0      0x7fffffffe0e0
r14            0x0                 0x0
r15            0x0                 0x0
rip            0x401160            0x401160 <main+30>
eflags         0x246               [ PF ZF IF ]
cs             0x33                0x33
ss             0x2b                0x2b
ds             0x0                 0x0
es             0x0                 0x0
fs             0x0                 0x0
gs             0x0                 0x0

Now let's view the stack frame:

gef➤  info frame
Stack level 0, frame at 0x7fffffffe010:
 rip = 0x401160 in main; saved rip = 0x7ffff7df0b6b
 Arglist at 0x7fffffffe000, args:
 Locals at 0x7fffffffe000, Previous frame's sp is 0x7fffffffe010
 Saved registers:
  rbp at 0x7fffffffe000, rip at 0x7fffffffe008

Now let's view the disassembly for the main function:

gef➤  disas main
Dump of assembler code for function main:
   0x0000000000401142 <+0>:    push   rbp
   0x0000000000401143 <+1>:    mov    rbp,rsp
   0x0000000000401146 <+4>:    sub    rsp,0x20
   0x000000000040114a <+8>:    mov    rax,QWORD PTR fs:0x28
   0x0000000000401153 <+17>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000401157 <+21>:    xor    eax,eax
   0x0000000000401159 <+23>:    lea    rdi,[rip+0xea4]        # 0x402004
=> 0x0000000000401160 <+30>:    call   0x401030 <puts@plt>
   0x0000000000401165 <+35>:    mov    rdx,QWORD PTR [rip+0x2ed4]        # 0x404040 <stdin@@GLIBC_2.2.5>
   0x000000000040116c <+42>:    lea    rax,[rbp-0x12]
   0x0000000000401170 <+46>:    mov    esi,0x9
   0x0000000000401175 <+51>:    mov    rdi,rax
   0x0000000000401178 <+54>:    call   0x401050 <fgets@plt>
   0x000000000040117d <+59>:    nop
   0x000000000040117e <+60>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000401182 <+64>:    xor    rax,QWORD PTR fs:0x28
   0x000000000040118b <+73>:    je     0x401192 <main+80>
   0x000000000040118d <+75>:    call   0x401040 <__stack_chk_fail@plt>
   0x0000000000401192 <+80>:    leave  
   0x0000000000401193 <+81>:    ret    
End of assembler dump.

Changing Values

Let's say we wanted to change the contents of the rdi register:

gef➤  p $rdi
$2 = 0x402004
gef➤  set $rdi = 0x0
gef➤  p $rdi
$3 = 0x0

Now let's say we wanted to change the value stored at the memory address 0x402004 to 0xfacade:

gef➤  x/g 0x402004
0x402004:    0x3b031b0100006968
gef➤  set *0x402004 = 0xfacade
gef➤  x/g 0x402004
0x402004:    0x3b031b0100facade

Let's say we wanted to jump directly to an instruction like 0x40117d, and skip all instructions in between:

gef➤  j *0x40117d
Continuing at 0x40117d.