Exploit Education Phoenix : Stack Three
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 first series of challenges concerns the stack.
The first thing to do is to analyse the executable’s source code. Looking for a vulnerability to exploit.
char *gets(char *);
void complete_level() {
printf("Congratulations, you've finished " LEVELNAME " :-) Well done!\n");
exit(0);
}
int main(int argc, char **argv) {
struct {
char buffer[64];
volatile int (*fp)();
} locals;
locals.fp = NULL;
gets(locals.buffer);
if (locals.fp) {
printf("calling function pointer @ %p\n", locals.fp);
fflush(stdout);
locals.fp();
} else {
printf("function pointer remains unmodified :~( better luck next time!\n");
}
exit(0);
}
The first thing you notice is that the structure is the same as in the previous challenges, except that the changeme
variable has now been replaced by the fp
variable, which seems to mean “function pointer”. In addition, we can see that in the rest of the source code, the program tries to call the function whose address is supposed to be stored in the fp
variable. Finally, to complete the challenge we need to call the complete_level
function. This function is not called in the source code. It seems that we need to change the value of the variable so that it contains the address of the complete_level
function in order for the function to be called.
The next thing we notice is the use of the gets
function. When we look at the documentation for the function using the command: man gets
, it explains how the function works. The gets
function retrieves a string of characters from the standard input (stdin
), each character is written to a buffer until the function detects an EOF
or a line feed. Finally, when one of these characters is detected, it is replaced by a \0
to end the string.
The documentation provides us with new information: this function should no longer be used, as it is sensitive to buffer overflow attacks. The function does not know how many characters it will write to the buffer and cannot be used to limit the number of characters copied. If the number of input characters is greater than the size of the buffer, the gets
function will continue to write to the next memory location.
Now that we’ve identified the sensitive parts of the source code, all we have to do is abuse the vulnerability to succeed in the challenge.
Exploiting the vulnerability #
To succeed in this challenge, we need to exploit a buffer overflow vulnerability. This will allow us to modify the value of the fp
variable and call the complete_level
function. However, to call the complete_level
function we need to find its address, so we can use GDB
.
$ gdb stack-three
$ disass complete_level
complete_level
function in GDB
.
Now we know that the address of the complete_level
function is 0x000000000040069D
, we can create a character string to exploit the buffer overflow. First we need to fill the buffer, in our case it will be 64 'A'
, then we need to enter the address of the complete_level
function.
To make it easier to create the string, we can use Python.
python -c "print 'A'*64 + '\x9D\x06\x40'" | ./stack-three
Finally, we can see that the fp
variable has been modified, so we can complete the challenge by calling the complete_level
function.