Using GDB - GNU Debugger
When tackling bugs in C, the terminal errors can often be confusing and unhelpful. A debugger solves this by letting you look inside your binary to pinpoint the exact cause of program behavior. This process of finding and fixing bugs not only helps you resolve immediate issues but also fortifies your code against exploitation.
As someone taking a Reverse Engineering and Exploit Development course, here are some ways you to use your debugger:
The -g flag (often called the debug flag) is a compile flag for the GNU Compiler Collection (known as gcc) that maps assembly instructions to the C code in your program.c source file. Here is an example of compilation with the debug flag:
gcc -g program.c -o program
Opening GDB is as simple as running gdb ./program
Setting breakpoints allows you to specify a specific place where you may want to check variable values or whether you maintain correct program flow. Breakpoints can be set using the commands:
break program.c:10 (This specifies the breakpoint to take place at line 10 in the program.c file)
break *0x080cf2b6 (This specifies the breakpoint to take place at the memory address 0x080cf2b6)
break main (This specifies the breakpoint to take place at the beginning of the function main)
break program.c:20 if x == 5 (This specifies the breakpoint to break at line 20 if variable x is equal to 5)
Stepping through a program is the process going through each line of either C code or x86 assembly. Using breakpoints you can stop execution at different portions of your program to monitor where your errors occur. You can step through your compiled binary in two ways:
step (used when stepping through C code)
stepi (used when stepping through x86 assembly)
Checking variables can be done using the print or display command. The print command only executes once where as the display command will print anytime execution is stopped (stepping, hitting breakpoints, or continuing execution). Here are some examples:
display i (Could be used to continuously check the iteration while stepping through a loop)
print *array_ptr (Shows the value stored at the memory location pointed to by array_ptr)
Lastly another helpful command is continue. The continue command will start execution from where the program may have paused due to hitting a breakpoint