Scripting with GDB

Created On 26. Feb 2022

Updated: 2022-02-26 20:23:03.135815000 +0000

Created By: acidghost

GDB is the default debugger that comes with most Linux distributions. When it is needed to analyze a program, we might already know beforehand what to look into. In such case, automating the things that need to be seen can save up a lot of time and it is very easy! Let's check this crackme where user is asked for a password:

#include <sys/sendfile.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char **argv[])
		char *expected_result = "password";
		char provided_password[20];
		int i; 

		printf("Type the password to get the flag:\n");
		scanf("%19s", provided_password);

		size_t l = strlen(provided_password);
  		char* x = (char*)malloc((l + 1) * sizeof(char));
  		x[l] = '\0';
  		for(i = 0; i < l; i++) {
    	        x[i] = provided_password[l - 1 - i];

		if (strcmp(expected_result, x) == 0)
		sendfile(1, open("./flag", O_RDONLY), 0, 100);
		printf("Wrong password! No Flag for you!\n");

Compile with gcc -o crackme crackme.c and run. We have a sort function that swaps the input and password is the expected value after it runs. Let's firstly check the function graph in the free version of IDA:

This is the important part that interests us. After the input is scanned, it is stored in rbp at an offset of 30. I learned that this version of IDA can mess up the offsets sometimes and I would suggest always to use a different tool to confirm this. Further down can be seen the sort function that runs multiple times until the count in rax is set. The loop function on the right will run each time to swap a byte - therefore it will run as many times as is the byte length of the input. This can be also observed from the loop function in the source code. Every time a byte is swapped, it will be dereferenced in rdx. Finally, after the loop runs, it will be compared against the expected result. This will run through strcmp function where values from rsi - the new value, and rdi - the stored expected result, will be compared. In such cases, it is easy to find out what is happening by breaking at the loop, before the iteration begins and at strcmp. Let's take the offsets and script this in GDB:


break *($base + 0x1309)
printf "The value that is being swapped is: %s\n", $rdx

break *($base + 0x1319)
printf "Resulting value is: %s\n", $rsi
x/8bx $rsi

Save as crackme.gdb and run the file gdb crackme -x crackme.gdb. I suggest having at least these lines in GDB config in ~/.gdbinit, which also sets up the $base variable to GDB's default:

set history save on
set disassembly-flavor intel
set $base = 0x0000555555554000

I already typed in the reversed string and got the flag on my system:

GDB's scripting language consists of its own instructions that can be combined with C syntax. With commands the analysis can be automated and as in the example above with c (continue), the debugger will execute all the instructions on its own, without the need for the user to interact with it and step manually. This is one of its few capabilities that makes it a powerful day-to-day debugger.

Section: Reverse Engineering