//Stop Drop and Roll
Challenge: Stop Drop and Roll
Remote: nc 94.237.57.115 47985
Flag format: HTB{...}
>Summary
This challenge is an interactive network service that implements a simple mapping game. The server presents a short tutorial and then repeatedly sends challenges: a comma-separated sequence of scenario words drawn from {GORGE, PHREAK, FIRE}. The correct reply is a dash-separated sequence mapping each scenario to a corresponding action:
-
GORGE -> STOP
-
PHREAK -> DROP
-
FIRE -> ROLL
After successfully answering a series of challenges the server returns the flag.
I automated the interaction with a short Python script 001_solve.py that connects to the remote host, answers the ready prompt, parses each challenge, sends the correct response, and prints the flag when seen.
>Recon and Analysis
-
I first inspected the workspace. There were no local challenge binaries or scripts to analyze; the challenge is remote-only.
-
I connected with netcat to the remote host to observe behavior and the tutorial text. The server clearly described the mapping and the format for multi-item responses (comma-separated input, dash-separated output).
-
The protocol is simple plain-text over TCP; no authentication or exotic encoding. Automating is straightforward and reliable.
Edge cases to consider
-
The tutorial includes the scenario words for demonstration; the solver must avoid replying to those tutorial lines.
-
The server asks a readiness confirmation
Are you ready? (y/n)that must be answered withyto start. -
Challenges might be single words or multiple words; responses must preserve order and be connected by
-. -
Ensure we detect the flag anywhere in the server output (it uses format HTB{...}).
>Solution approach
Write a short, robust Python client that:
-
Connects to 94.237.57.115:47985 with a socket.
-
Reads incoming lines and prints them for logging.
-
When the server asks
Are you ready? (y/n), sendy. -
Only after sending
y, parse challenge lines for the tokensGORGE,PHREAK,FIRE. -
Build the response by mapping tokens to their actions and joining with
-. -
Send responses with a newline and keep listening until a flag HTB{...} appears.
This approach is resilient to the tutorial text and simple to implement.
>Code: 001_solve.py
Below is the full solver script used. It is intentionally verbose for visibility (prints server messages, parsed sequences, and outgoing responses).
#!/usr/bin/env python3
"""
001_solve.py
Automated solver for 'Stop Drop and Roll' (HTB MISC).
Connects to the remote service, parses scenario sequences like
"GORGE, FIRE, PHREAK" and replies with the mapped actions
"STOP-ROLL-DROP". Prints the HTB{...} flag when seen.
Usage: python3 001_solve.py
"""
import socket
import re
import time
import sys
HOST = '94.237.57.115'
PORT = 47985
MAPPING = {
'GORGE': 'STOP',
'PHREAK': 'DROP',
'FIRE': 'ROLL',
}
WORD_RE = re.compile(r'GORGE|PHREAK|FIRE')
FLAG_RE = re.compile(r'HTB\{.*?\}')
def recv_all(sock, timeout=2.0):
"""Receive available data (non-blocking-ish) and return decoded text."""
sock.settimeout(timeout)
data = b''
try:
while True:
part = sock.recv(4096)
if not part:
break
data += part
if len(part) < 4096:
# no more immediate data
break
except socket.timeout:
pass
except Exception:
pass
try:
return data.decode(errors='ignore')
except Exception:
return ''
def solve_loop(host, port):
print('\n=== 🕹️ Stop Drop and Roll solver starting ===')
print(f'Connecting to {host}:{port}...')
with socket.create_connection((host, port), timeout=10) as s:
s.settimeout(10)
buffer = ''
started = False
while True:
data = recv_all(s, timeout=2.0)
if not data:
# nothing new, keep waiting
time.sleep(0.1)
continue
buffer += data
for line in data.splitlines():
line = line.strip()
if not line:
continue
print('\n📥 Server:', line)
# Check for flag anywhere in the line
mflag = FLAG_RE.search(line)
if mflag:
print('\n🎯 FLAG found:', mflag.group(0))
print('=== ✅ Done ===\n')
return
# If the server asks if we're ready, answer 'y' (robust substring check)
low = line.lower()
if 'ready' in low and '(y/n)' in low:
try:
print('➡️ Sending: y')
s.sendall(b'y\n')
started = True
print('🏁 Game started — now listening for challenges')
continue
except BrokenPipeError:
print('⚠️ Connection closed by remote')
return
# If the game hasn't started (we're in tutorial), don't reply to
# scenario words. Only respond after we've answered 'y'.
if not started:
continue
# Now we are in the game: respond to scenario lines. Only reply
# when the line looks like an actual challenge (comma-separated
# or multiple words).
seq = WORD_RE.findall(line)
if seq and (',' in line or len(seq) > 1 or line.isupper()):
resp = '-'.join(MAPPING.get(w, 'UNK') for w in seq)
print('🔎 Parsed sequence:', seq)
print('➡️ Sending response:', resp)
try:
s.sendall((resp + '\n').encode())
except BrokenPipeError:
print('⚠️ Connection closed by remote')
return
if __name__ == '__main__':
try:
solve_loop(HOST, PORT)
except KeyboardInterrupt:
print('\nInterrupted by user')
sys.exit(1)
except Exception as e:
print('Error:', e)
sys.exit(2)
>Sample run (trimmed)
Below is an excerpt from the script running against the remote service (output is verbatim except for trimming):
📥 Server: What do you do?
📥 Server: PHREAK, FIRE, FIRE, GORGE
🔎 Parsed sequence: ['PHREAK', 'FIRE', 'FIRE', 'GORGE']
➡️ Sending response: DROP-ROLL-ROLL-STOP
... [many rounds omitted for brevity] ...
📥 Server: Fantastic work! The flag is HTB{1_wiLl_sT0p_dR0p_4nD_r0Ll_mY_w4Y_oUt!}
🎯 FLAG found: HTB{1_wiLl_sT0p_dR0p_4nD_r0Ll_mY_w4Y_oUt!}
=== ✅ Done ===
>Final flag
HTB{1_wiLl_sT0p_dR0p_4nD_r0Ll_mY_w4Y_oUt!}
>Notes & next steps
-
If you want the script to log every interaction to a numbered file
003_session_log.txt, I can add that. -
If you'd like the run wrapped in a Python virtualenv and a small
README.mdwith usage and requirements, I can add that too. -
The current script is synchronous and simple; for large-scale automation (multiple concurrent sessions) a non-blocking or threaded approach would be better.