Exploit Education Phoenix : Format One
Table of Contents
Exploit Education Phoenix - This article is part of a series.
Overview of the challenge #
The aim of the Phoenix challenges is to analyse the source code of an executable in order to find and exploit a vulnerability. This second series of challenges concerns the format string vulnerabilities.
The first thing to do is to analyse the executable’s source code. Looking for a vulnerability to exploit.
int main(int argc, char **argv) {
struct {
char dest[32];
volatile int changeme;
} locals;
char buffer[16];
if (fgets(buffer, sizeof(buffer) - 1, stdin) == NULL) {
errx(1, "Unable to get buffer");
}
buffer[15] = 0;
locals.changeme = 0;
sprintf(locals.dest, buffer);
if (locals.changeme != 0x45764f6c) {
printf("Uh oh, 'changeme' is not the magic value, it is 0x%08x\n",
locals.changeme);
} else {
puts("Well done, the 'changeme' variable has been changed correctly!");
}
exit(0);
}
This challenge is very similar to the previous one, but with a little extra difficulty.
The first thing you notice is the structure containing a 32-character buffer and the changeme
variable. The aim of this challenge is to modify the value of the changeme
variable and set the value at 0x45764f6c
. There is also a second buffer of 16 characters.
The second thing is to use the sprintf
function. When we look at the documentation for the function with the command: man sprintf
. The documentation in the BUGS
section explains that using the sprintf
function can be dangerous, especially if the format is given by the user. In other words, the function is used in this way: sprintf(foo);
instead of sprintf(format, foo);
with the format is given by the programmer.
Furthermore, it is not possible to know what the size of the final character string will be, as the use of %
characters will allow an attacker to change the size of the final character string.
The challenge is to exploit a buffer overflow and modify the changeme
variable, while being restricted by a 15-character buffer for user input. This prevents us from using a stack buffer overflow and modifying the variable directly.
Exploiting the vulnerability #
To do this, we need to exploit a buffer overflow vulnerability, we need to instrument a string so that the sprintf
function generates a long string of characters.
$ python -c "print '%32x'+'\x6C\x4F\x76\x45'" | ./format-one
Using the %32x
parameter tells the sprintf
function to represent a variable in hexadecimal. However, we also specify the size of the hexadecimal representation, in this case 32
. At the output of the sprintf
function, the string will be 32
characters long, allowing us to change the value of the changeme
variable by exploiting a buffer overflow. The interesting thing about this method is that we can bypass the buffer size by using the sprintf
function parameters. Finally, when we reach the correct padding, we overwrite the value of the changeme
variable with the correct ASCII code.
Finally, we can see that the changeme
variable has been modified with the right value, so we can complete the challenge.