# bad_file

This writeup goes out to my friend and the person who made this challenge, the man, the myth, the legend himself, noopnoop.

Let's take a look at the binary and libc file:
```
$ file bad_file
bad_file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=2f17700ec82063187dc67e7ac0f76345fbbd3c20, not stripped
$ pwn checksec bad_file
[*] '/Hackery/pod/modules/fs_exploitation/swamp19_badfile/bad_file'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$ ./libc6.so
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu11) stable release version 2.23, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 5.4.0 20160609.
Available extensions:
  crypt add-on version 2.1 by Michael Glad and others
  GNU Libidn by Simon Josefsson
  Native POSIX Threads Library by Ulrich Drepper et al
  BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

```

```
$    file bad_file
bad_file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=2f17700ec82063187dc67e7ac0f76345fbbd3c20, not stripped
$    pwn checksec bad_file
[*] '/Hackery/swamp/bad_file/bad_file'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
$    ./bad_file
Would you like a (1) temporary name or a (2) permanent name?
1
15935728
Hello, 15935728 (for now)
I created a void for you, and this can let you practice some sorcery
You're in danger, you'll need a new name.
75395128
Now let's send some magic to the void!!
Segmentation fault (core dumped)
$ ./bad_file
Would you like a (1) temporary name or a (2) permanent name?
1
15935728
Hello, 15935728 (for now)
I created a void for you, and this can let you practice some sorcery
You're in danger, you'll need a new name.
75395128
Now let's send some magic to the void!!
 [;9B
I hope the spell worked!
```

So we can see that we are dealing with a 64 bit binary without RELRO or PIE. When we run the binary it prompts us for several inputs before crashing.

### Reversing

When we take a look at the Ghidra disassembly, we see this:
```

void main(void)

{
  void *ptr;
  FILE *stream;
  char input0 [16];
  char input1 [40];
 
  ptr = malloc(0x250);
  setbuf(stdout,(char *)0x0);
  puts("Would you like a (1) temporary name or a (2) permanent name?");
  read(0,input0,2);
  if (input0[0] == '1') {
    temp_name(ptr);
  }
  else {
    perm_name(ptr);
  }
  stream = fopen("/dev/null","rw");
  puts("I created a void for you, and this can let you practice some sorcery");
  puts("You\'re in danger, you\'ll need a new name.");
  read(0,ptr,0x160);
  puts("Now let\'s send some magic to the void!!");
  fread(input1,1,8,stream);
  puts(input1);
  puts("I hope the spell worked!");
                    /* WARNING: Subroutine does not return */
  exit(0);
}
```

So we see it starts off my allocating the `0x250` byte chunk `ptr` with malloc. Proceeding that it prompts us for input. If we input a `1` it runs the `temp_name` function with the argument `ptr`. If we input anything else it runs `perm_name` with the argument `ptr`. After that it opens up the file `/dev/null`. Proceeding that we are able to scan `0x160` bytes into the space pointed to by `ptr`. After that it scans in 8 bytes of data from the file object which should be `/dev/null` into the char buffer `input1`. Following that it prints the contents of `input1`. Let's take a look at the `perm_name` and `temp_name` functions:

```
void temp_name(char *input)

{
  gets(input);
  printf("Hello, %s (for now)\n",input);
  free(input);
  return;
}
```

```
void perm_name(char *input)

{
  gets(input);
  printf("Hello, %s!\n");
  return;
}
```

These functions are pretty similar. They both scan in input to the heap pointer `ptr` with `gets` (which will allow us to overflow it), and then prints the contents of `ptr`. The difference is `temp_name` frees the heap pointer after printing it's contents, which we can then scan data into later. This is a use after free bug.

### Exploiting

So we have a heap overflow bug with gets, and a use after free. For the heap overflow bug I initially wanted to see if I could overflow the buffer right up to an address and then leak it with the printf call. However there was one problem with that:

```
gef➤  x/80g 0x602010
0x602010: 0x0 0x0
0x602020: 0x0 0x0
0x602030: 0x0 0x0
0x602040: 0x0 0x0
0x602050: 0x0 0x0
0x602060: 0x0 0x0
0x602070: 0x0 0x0
0x602080: 0x0 0x0
0x602090: 0x0 0x0
0x6020a0: 0x0 0x0
0x6020b0: 0x0 0x0
0x6020c0: 0x0 0x0
0x6020d0: 0x0 0x0
0x6020e0: 0x0 0x0
0x6020f0: 0x0 0x0
0x602100: 0x0 0x0
0x602110: 0x0 0x0
0x602120: 0x0 0x0
0x602130: 0x0 0x0
0x602140: 0x0 0x0
0x602150: 0x0 0x0
0x602160: 0x0 0x0
0x602170: 0x0 0x0
0x602180: 0x0 0x0
0x602190: 0x0 0x0
0x6021a0: 0x0 0x0
0x6021b0: 0x0 0x0
0x6021c0: 0x0 0x0
0x6021d0: 0x0 0x0
0x6021e0: 0x0 0x0
0x6021f0: 0x0 0x0
0x602200: 0x0 0x0
0x602210: 0x0 0x0
0x602220: 0x0 0x0
0x602230: 0x0 0x0
0x602240: 0x0 0x0
0x602250: 0x0 0x0
0x602260: 0x0 0x20da1
```

Here is a look at the memory region of `ptr` which points to `0x602010` (and a bit past where it ends). The issue is other than the top chunk (`0x20da1` specifies how much space is left unallocated in the heap) there is nothing but zeroes in are of the heap our overflow can reach. That coupled with the fact the only thing left that happens to the heap in terms of allocating/freeing memory is a single free to `ptr`, we can't use this bug for anything other than a DOS.

So that just leaves us with the use after free. However when we look into that, we see something interesting:

```
────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffde00│+0x0000: 0x[PII_REDACTED]602010  →  0x00007ffffbad2488  ← $rsp
0x00007fffffffde08│+0x0008: 0x[PII_REDACTED]000000
0x00007fffffffde10│+0x0010: 0x[PII_REDACTED]000a31 ("1"?)
0x00007fffffffde18│+0x0018: 0x[PII_REDACTED]400a0d  →  <__libc_csu_init+77> add rbx, 0x1
0x00007fffffffde20│+0x0020: 0x[PII_REDACTED]000000
0x00007fffffffde28│+0x0028: 0x[PII_REDACTED]000000
0x00007fffffffde30│+0x0030: 0x[PII_REDACTED]4009c0  →  <__libc_csu_init+0> push r15
0x00007fffffffde38│+0x0038: 0x[PII_REDACTED]400740  →  <_start+0> xor ebp, ebp
──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x400938 <main+123>       mov    esi, 0x400ab5
     0x40093d <main+128>       mov    edi, 0x400ab8
     0x400942 <main+133>       call   0x400710 <fopen@plt>
 →   0x400947 <main+138>       mov    QWORD PTR [r