← Back to Writeups
CUSTOMEasyWeb

Prove You Are (Not) a Robot

XESXOR9/10/20262 min read
#web#custom#easy#arithmetic_expression_solver#base64_task_decoding#websocket_automation

Prove You Are (Not) a Robot

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-04-04 | Status: Solved Techniques: arithmetic_expression_solver, base64_task_decoding, websocket_automation

Summary

Task: a Uvicorn-served page delegated the real logic to a websocket that issued base64-encoded arithmetic challenges. Solution: automate the websocket flow, decode each expression, compute the answer, and loop through 50 rounds until the server returned the flag.

Prove You Are (Not) a Robot — Hackerlab

Description

Original task name: «Я не робот! Докажи, что ты (не) робот!»

Target: http://62.173.140.174:16011/

The page itself was only a thin frontend. JavaScript immediately opened a websocket connection and the real challenge was a sequence of server-issued arithmetic tasks that had to be solved automatically.

Analysis

Initial recon showed an HTTP page served by Uvicorn and a client-side websocket connection to:

text
ws://62.173.140.174:16011/ws

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

After connecting, the server sent messages such as:

text
[*] Solve: eCA9IDE2MSAqIDg3Ng==

The string after Solve: was base64. Decoding it produced an expression like:

text
x = 161 * 876

Sending the correct result returned the next challenge together with a progress counter (1/50 through 49/50). After 50 correct answers, the websocket returned the flag directly. So this was not a browser interaction problem; it was a simple websocket automation task.

Solution

  1. Open the main page and inspect the JavaScript.
  2. Connect directly to ws://62.173.140.174:16011/ws.
  3. Extract the base64 blob from each Solve: message.
  4. Decode it and parse the arithmetic expression.
  5. Support +, -, and *.
  6. Send each computed result back on the same websocket until the flag appears. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
python
#!/usr/bin/env python3
import asyncio
import base64
import re

import websockets


HOST = "ws://62.173.140.174:16011/ws"
FLAG_RE = re.compile(r"CODEBY\{[^}]+\}")
TASK_RE = re.compile(r"Solve:\s*([A-Za-z0-9+/=]+)")
EXPR_RE = re.compile(r"x\s*=\s*(-?\d+)\s*([+\-*])\s*(-?\d+)")


def solve_expr(encoded: str) -> str:
    decoded = base64.b64decode(encoded).decode()
    m = EXPR_RE.fullmatch(decoded.strip())
    if not m:
        raise ValueError(f"Unexpected task: {decoded!r}")
    a, op, b = m.groups()
    a, b = int(a), int(b)
    if op == "+":
        return str(a + b)
    if op == "-":
        return str(a - b)
    if op == "*":
        return str(a * b)
    raise ValueError(f"Unsupported operator: {op}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍


async def main() -> None:
    async with websockets.connect(HOST) as ws:
        while True:
            message = await ws.recv()
            print(message)
            flag = FLAG_RE.search(message)
            if flag:
                print(f"\nFLAG: {flag.group(0)}")
                return

            m = TASK_RE.search(message)
            if not m:
                continue
            await ws.send(solve_expr(m.group(1)))


if __name__ == "__main__":
    asyncio.run(main())

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍