Chapter 1: Intrigue in the Interstice

Thanks to your work, we have discovered that the owner of the car is actually a technician that belongs to the organization. They frequently went to a server room, of which we have found the location.

Our operatives have managed to intrude into the building and place an MITM chip on the target's network. It is situated right in front of what we suspect to be a license server, probably used for a game that is played by some of the organization's members.

The server manages accounts and account activation, and does not host the game in itself. This means the legitimate client of this server is not the whole game but only the game launcher.

We first need you to make sense of the communications between this server and its various clients, and retrieve a license key. This may allow us to get a foothold on their private game server, and move on further with the investigation.

To connect to the MITM setup, you need to expose a TCP port to the internet (this may be achieved through a reverse tunnel such as serveo or ngrok). When a client tries to connect to the license server, it will instead connect to you: you can then choose whether you will forward messages to the server, and even tamper with them.

By starting an instance, you will be assigned two ports: one for the MITM setup server, and one for the license server. First, you need to specify which host and port you are listening on to the MITM setup server. Then, any client trying to reach the server will attempt to connect to you through this port, and you shall be able to forward connections to the license server.

To make your life easier, we provide a small template script that you may use to connect to the MITM chip and view all communications going through it: mitm.py.

import asyncio

SERVER_HOST = "163.172.99.233"

SETUP_PORT = ### <-- SETUP PORT GIVEN WHEN STARTING INSTANCE
SERVER_PORT = ### <-- LICENSE SERVER PORT GIVEN WHEN STARTING INSTANCE

PUBLIC_TUNNEL_HOST = ### <-- YOUR PUBLIC HOST
PUBLIC_TUNNEL_PORT = ### <-- YOUR PUBLIC PORT

LOCAL_MITM_HOST = ""
LOCAL_MITM_PORT = ### <-- YOUR LOCAL BINDING PORT

async def client_handler(clientside_reader, clientside_writer):
    print("New connection")
    serverside_reader, serverside_writer = await asyncio.open_connection(SERVER_HOST, SERVER_PORT)

    while True:
        if not (client_to_server := (await clientside_reader.read(1024))):
            print("Connection closed by client")
            serverside_writer.close()
            await serverside_writer.wait_closed()
            return

        print("Client: " + client_to_server.hex())
        serverside_writer.write(client_to_server)
        await serverside_writer.drain()

        if not (server_to_client := (await serverside_reader.read(1024))):
            print("Connection closed by server")
            return

        print("Server: " + server_to_client.hex())
        clientside_writer.write(server_to_client)
        await clientside_writer.drain()

async def print_setup_read(reader, writer):
    if not (setup_msg := (await reader.read(1024))):
        print("\033[31mConnection closed during setup phase\033[0m")
        writer.close()
        await writer.wait_closed()
        exit()
    print(setup_msg.decode())

# Start an instance of the challenge
async def setup():
    setup_reader, setup_writer = await asyncio.open_connection(SERVER_HOST, SETUP_PORT)
    await print_setup_read(setup_reader, setup_writer)
    setup_writer.write(f"{PUBLIC_TUNNEL_HOST}:{PUBLIC_TUNNEL_PORT}".encode())
    await setup_writer.drain()
    await print_setup_read(setup_reader, setup_writer)

# Start the MITM listener
async def mitm_listener():
    server = await asyncio.start_server(client_handler, LOCAL_MITM_HOST, LOCAL_MITM_PORT)
    async with server:
        await server.serve_forever()

async def main():
    # Run the listener and the setup tasks in parallel to avoid the challenge telling us it can't connect to our listener
    await asyncio.gather(mitm_listener(), setup())

asyncio.run(main())

We are looking forward to your success on this mission. Good luck, agent!


Once you found the license key, enter it here:

 


This challenge was designed to be solved in black box (no source files were given). If you are interested in running this challenge locally, you can download the sources here and build the Docker container. In this case, you don't need to expose a TCP port to the internet anymore; you can simply setup a local listener.