2024 Cyber Apocalypse: Stop Drop and Roll
Challenge Information
| Attribute | Details |
|---|---|
| Event | 2024 Cyber Apocalypse |
| Category | Miscellaneous |
| Challenge | Stop Drop and Roll |
| Difficulty | Very Easy |
Summary
Stop Drop and Roll is a miscellaneous coding challenge where participants must script responses to a text-based game. The server presents scenarios (GORGE, PHREAK, or FIRE) and expects corresponding actions (STOP, DROP, or ROLL). The challenge tests basic socket programming and string manipulation skills.
Analysis
The challenge runs a simple remote game server that:
- Presents game scenarios in a sequence
- Expects players to respond with the correct action mapping:
- GORGE → STOP
- PHREAK → DROP
- FIRE → ROLL
- Can present multiple scenarios at once (e.g., “GORGE, FIRE, PHREAK” → “STOP-ROLL-DROP”)
- Terminates after all scenarios are completed, returning the flag
The vulnerability (if any) is the necessity to script automation to handle the repetitive scenarios quickly.
Solution
Step 1: Connect to the Server
The server is accessed via socket connection to the provided IP and port:
- IP:
94.237.56.248 - Port:
58685
Step 2: Send Initial Confirmation
Upon connection, the server presents rules and asks if you’re ready. Respond with ‘y’:
p.sendlineafter(b'(y/n) ', b'y')Step 3: Parse and Respond to Scenarios
For each prompt, extract the scenario, map each component, and send back the action:
def send_response(sock, scenario, log_file): """Send the appropriate response to the server based on the scenario.""" action_map = {'GORGE': 'STOP', 'PHREAK': 'DROP', 'FIRE': 'ROLL'} actions = [action_map[part.strip()] for part in scenario.split(',')] response = '-'.join(actions) + '\n' sock.sendall(response.encode()) log_file.write("Sent: " + response)Step 4: Loop Until Flag
Continue reading prompts and sending responses until the server returns data that doesn’t contain game scenarios. This will be the flag:
while True: prompt = recvuntil(sock, b'What do you do?')
if "What do you do?" not in prompt: continue
scenario_lines = prompt.strip().split('\n') scenario = scenario_lines[-1] if scenario_lines[-1] != "What do you do?" else scenario_lines[-2]
send_response(sock, scenario, log_file)Complete Solver Script
import socket
def recvuntil(sock, delim=b'\n'): data = b'' try: while not data.endswith(delim): fragment = sock.recv(1) if not fragment: break data += fragment except socket.timeout: print("Timeout reached without finding delimiter.") return data.decode()
def send_response(sock, scenario, log_file): action_map = {'GORGE': 'STOP', 'PHREAK': 'DROP', 'FIRE': 'ROLL'} actions = [action_map[part.strip()] for part in scenario.split(',')] response = '-'.join(actions) + '\n' sock.sendall(response.encode()) log_file.write("Sent: " + response)
def main(ip, port): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock, open("game_log.txt", "w") as log_file: sock.connect((ip, port)) sock.settimeout(2)
intro = recvuntil(sock, b'Are you ready? (y/n)') print(intro) log_file.write(intro + '\n') sock.sendall(b'y\n')
index = 0 while True: index += 1 print(f"\nScenario {index}:") try: prompt = recvuntil(sock, b'What do you do?') print(prompt) log_file.write("Received: " + prompt + '\n')
if "What do you do?" not in prompt: continue
scenario_lines = prompt.strip().split('\n') scenario = scenario_lines[-1] if scenario_lines[-1] != "What do you do?" else scenario_lines[-2]
send_response(sock, scenario, log_file)
except socket.timeout: print("No more data from the server.") log_file.write("No more data from the server.\n") break
if __name__ == "__main__": IP = "94.237.56.248" PORT = 58685 main(IP, PORT)Key Takeaways
- Socket programming fundamentals for remote server communication
- String manipulation and parsing of game scenarios
- Understanding protocol-based challenges where responses must follow specific rules
- Logging output for debugging complex interactions
- Timeout handling when dealing with network sockets
Flag: HTB{1_wiLl_sT0p_dR0p_4nD_r0Ll_mY_w4Y_oUt!}