The GNU Debugger or GDB for short is a command line tool that allows you to disassemble and understand the code execution of a program.
If you have ever used a debugger built into an IDE then you should be familiar with breakpoints, watch points and code stepping.
GDB provides this functionality and is often used to implement the debugging features of IDEs.
GDB can thus be useful for reverse engineering as it can show and dynamically change the flow of the program, showing all state changes and code executed.
In this video tutorial from LiveOverflow it gives a brief introduction on how to understand a simple license check application 1.
You can download the files used in the tutorial from LiveOverflows Github page: liveoverflow_youtube/0x05_simple_crackme_intro_assembler at master · LiveOverflow/liveoverflow_youtube · GitHub
It is a linux executable that can be run either on a linux distribution or in Docker.
You can simply execute the provided example on a linux machine like so:
./license_1 TEST-KEY-1234
It will check to see if the argument is a valid license key, in this case TEST-KEY-1234
is not a valid license key so it prints the string “WRONG!”
It is just as simple to run the example through GDB, it just has a few extra steps before execution. You can run the executable through gdb like so:
gdb license_1
Notice that it won’t start execution straight away and instead give a command line prompt for you to execute a command into.
The commands you can type into here are known as GDB commands and provide options for setting breakpoints, disassembling and much more.
As this is a program compiled from C it has a main function, you can disassemble this function with GDB like so:
disassemble main
How easy is that? You can now see a full assembly listing of the main function! This is all the code that the CPU will execute when running your executable.
Some people prefer the intel syntax for disassembled code and you can set this with the following GDB command:
set disassembly-flavor intel
To create a breakpoint it is very simple you just use the command break
along with the function name or address you want to break execution flow on. So for example:
break main
To start execution so that we can reach our breakpoint simply type the command:
run
Note that you can also pass in arguments to the program as parameters to the run command so for out example we can pass a license key to the executable like so:
run TEST-KEY-1234
Also notice that if you use run when a program is already running it asks if you want to restart it, if you are looking to just go to the next breakpoint then use the continue
command instead.
Registers are small pieces of memory that store values inside the CPU, assembly code works with registers to provide most of the logic. You can view their current values at the current breakpoint like so:
info registers
You have a few commands to step to the next instruction “ni” (next instruction) and “si” (step instruction. The difference is that ni doesn’t not step into function calls but si does.
ni ; step over function calls
si ; step into function calls
You can dynamically alter the values of registers with GDB too like so:
set $eax=0
This will set the EAX register to 0, but you can set it to any value you want.