ReturnMeFast

problem description

Solution

We connect to the challenge and interact with it:

$ nc returnmefast.chal.intentsummit.org 9999
INPUT> fdsf
NotTheJsonIWasLookingFor
INPUT> {}
NoCommand No field command in data.
INPUT> {"command": 1}
BadUserName No username field.
INPUT> {"command": 1, "username": "username"}
Unicorn me asap. Starting the game: username -> [(1, 2), (1, 5), (10, 14), (7, 8), (3, 6), (6, 9), (4, 5), (11, 16)].
INPUT>
... snipped ...
$ nc returnmefast.chal.intentsummit.org 9999
INPUT> {"command": 1, "username": "username"}
Unicorn me asap. Starting the game: username -> [(6, 11), (1, 6), (13, 18), (2, 3), (4, 9), (2, 7), (5, 8), (8, 9)].
INPUT> {"command":2,"username":"username"}
MissingX86Unicorn Missing asm field.
INPUT> {"command":2,"username":"username","asm":"9"}
BadX86AsmHex The format of your asm code was not right. Look at unicorns for examples.
INPUT> {"command":2,"username":"username","asm":"909090909090909090"}
BadUnicornLength 9
... snipped ...
INPUT> {"command": 1, "username": "username"}
Unicorn me asap. Starting the game: username -> [(6, 9), (4, 8), (8, 12), (7, 11), (4, 8), (1, 4), (5, 3), (12, 17)].
INPUT> {"command":2,"username":"usernane","asm":"909090909090909090"}
BadUserName
INPUT> {"command":2,"username":"username","asm":"909090909090909090"}
BadEaxVal Val was 0

So what we have seen? The server challenge us to send it a spesified length of bytes that are hex-encoded x86 assembly which should probably set the value of the EAX register to a provided value. To evaluate our code it uses unicorn-engine, also it expects us to return the answers pretty fast.

To overcome the challenge we create the following script:

from pwn import *
from ast import literal_eval
import json

r = remote("returnmefast.chal.intentsummit.org", 9999)

def send_start():
    r.recvuntil(b"INPUT> ")
    r.sendline(json.dumps({"command": 1, "username": "username"}).encode())


def parse_ch():
    ret = r.recvuntil(b"INPUT> ")
    return literal_eval(f"[{(ret.partition(b'[')[2].partition(b']')[0]).decode()}]")

def send_asm(sz, val):
    nh = asm(f'add eax, {val}')
    r.sendline(json.dumps({"command": 2, "username": "username", "asm": nh.hex()+"90"*(sz-len(nh))}).encode())
    print(r.recvuntil(b"INPUT> "))


send_start()
ch = parse_ch()
print(ch)
for val, sz in ch:
    print(sz, val)
    send_asm(sz, val)

We run the script:

$ python3 script.py
[+] Opening connection to returnmefast.chal.intentsummit.org on port 9999: Done
[(6, 10), (4, 8), (8, 13), (3, 5), (3, 6), (7, 8), (3, 5), (12, 13)]
10 6
b'Good!. Go to the next step.\nINPUT> '
8 4
b'Good!. Go to the next step.\nINPUT> '
13 8
b'Good!. Go to the next step.\nINPUT> '
5 3
b'Good!. Go to the next step.\nINPUT> '
6 3
b'Good!. Go to the next step.\nINPUT> '
8 7
b'Good!. Go to the next step.\nINPUT> '
5 3
b'Good!. Go to the next step.\nINPUT> '
13 12
b'INTENT{we1Rd_unkn0wn_m4Chin3S_ar3_mY_J4m}\nINPUT> '
[*] Closed connection to returnmefast.chal.intentsummit.org port 9999

We got the flag: INTENT{we1Rd_unkn0wn_m4Chin3S_ar3_mY_J4m}.