heap-one

heap-one is the second heap exploitation exercise from the phoenix vm from exploit education

Source Code

/*
 * phoenix/heap-zero, by https://exploit.education
 *
 * Can you hijack flow control?
 *
 * Which vegetable did Noah leave off the Ark?
 * Leeks
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define BANNER \
  "Welcome to " LEVELNAME ", brought to you by https://exploit.education"

struct heapStructure {
  int priority;
  char *name;
};

int main(int argc, char **argv) {
  struct heapStructure *i1, *i2;

  i1 = malloc(sizeof(struct heapStructure));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct heapStructure));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

void winner() {
  printf(
      "Congratulations, you've completed this level @ %ld seconds past the "
      "Epoch\n",
      time(NULL));
}

For this challenge, paying attention to the source code is vital. We can see that the program defines a structure called heapStructure with two variables one is an integer, called priority and the other one is a pointer, called name.

The program allocates a chunk in the heap for a heapStructure and assigns the i1 variable to it and assings the number 1 to the priority variable, then allocates another space in the heap for the name variable, notice that the second the second element of the first chunk will be a pointer to this new space in the heap.

After that the program repeats the exact same process to a second variable, called i2, regarding that it assings 2 instead of 1 to the priority variable.

After allocation the space it needs, the program copies the first argument to the name variable from the pointer at the i1 heapStructure and the second argument to the name variable from the pointer at the i2 heapStructure. So finally, if we creat a representation of the heap it would look something like this:

Notice that I'm ignoring the metadata for now to ease comprehension. Now, to understand how to abuse this, we must also understand how strcpy() works. strcpy copies something to somewhere, that said and with the source code in hands, we can see that the program copies the arguements to WHEREVER the pointers to name in i1 and i2 point, that means that the DESTINATION of this write action is read from the pointer (ptr[name]) in our representation, that means we can say that the ptr to name, second word of each heapStructure, is WHERE to write, and the respective command line argument is WHAT to write. Now let's picture how that would look if we overflow argv[1]:

Sounds like a plan! Basically with argv[1] we can abuse a heap overflow to control WHERE to write and with argv[2] we already control WHAT to write. Now we need to take a look into the compiled binary to start developing an exploit more easily.

The challenge is available in a varity of architectures, so there will be a different solution to each of them, but all based on the same principle, though I recomend checking the i486 one out first because it's way more didactic than all the others, since I won't repeat the same information over and over again when I'm doing the other versions.

Summary

pagei486

Last updated