GDB Guides Series:

  1. GDB Guide Part 1 - Basics
  2. GDB Guide Part 2 - Breakpoints & Linux Calling Conventions
  3. GDB Guide Part 3 - Process Maps
  4. GDB Guide Part 4 - Examining Memory
  5. GDB Guide Part 5 - Stepping
  6. GDB Guide Part 6 - Automation
  7. GDB Guide Part 7 - Custom Commands
  8. GDB Guide Part 8 - Invoking Function Calls

1. Introduction

This part of the guide will demonstrate to you the differences between stepping in, over and out. In most cases while doing cyber security research, we will not have access to symbols and source code. Thus, the examples I provide will only be for stepping through instructions and not source lines.

2. Example Program

For this part of the tutorial, either compile stepping-exercise.c or download the static binary stepping-exercise to follow along.

3. Stepping In

To step through one instruction at a time, the command to use will be stepi / si. For more information, see the help usage of stepi / si.

(gdb) help si

stepi, si
Step one instruction exactly.
Usage: stepi [N]
Argument N means step N times (or till program stops for another reason).
Step-Into Usage

The following example shows the relevant commands for stepping into 5 instructions after we hit the breakpoint at the start of fib_num():

(gdb) set pag off
(gdb) set disassembly-flavor intel

(gdb) b fib_num
Breakpoint 1 at 0x4018bd

# Run the program and enter any number
(gdb) r
Enter Fibonacci Sequence: 10

Breakpoint 1, 0x00000000004018bd in fib_num ()

# Inspect 10 instructions from the current instruction
(gdb) x/10i $pc
=> 0x4018bd <fib_num+8>:        mov    DWORD PTR [rbp-0x14],edi
   0x4018c0 <fib_num+11>:       mov    DWORD PTR [rbp-0x10],0x0
   0x4018c7 <fib_num+18>:       mov    DWORD PTR [rbp-0xc],0x1
   0x4018ce <fib_num+25>:       mov    DWORD PTR [rbp-0x8],0x0
   0x4018d5 <fib_num+32>:       cmp    DWORD PTR [rbp-0x14],0x0
   0x4018d9 <fib_num+36>:       jne    0x4018e0 <fib_num+43>
   0x4018db <fib_num+38>:       mov    eax,DWORD PTR [rbp-0x10]
   0x4018de <fib_num+41>:       jmp    0x40191a <fib_num+101>
   0x4018e0 <fib_num+43>:       cmp    DWORD PTR [rbp-0x14],0x1
   0x4018e4 <fib_num+47>:       jne    0x4018eb <fib_num+54>

# Step into 5 instructions
(gdb) si 5
0x00000000004018d9 in fib_num ()

# Inspect the current instruction
(gdb) x/i $pc
=> 0x4018d9 <fib_num+36>:       jne    0x4018e0 <fib_num+43>
Example Usage of Stepping Into

4. Stepping Over

Stepping over is slightly different from stepping as it treats a function/subroutine call as one instruction. To step over instructions, the command to use is nexti / ni. To see more information on nexti / ni, refer to the help usage.

(gdb) help ni

nexti, ni
Step one instruction, but proceed through subroutine calls.
Usage: nexti [N]
Argument N means step N times (or till program stops for another reason).
Step-Over Usage

The following example shows the relevant commands for stepping over the fib_num call after we hit the breakpoint at the function call to fib_num():

(gdb) set pag off
(gdb) set disassembly-flavor intel

# Diassemble main to find the offset of the call to fib_num()
(gdb) disass main
Dump of assembler code for function main:
   ...
   0x0000000000401959 <+61>:    mov    rdi,rax
   0x000000000040195c <+64>:    mov    eax,0x0
   0x0000000000401961 <+69>:    call   0x404e00 <__isoc99_scanf>
   0x0000000000401966 <+74>:    mov    eax,DWORD PTR [rbp-0xc]
   0x0000000000401969 <+77>:    mov    edi,eax
   0x000000000040196b <+79>:    call   0x4018b5 <fib_num>
   0x0000000000401970 <+84>:    mov    esi,eax
   ...
End of assembler dump.

# Set a breakpoint at the call instruction
(gdb) b *(main + 79)
Breakpoint 1 at 0x40196b

# Run the program and enter any number
(gdb) r
Enter Fibonacci Sequence: 10

Breakpoint 1, 0x000000000040196b in main ()

# Inspect 5 instructions from the current instruction
(gdb) x/5i $pc
=> 0x40196b <main+79>:  call   0x4018b5 <fib_num>
   0x401970 <main+84>:  mov    esi,eax
   0x401972 <main+86>:  lea    rax,[rip+0x9b6d1]        # 0x49d04a
   0x401979 <main+93>:  mov    rdi,rax
   0x40197c <main+96>:  mov    eax,0x0

# Step over once
(gdb) ni
0x0000000000401970 in main ()

# Current instruction is after fib_num() call.
(gdb) x/i $pc
=> 0x401970 <main+84>:  mov    esi,eax
Example Usage of Stepping Over

5. Stepping Out

The last method of stepping is to execute everything in the current function and return to the caller. To do so, use the finish command. To see more information on finish, refer to the help usage.

(gdb) help finish

finish, fin
Execute until selected stack frame returns.
Usage: finish
Upon return, the value returned is printed and put in the value history.
Step-Out Usage

The following example shows the relevant commands for stepping out of the fib_num() function and getting its return value. The

(gdb) set pag off
(gdb) set disassembly-flavor intel
(gdb) b fib_num
Breakpoint 1 at 0x4018bd
(gdb) r
Starting program: /home/gerald/Desktop/Repositories/hugo-blog/staging.mathscantor.github.io/static/posts/gdb-guides/gdb-guide-part5-stepping/resources/stepping-exercise 
Enter Fibonacci Sequence: 10

Breakpoint 1, 0x00000000004018bd in fib_num ()
(gdb) finish
Run till exit from #0  0x00000000004018bd in fib_num ()
0x0000000000401970 in main ()

# See current instruction
(gdb) x/i $pc
=> 0x401970 <main+84>:  mov    esi,eax

# Get the return value of fib_num()
(gdb) p $rax
$1 = 55
Example Usage of Step Out

6. Conclusion

Now that you have made it this far, you have mastered the basics of GDB! In the next few guides, I will be going through more advanced techniques to achieve greater efficiency in dynamic analysis through automation.

Stay safe and healthy folks!

7. Resources

  1. stepping-exercise.c
  2. stepping-exercise

GDB Guides Series:

  1. GDB Guide Part 1 - Basics
  2. GDB Guide Part 2 - Breakpoints & Linux Calling Conventions
  3. GDB Guide Part 3 - Process Maps
  4. GDB Guide Part 4 - Examining Memory
  5. GDB Guide Part 5 - Stepping
  6. GDB Guide Part 6 - Automation
  7. GDB Guide Part 7 - Custom Commands
  8. GDB Guide Part 8 - Invoking Function Calls