13 June 2019

Net 1

Write-up for: https://exploit.education/phoenix/net-one/.

The challenge

This level is similar to the previous one. We can connect on port 64001 to examine the service manually:

user@phoenix-amd64:~$ nc 127.0.0.1 64001
Welcome to phoenix/net-one, brought to you by https://exploit.education
XNp
Close, you sent "", and we wanted "3379580504"

user@phoenix-amd64:~$ nc 127.0.0.1 64001
Welcome to phoenix/net-one, brought to you by https://exploit.education
'#abc
Close, you sent "abc", and we wanted "589766342"

As you can see, it seems like the service is sending some random bytes and expects us to send the number they represent (in the given architecture) back as an ascii string.

Translated to a python script it looks like this:

import struct
import socket

HOST = "127.0.0.1"
PORT = 64001

def read_line_from_sock(socket):
    buf = ""
    while True:
        b = s.recv(1)
        if b == b'\n':
            break
        buf += b.decode("ascii")
    return buf

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    print(read_line_from_sock(s))
    query = s.recv(4)
    to_send = struct.unpack("<I", query)
    print(query)
    print(to_send)
    s.send((str(to_send[0]) + "\n").encode("ascii"))
    print(read_line_from_sock(s))

We use the same read_line_from_sock function as before to read the banner of the service. Next, we use recv to read the 4 bytes that we are expected to write back as an ascii-encoded number. We unpack the value as a little-endian value, convert it to a string and send it back. Done.

Looking at the challenge’s code, we see what happens exactly:

uint32_t i;

getrandom((void *)&i, sizeof(i), 0) != sizeof(i)

write(1, &i, sizeof(i)) != sizeof(i)

fgets(buf, sizeof(buf), stdin) == NULL

sprintf(fub, "%u", i);
if (strcmp(fub, buf) == 0) {

These are the relevant passages. i is a 32-bit unsigned integer, so 4 bytes will be required. The value is generated with getrandom and written to stdout using write. User input is stored in buf and i is stored in fub. Those two (ascii) buffers are then compared as strings using strcmp.

user@phoenix-amd64:~$ python3 net1.py
Welcome to phoenix/net-one, brought to you by https://exploit.education
b'\x96\x9b\xb1:'
(984718230,)
Congratulations, you've passed this level!

Done! ```