# 0ctf babyheap

For this we are given a binary and a libc file. In order for this exploit to work, you need to run it with the right libc version (look at the exploit code to see how to do it). Let's take a look at what we have here:

```
$    file 0ctfbabyheap
0ctfbabyheap: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=9e5bfa980355d6158a76acacb7bda01f4e3fc1c2, stripped
$    pwn checksec 0ctfbabyheap
[*] '/home/guyinatuxedo/Desktop/prayer/0ctfbabyheap'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
$    ./0ctfbabyheap
===== Baby Heap in 2017 =====
1. Allocate
2. Fill
3. Free
4. Dump
5. Exit
Command:
```

## Reversing

So we can see that we are dealing with a 64 bit binary, with all of the standard elf mitigations. When we run it, we see that we are given a menu with the option to either `Allocate/Fill/Free/Dump/Exit`. When we take a look at the functions in Ghidra we don't see a `main` function. However we can find a function that looks like a menu (either by going through the functions, or checking the x-references to strings we see, and tracing back the function calls):

```
undefined8 heapPointers(void)

{
  undefined8 heapPointers;
  undefined8 menuInput;
 
  heapPointers = FUN_00100b70();
LAB_00101133:
  printMenu();
  menuInput = getInt();
  switch(menuInput) {
  case 1:
    allocate(heapPointers);
    goto LAB_00101133;
  case 2:
    fill(heapPointers);
    goto LAB_00101133;
  case 3:
    free(heapPointers);
    goto LAB_00101133;
  case 4:
    dump(heapPointers);
    goto LAB_00101133;
  case 5:
    break;
  
  return 0;
}
```

So we can see that this is a pretty standard menu function. When we take a look at the `allocate` function, we see this:

```
void allocate(long heapPointers)

{
  void *ptr;
  uint newIndex;
  int size;
 
  newIndex = 0;
  while( true ) {
    if (0xf < (int)newIndex) {
      return;
    }
    if (*(int *)(heapPointers + (long)(int)newIndex * 0x18) == 0) break;
    newIndex = newIndex + 1;
  
  printf("Size: ");
  size = getInt();
  if (size < 1) {
    return;
  
  if (0x1000 < size) {
    size = 0x1000;
  
  ptr = calloc((long)size,1);
  if (ptr != (void *)0x0) {
    *(undefined4 *)(heapPointers + (long)(int)newIndex * 0x18) = 1;
    *(long *)((long)(int)newIndex * 0x18 + heapPointers + 8) = (long)size;
    *(void **)((long)(int)newIndex * 0x18 + heapPointers + 0x10) = ptr;
    printf("Allocate Index %d\n",(ulong)newIndex);
    return;
  
                    /* WARNING: Subroutine does not return */
  exit(-1);
}
```

So we can see a few things here. The first is that it does a check on the amount of chunks it has allocated, and that the max is `0x10` After that it prompts us for a size, that has to be between `1` - `0x1000`. It will then allocate a chunk equal to that size with `calloc`. Proceeding that it will save a pointer to the newly allocated chunk along with its size in `heapPointers` (the arg passed to this function) . Next up we take a look at the `fill` function:

```
void fill(long heapPointers)

{
  int index;
  int size;
 
  printf("Index: ");
  index = getInt();
  if (((-1 < index) && (index < 0x10)) && (*(int *)(heapPointers + (long)index * 0x18) == 1)) {
    printf("Size: ");
    size = getInt();
    if (0 < size) {
      printf("Content: ");
      requestInput(*(long *)(heapPointers + (long)index * 0x18 + 0x10),(long)size);
    }
  
  return;
}
```

So looking at this function, we can see a few things. First it prompts you for the index, and checks it. It will then prompt you for a size, and check if it is greater than `0`. Then it will run `requestInput` with the arguments being a pointer to the chunk we specified with an index, and the size we gave it. This function essentially just scans in the amount of bytes equal to the second argument to the pointer passed to it in the first argument. While it checks to see if the size is greater than zero, it doesn't check to see if the data will overflow it so we have a heap overflow bug. Next up we take a look at the `free` function:

```
void free(long heapPointers)

{
  int index;
 
  printf("Index: ");
  index = getInt();
  if (((-1 < index) && (index < 0x10)) && (*(int *)(heapPointers + (long)index * 0x18) == 1)) {
    *(undefined4 *)(heapPointers + (long)index * 0x18) = 0;
    *(undefined8 *)(heapPointers + (long)index * 0x18 + 8) = 0;
    free(*(void **)(heapPointers + (long)index * 0x18 + 0x10));
    *(undefined8 *)(heapPointers + (long)index * 0x18 + 0x10) = 0;
  
  return;
}
```

Starting out we see it prompts us for an index, and performs the same index check on it. After that it will free the chunk pointer, and zero out the various elements of the data stored in `heapPointers` (so no use after free). Also since the `allocate` function looks for the first blank spot, after we free a chunk that index will be the first one allocated after that. Next up we have the `dump` function:

```
void dump(long heapPointers)

{
  undefined8 uVar1;
  int index;
 
  printf("Index: ");
  index = getInt();
  if (((-1 < index) && (index < 0x10)) && (*(int *)(heapPointers + (long)index * 0x18) == 1)) {
    puts("Content: ");
    uVar1 = *(undefined8 *)(heapPointers + (long)index * 0x18 + 8);
    printChunk(*(undefined8 *)(heapPointers + (long)index * 0x18 + 0x10),uVar1,(long)index * 0x18,
               uVar1);
    puts("");
  
  return;
}
```

Here it prompts us for an index and checks it, just like every other function. Then it will print the contents of the chunk for us with the `printChunk` function.


## Exploitation

So we have the ability to freely allocate and free chunks between `1-0x1000` bytes in size, and up to `0x10` chunks at a time. We can also view the contents of the chunks, and have a heap overflow bug. For this exploit, there will be two parts. The first will involve causing heap consolidation to get a libc infoleak. The second will involve using a Fastbin Attack to write a oneshot gadget to the hoo of malloc. The libc infoleak will allow us to break ASLR in libc and know the address of everything, and writing over the malloc hook with a ROP gadget (that will call system) will give us a shell when we call malloc (we need the infoleak to figure out where the malloc hook and rop gadget are):
 
#### Infoleak

For the infoleak, we will be using a heap consolidation technique. Below you can see exactly how we allocate/free/manage space:

First we allocate four chunks:
```
0xf0:    0
0x70:    1
0xf0:    2
0x30:    3
```

Proceeding that we will free chunks 0 and 1. This will add those chunks to the free list, and if we allocate a chunk of a similar size we will get that chunk again:
```
0xf0:    (freed)
0x70:    (freed)
0xf0:    2
0x30:    3
```

Now that they have been added to the free list, we can allocate another chunk that is `0x78` bytes large. Due to it’s size (and the fact that we just free