# Swamp ctf 2019 syscaller

Let's take a look at the binary:

```
$    file syscaller
syscaller: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=15d03138700bbfd52c735087d738b7433cfa7f22, not stripped
$    pwn checksec syscaller
[*] '/Hackery/pod/modules/srop/swamp19_syscaller/syscaller'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
$    /syscaller
Hello and welcome to the Labyrinthe. Make your way or perish.
15935728
```

So we can see that we are dealing with a `64` bit binary, with non of the standard binary mitigations. When we run it, it prompts us for input.

## Reversing

When we through the binary in Ghidra, we see that it looks like another custom assembled binary. When we look at the `entry` function, we see this:

```
                             //
                             // .text
                             // SHT_PROGBITS  [0x4000e0 - 0x40016d]
                             // ram: 004000e0-0040016d
                             //
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined entry()
             undefined         AL:1           <RETURN>
                             _start                                          XREF[3]:     Entry Point(*), 00400018(*),
                             entry                                                        _elfSectionHeaders::00000090(*)  
        004000e0 55              PUSH       RBP
        004000e1 48 89 e5        MOV        RBP,RSP
        004000e4 48 81 ec        SUB        RSP,0x200
                 00 02 00 00
        004000eb bf 01 00        MOV        EDI,0x1
                 00 00
        004000f0 48 be 30        MOV        RSI,msg1                                         = 48h    H
                 01 40 00
                 00 00 00 00
        004000fa ba 3e 00        MOV        EDX,0x3e
                 00 00
        004000ff b8 01 00        MOV        EAX,0x1
                 00 00
        00400104 0f 05           SYSCALL
        00400106 b8 00 00        MOV        EAX,0x0
                 00 00
        0040010b 48 89 e6        MOV        RSI,RSP
        0040010e bf 00 00        MOV        EDI,0x0
                 00 00
        00400113 ba 00 02        MOV        EDX,0x200
                 00 00
        00400118 0f 05           SYSCALL
        0040011a 41 5c           POP        R12
        0040011c 41 5b           POP        R11
        0040011e 5f              POP        RDI
        0040011f 58              POP        RAX
        00400120 5b              POP        RBX
        00400121 5a              POP        RDX
        00400122 5e              POP        RSI
        00400123 5f              POP        RDI
        00400124 0f 05           SYSCALL
        00400126 b8 3c 00        MOV        EAX,0x3c
                 00 00
        0040012b 48 31 ff        XOR        RDI,RDI
        0040012e 0f 05           SYSCALL
```

We can see, it starts off by moving the stack down by `0x200` bytes. Then it sets up a write syscall to `stdout` (which is what causes us to see that output message). Proceeding that it sets up a read syscall which will allow us to scan in `0x200` bytes via stdin to the top of the stack (where `rsp` is). After that, it will pop values off of the stack into the `r12`, `r11`, `rdi`, `rax`, `rbx`, `rdx`, `rsi`, and `rdi` registers and make a syscall. So we get a syscall where we control a lot of the registers. After that it will make an exit syscall.

## Exploitation

So for the exploit, we will have to do several things. We will use the `syscall` that is preceded by a bunch of `pop` instructions to execute a sigreturn, which will give us code execution. However there is one problem with that.

#### Remapping Memory Regions

Let's take a look at the memory mappings:

```
gef➤  vmmap
Start              End                Offset             Perm Path
0x[PII_REDACTED]400000 0x[PII_REDACTED]401000 0x[PII_REDACTED]000000 r-x /Hackery/pod/modules/srop/swamp19_syscaller/syscaller
0x00007ffff7ffb000 0x00007ffff7ffe000 0x[PII_REDACTED]000000 r-- [vvar]
0x00007ffff7ffe000 0x00007ffff7fff000 0x[PII_REDACTED]000000 r-x [vdso]
0x00007ffffffde000 0x00007ffffffff000 0x[PII_REDACTED]000000 rwx [stack]
0xffffffffff600000 0xffffffffff601000 0x[PII_REDACTED]000000 r-x [vsyscall]
gef➤  
```

So we can see that the only writable memory region by default is the stack. Thing is, we need to write the string `/bin/sh` somewhere in memory at an address we know in order to call it. So starting off the only region we can write to is the stack. However when the syscall is executed, the only real stack addresses we have are stored in the `rbp` and `rsp` registers, which are overwritten by the sigreturn. We can't use the syscall to give us an infoleak, because if it does it will continue on to the exit syscall before we actually get code execution. So by using the sigreturn, we effectively lose our only really stack addresses (stored in `rbp` and `rsp`). Also when we check the stack to see what's in range of our input for a potential leak, we come up with nothing:

```
gef➤  x/65g 0x7fffffffde68
0x7fffffffde68:    0x[PII_REDACTED]393531    0xa
0x7fffffffde78:    0x0    0x0
0x7fffffffde88:    0x0    0x0
0x7fffffffde98:    0x0    0x0
0x7fffffffdea8:    0x0    0x0
0x7fffffffdeb8:    0x0    0x0
0x7fffffffdec8:    0x0    0x0
0x7fffffffded8:    0x0    0x0
0x7fffffffdee8:    0x0    0x0
0x7fffffffdef8:    0x0    0x0
0x7fffffffdf08:    0x0    0x0
0x7fffffffdf18:    0x0    0x0
0x7fffffffdf28:    0x0    0x0
0x7fffffffdf38:    0x0    0x0
0x7fffffffdf48:    0x0    0x0
0x7fffffffdf58:    0x0    0x0
0x7fffffffdf68:    0x0    0x0
0x7fffffffdf78:    0x0    0x0
0x7fffffffdf88:    0x0    0x0
0x7fffffffdf98:    0x0    0x0
0x7fffffffdfa8:    0x0    0x0
0x7fffffffdfb8:    0x0    0x0
0x7fffffffdfc8:    0x0    0x0
0x7fffffffdfd8:    0x0    0x0
0x7fffffffdfe8:    0x0    0x0
0x7fffffffdff8:    0x0    0x0
0x7fffffffe008:    0x0    0x0
0x7fffffffe018:    0x0    0x0
0x7fffffffe028:    0x0    0x0
0x7fffffffe038:    0x0    0x0
0x7fffffffe048:    0x0    0x0
0x7fffffffe058:    0x0    0x0
0x7fffffffe068:    0x0
```

My solution to this is to remap the binary segment (`0x400000 - 0x401000`) to the permissions `rwx`, so we can read write and execute to that segment. I will do this using an `mprotect` syscall, which allows me to assign permissions to a memory region. For that, we will need to have the following register values set:

```
rax:    0xa (specify memprotect syscall)
rdi:    0x400000 (specify beginning of the binary's data segment)
rsi:    0x1000 (specify to apply the permissions to the chunk of this length, which covers the entire memory segment)
rdx:    0x7 (standard unix per