GDB Guide Part 5 - Stepping
GDB Guides Series:
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).
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>
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).
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
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.
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
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!