Deadgame2
Deadgame2
Platform: Sekai2026 | Category: Misc | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-06-27 | Status: Solved Techniques: chat_fragment_recovery, md5_verification, mpq_extraction, replay_event_decoding, tracker_coordinate_plotting
Summary
Task: analyze a StarCraft II SC2Replay MPQ archive with chat fragments and hidden position-based data. Solution: decode replay messages, plot SUnitDiedEvent coordinates from tracker events, and rebuild the flag.
Recon
Port scan
bash read-only • copy allowednmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
sekai2026| ID:20260627_sekai2026_deadgame2 - Tags: starcraft_ii, sc2replay, mpq_archive, game_replay, s2protocol, coordinate_plotting
- Indicators: SC2Replay file is an MPQ archive, replay.message.events contains partial flag chat, chat hint says position is crucial, SUnitDiedEvent coordinates draw readable text
- Source:
20260627_sekai2026_deadgame2.md
Foothold
Vulnerability / Misconfiguration
- chat_fragment_recovery
- md5_verification
- mpq_extraction
- replay_event_decoding
- tracker_coordinate_plotting
bash read-only • copy allowed<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
bash read-only • copy allowedsudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
bash read-only • copy allowed<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- chat_fragment_recovery
- md5_verification
- mpq_extraction
- replay_event_decoding
- tracker_coordinate_plotting
- Tags: starcraft_ii, sc2replay, mpq_archive, game_replay, s2protocol, coordinate_plotting
Original Writeup
<details><summary>Click to expand original content</summary>Description
The provided archive was misc_deadgame2.tar.gz, containing misc_deadgame2/DeadGame2.SC2Replay.
The replay is a StarCraft II MPQ archive. Metadata identified map title Tunguska, GameVersion 5.0.15.96999, and Base96999.
The goal was to recover the complete SeKaiCTF{...} flag from replay data. The visible chat gave most of the flag, while a hint about positions pointed to hidden text encoded in tracker coordinates.
Tools
python3.11mpyqfor extracting the MPQ replay archives2protocolfor decoding StarCraft II replay streamsPillowfor rendering coordinate plots
The local environment used vendor311 packages because the bundled s2protocol code was compatible with Python 3.11.
Extraction and Parsing
After unpacking the challenge archive, treat DeadGame2.SC2Replay as an MPQ archive and extract the replay streams. The important files were:
replay.message.events- in-game chat messagesreplay.tracker.events- unit and positional tracker events
The message stream can be decoded directly with the matching/latest bundled s2protocol protocol module:
python read-only • copy allowed#!/usr/bin/env python3 from pathlib import Path from s2protocol.versions import protocol97364 as protocol data = Path("extract/replay.message.events").read_bytes() for event in protocol.decode_replay_message_events(data): if event.get("_event") != "NNet.Game.SChatMessage": continue text = event["m_string"].decode("utf-8", "replace") if text: print(event["_gameloop"], event["_userid"]["m_userId"], text)
Chat Fragment Recovery
The decoded chat stream contained direct flag fragments plus the key hint:
| Gameloop | User | Message |
|---|---|---|
| 4662 | 0 | SeKaiCTF{lol |
| 7428 | 0 | Want more? Let me be kind enough to give you a hint - in this interstellar war, everyone's "position" is crucial! |
| 11697 | 0 | Chinese hint, translated: Mysterious Eastern text: you should also send some flag out! |
| 11897 | 1 | _fl2g_ |
| 72569 | 0 | Attention!!! |
| 73100 | 1 | _ |
| 73312 | 1 | _ |
| 73588 | 1 | _ |
| 73864 | 1 | GG |
| 73931 | 1 | } |
This recovered the skeleton:
text read-only • copy allowedSeKaiCTF{lol_fl2g_???_???_???_GG}
The word position in the hint is the important clue: the missing chunks are not another chat encoding layer, but text drawn by positions in tracker events near the underscore-only chat messages.
Tracker Coordinate Plotting
In replay.tracker.events, the useful data is in NNet.Replay.Tracker.SUnitDiedEvent events. Filter events where m_killerPlayerId == 1 around the three underscore chat gameloops and plot (m_x, m_y) coordinates.
python read-only • copy allowed#!/usr/bin/env python3 from pathlib import Path from s2protocol.versions import protocol97364 as protocol TARGETS = { 73086: "EN", 73290: "TARO", 73563: "HERO", } groups = {g: [] for g in TARGETS} data = Path("extract/replay.tracker.events").read_bytes() for event in protocol.decode_replay_tracker_events(data): if event.get("_event") != "NNet.Replay.Tracker.SUnitDiedEvent": continue if event.get("m_killerPlayerId") != 1: continue gameloop = event.get("_gameloop") if gameloop in groups: groups[gameloop].append((event["m_x"], event["m_y"])) for gameloop, label in TARGETS.items(): pts = groups[gameloop] xs = [x for x, _ in pts] ys = [y for _, y in pts] print(f"{gameloop}: {label} points={len(pts)} bbox=x[{min(xs)},{max(xs)}], y[{min(ys)},{max(ys)}]") occupied = set(pts) for y in range(max(ys), min(ys) - 1, -1): print("".join("#" if (x, y) in occupied else "." for x in range(min(xs), max(xs) + 1))) print()
The three bursts immediately before the underscore chat messages produced readable coordinate plots:
| Gameloop | Points | Bounding box | Text |
|---|---|---|---|
| 73086 | 48 | x[115,129], y[152,161] | EN |
| 73290 | 82 | x[106,134], y[140,148] | TARO |
| 73563 | 83 | x[112,142], y[115,125] | HERO |
The helper script show_tracker_chunks.py renders these same grids and writes tracker_missing_chunks.png for visual confirmation.
Flag Reconstruction
Combine the visible chat fragments with the tracker text chunks. The underscore-only chat messages mark the separators around the hidden words:
text read-only • copy allowedSeKaiCTF{lol _fl2g_ EN _ TARO _ HERO _ GG }
So the reconstructed flag is:
text read-only • copy allowedSeKaiCTF{REDACTED}
Verification
The provided MD5 check matches the reconstructed flag:
</details>python read-only • copy allowed#!/usr/bin/env python3 import hashlib flag = "SeKaiCTF{REDACTED}" assert hashlib.md5(flag.encode()).hexdigest() == "0b95495176f49f2dab8a2d9c26a41ecc" print(flag)
signed by XESXOR