Tower of Hanoi Revenge - Writeup
Challenge Overview
The "Tower of Hanoi Revenge" challenge provides a network service and a zip file containing an emulator environment. The goal is to obtain the flag hidden within the system.
- Points: 500
- Service:
nc exp.cybergame.sk 7011
Initial Analysis
The provided zip file contains:
markiv_nosocket: A 64-bit ELF executable (emulator).markivrom.bin: A 512KB ROM image for the emulator.main.com: A CP/M executable (the Tower of Hanoi game).Dockerfile&docker-compose.yaml: Infrastructure for the challenge.
The system is a Mark IV (Z180) single-board computer running RomWBW HBIOS v3.5.1 and CP/M 2.2.
Discovery and Attempts
1. Automation of the Game
The game MAIN.COM is a standard Tower of Hanoi implementation with 5 disks. Solving it requires 31 moves. I wrote a Python script to automate these moves.
Script Fragment:
moves = [(1,3), (1,2), (3,2), (1,3), (2,1), (2,3), (1,3), ...]
for src, dst in moves:
s.sendall(fclass="hljs-string">"{src}\r\n{dst}\r\n")Solving the game resulted in a "Congratulations! You Win!" message but did not yield the flag.
2. File System Investigation
Listing the directory (DIR) on drive B: (the ROM disk) showed two files:
FLAG.TXTMAIN.COM
However, attempting to read the flag using the standard CP/M TYPE command failed:
B>TYPE FLAG.TXT
TYPE?The standard CP/M shell seemed restricted or broken, as many built-in commands returned a ? error.
3. Exploring the Boot Loader and Monitor
By sending <esc> repeatedly during the boot process, I was able to interrupt the autoboot and enter the Mark IV Boot Loader.
The Boot Loader offers several options (L command):
M: MonitorC: CP/M 2.2Z: Z-SystemB: BASIC- ...
Entering the Monitor (M) allowed for direct memory manipulation and dumping (D command). While I found a fake flag in the local ROM file, scanning the remote memory for the real flag proved time-consuming.
Final Solution: Z-System
The breakthrough came from booting into Z-System (option Z in the Boot Loader) instead of the default CP/M. Z-System is an advanced replacement for CP/M that often includes more robust tools and a different command processor.
- Connect to the server.
- Send
<esc>multiple times to interrupt boot. - Send
Zto boot into Z-System. - Navigate to drive
B:. - Execute
TYPE FLAG.TXT.
In Z-System, the TYPE command worked perfectly and revealed the flag.
Flag
SK-CERT{0k4y_n0w_f0r_r34l_h0w_0ld_4r3_y0u}
Automation Script
import socket
import time
def solve():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((class="hljs-string">'exp.cybergame.sk', 7011))
s.settimeout(2)
# 1. Interrupt boot process
print(class="hljs-string">"[*] Interrupting boot...")
for _ in range(50):
s.sendall(bclass="hljs-string">"\x1b")
time.sleep(2)
s.recv(16384) # Clear buffer
# 2. Boot into Z-System
print(class="hljs-string">"[*] Booting into Z-System...")
s.sendall(bclass="hljs-string">"Z\r\n")
time.sleep(10) # Wait for Z-System to initialize
s.recv(16384)
# 3. Read the flag
print(class="hljs-string">"[*] Reading FLAG.TXT...")
s.sendall(bclass="hljs-string">"TYPE FLAG.TXT\r\n")
time.sleep(2)
output = s.recv(16384).decode(class="hljs-string">'ascii', errors=class="hljs-string">'ignore')
print(class="hljs-string">"\n--- Output ---")
print(output)
print(class="hljs-string">"--------------\n")
s.close()
if __name__ == class="hljs-string">"__main__":
solve()