Heap Exploits

Heap Buffer Overflow

This occurs when unsafe functions are used which can overflow buffers (such as strcpy).

The idea is to overflow a pointer. When that pointer is written to, then since you can overflow it with an arbitrary value, then you will be able to write to an arbitrary address.

This allows you to overwrite a function pointer in the global offset table (GOT), or overwrite the function return pointer. The GOT method is more reliable.

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");
}

Heap state before the first strcpy:

0xf7e69000  0x00000000 # chunk header first part 
0xf7e69004  0x00000011 # chunk second part. 0x8 bytes malloc + 0x8 bytes header + 0x1 byte for the previous chunk being used = 0x11 
0xf7e69008  0x00000001 # struct1.priority = 1
0xf7e6900c  0xf7e69018 # *struct1.name
0xf7e69010  0x00000000
0xf7e69014  0x00000011
0xf7e69018  0x00000000 # struct1.name. Strcpy starts writing into this part 
0xf7e6901c  0x00000000
0xf7e69020  0x00000000
0xf7e69024  0x00000011
0xf7e69028  0x00000002
0xf7e6902c  0xf7e69038 # *struct2.name. The pointer specified at this address will be written to. If we overwrite this value, then we will change the address where the write will occur. We can overwrite it  with the GOT address
0xf7e69030  0x00000000
0xf7e69034  0x00000011
0xf7e69038  0x00000000
0xf7e6903c  0x00000000
0xf7e69040  0x00000000
0xf7e69044  0x000fffc1

Use-After-Free

Use after free occurs when a memory address is freed, but the variable that points to the free memory address is still used after the free.

By allocating space for new variable(s) into the space that was freed, you can control the value of the old variable through the value new variable(s). This is because if the old dangling variable is used again, then its value will be taken from the space where the new variable(s) was/were allocated.

Phoenix Heap 2 solution

Solution (all you have to do is interact with the program):

[ auth = 0, service = 0 ]
auth admin
[ auth = 0x8049af0, service = 0 ]
reset
[ auth = 0x8049af0, service = 0 ]
service aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[ auth = 0x8049af0, service = 0x8049af0 ]
login
you have logged in already!

Explanation

You allocate space for the auth variable on the heap. The auth variable will point to the location of the allocated space on the heap. Then you free that space. However, the variable is not nulled and it will still point to a freed space on the heap.

The service command calls malloc() behind the scenes (allocates space on the heap) and writes to the allocated space.

This space will be allocated to the same spot that was freed earlier. And data will be written there. The auth variable still points to that spot, so you're effectively overwriting the contents of auth.

By specifying a long string ("aaaaaaaaaa...") you're overwriting the 32 byte buffer of name and overwriting auth.

Thus, the application thinks you're logged in.

Last updated