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);
}
else
{
printf("Wrong password! No Flag for you!\n");
}
free(x);
}
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:
start
break *($base + 0x1309)
commands
printf "The value that is being swapped is: %s\n", $rdx
c
end
break *($base + 0x1319)
commands
printf "Resulting value is: %s\n", $rsi
x/8bx $rsi
c
end
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
Back