$ cat writeup.md…
$ cat writeup.md…
hackthebox
Task: Interactive text game requiring automated responses to scenarios (GORGE→STOP, PHREAK→DROP, FIRE→ROLL). Solution: Used pwntools for interactive connection and regex parsing to extract scenarios and send correct responses.
An interactive HackTheBox challenge featuring a text-based game "The Fray: The Video Game". The player must respond to various scenarios with the correct actions:
| Scenario | Action |
|---|---|
| GORGE | STOP |
| PHREAK | DROP |
| FIRE | ROLL |
When multiple scenarios are presented together (e.g., "GORGE, FIRE, PHREAK"), the response should be "STOP-ROLL-DROP" (actions joined by hyphens).
nc 94.237.120.233 51681
Upon connection, we receive a prompt to start the game:
Welcome to The Fray: The Video Game!
We will present you with various scenarios that you must react to.
If you have any questions, please direct them to the organisers.
Do you want to start? (y/n):
After sending 'y', the game starts with an endless stream of scenarios:
What do you do?
GORGE
Your response:
Key observations:
#!/usr/bin/env python3 """ HTB - Stop Drop and Roll Interactive challenge solution using pwntools. The challenge simulates a video game where the player must respond to scenarios with correct actions: - GORGE → STOP - PHREAK → DROP - FIRE → ROLL """ from pwn import * # Logging setup context.log_level = 'info' def solve(): """ Main solution function that handles the interactive game. """ # Connect to the service io = remote('94.237.120.233', 51681) try: # Wait for prompt and start the game io.recvuntil(b'Do you want to start? (y/n):') io.sendline(b'y') log.info("Game started!") # Dictionary mapping scenarios to actions action_map = { 'GORGE': 'STOP', 'PHREAK': 'DROP', 'FIRE': 'ROLL' } # Round counter round_num = 0 while True: round_num += 1 # Receive data from server data = io.recvuntil(b'\n').decode('utf-8') log.debug(f"Received: {data!r}") # Skip empty lines and service messages if 'What do you do?' in data: # Sometimes scenario is on the same line, sometimes on the next # Read next line if needed more_data = io.recvuntil(b'\n').decode('utf-8') log.debug(f"More data: {more_data!r}") # Combine for parsing scenario_line = more_data.strip() else: scenario_line = data.strip() # Check for flag if 'HTB{' in scenario_line: log.success(f"Flag found: {scenario_line}") print(scenario_line) break # Skip service lines if 'Your response:' in data or 'Your response:' in more_data: continue # Extract scenarios from the line scenarios = [] for keyword in action_map.keys(): if keyword in scenario_line: scenarios.append(keyword) # Form response if scenarios: # Sort by order of appearance in the original line scenarios_sorted = sorted(scenarios, key=lambda x: scenario_line.find(x)) response = '-'.join(action_map[s] for s in scenarios_sorted) log.info(f"Round {round_num}: {scenario_line} → {response}") # Send response io.sendline(response.encode('utf-8')) else: # If scenario not recognized, continue log.warning(f"Unknown scenario: {scenario_line}") except Exception as e: log.error(f"Error: {e}") raise finally: io.close() if __name__ == '__main__': solve()
For more reliable parsing, regular expressions can be used:
#!/usr/bin/env python3 """ Optimized version with better parsing using regex. """ from pwn import * import re def solve(): io = remote('94.237.120.233', 51681) io.recvuntil(b'Do you want to start? (y/n):') io.sendline(b'y') action_map = { 'GORGE': 'STOP', 'PHREAK': 'DROP', 'FIRE': 'ROLL' } # Pattern for finding scenarios pattern = re.compile(r'\b(GORGE|PHREAK|FIRE)\b') while True: # Read line and search for scenarios data = io.recvline().decode('utf-8') if 'HTB{' in data: match = re.search(r'HTB{[^}]+}', data) if match: print(match.group(0)) break if 'What do you do?' in data: # Read next line with scenario scenario = io.recvline().decode('utf-8').strip() # Extract scenarios found = pattern.findall(scenario) if found: response = '-'.join(action_map[a] for a in found) log.info(f"Response: {response}") io.sendline(response.encode('utf-8')) if __name__ == '__main__': solve()
This challenge can be solved when the following are present:
pwntools for interactivity — the pwn module provides convenient functions for working with network connections (remote(), recvuntil(), sendline())
Parsing dynamic input — the server may combine multiple messages into one line, so flexible parsing is needed
Automating routine tasks — when a challenge requires repeated similar actions, a script saves time and eliminates human errors
Regular expressions — for extracting patterns from strings (re.findall(), re.search()) — more reliable than in + substring search
Error handling — always use try/finally to guarantee connection closure
Logging context — context.log_level = 'info' allows seeing progress without excessive debug message noise
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar