$ cat writeup.md…
$ cat writeup.md…
fortid2026
Task: a ~345 MB stored ZIP encoding 7000 root-to-leaf paths as a trie, where directory names are ASCII codes decoding to 770 decoy FortID{...} flags, each path ending in an identical meme PNG. Solution: decode paths via chr(), then discriminate the real flag structurally by finding the single PNG whose tEXt Comment chunk is a length outlier (11171 vs 236 hex chars).
Heard you're a M4st3r H4ck3r, can you retrieve the flag from this archive?
English summary: a ~345 MB ZIP archive is downloaded from Google Drive. It is a classic needle-in-a-haystack misc challenge: the archive hides one real flag among hundreds of plausible decoys, and the challenge text explicitly taunts the naive text-search approach.
The ZIP is stored (compression method = store / uncompressed), so its on-disk
size reflects raw content. unzip -l reveals ~7000 files, all at paths of the
shape:
retrieve/81/117/97/110/116/.../eow.png
Observations:
eow.png ("end of word").FortID{...} flags.pixel, laser, modem, photon, socket, radio with numeric
suffixes).grep / Ctrl-F: phrases telling you that grepping harder will not help, that
Ctrl-F will not save you, that the flag is a lie but the PNG is not, and that
your princess is in another directory.Conclusion: you cannot pick the real flag from the text alone. A structural discriminator is required — which the challenge hints with "the flag is a lie but the png is not".
All 7000 leaf PNGs are the same meme image (290×320, 8-bit palette) depicting a hacker in a haystack captioned "REAL FLAG SOMEWHERE IN HERE". Key facts:
IEND.tEXt chunk whose keyword is Comment and
whose value is a hex string. This per-file random hex defeats de-duplication
and acts as noise.Extract the tEXt Comment value from every PNG and histogram its length:
The single file carrying the oversized comment is the marker that singles out the real flag among the 770 decoys. Decoding that one file's directory path with the same ASCII-code method yields a clean, thematic flag — a Star Wars pun ("Do or do not, there is no try") rendered in leetspeak and punning on the trie directory structure.
unzip -l; note it is stored and
consists of ~7000 retrieve/.../eow.png paths.retrieve/ prefix and /eow.png suffix,
splitting on /, and mapping each integer through chr().FortID{...} decoys and the anti-grep troll sentences;
conclude a structural discriminator is needed.tEXt Comment value from every leaf PNG and compute a length
histogram.FortID{...} flag (the "trie" pun).#!/usr/bin/env python3 import os, struct, zipfile from collections import Counter ZIP = "archive.zip" def decode_path(path: str) -> str: """Trie path -> string: directory names are ASCII codes.""" mid = path.replace("retrieve/", "").replace("/eow.png", "") parts = [x for x in mid.split("/") if x] return "".join(chr(int(x)) for x in parts) def png_text_comments(data: bytes): """Yield (keyword, value) for every tEXt chunk in a PNG byte string.""" assert data[:8] == b"\x89PNG\r\n\x1a\n" i = 8 while i < len(data): (length,) = struct.unpack(">I", data[i:i+4]) ctype = data[i+4:i+8] payload = data[i+8:i+8+length] if ctype == b"tEXt": kw, _, val = payload.partition(b"\x00") yield kw.decode("latin1"), val.decode("latin1") if ctype == b"IEND": break i += 12 + length # 4 len + 4 type + data + 4 crc # 1-2) enumerate + decode all trie paths zf = zipfile.ZipFile(ZIP) leaf_names = [n for n in zf.namelist() if n.endswith("eow.png")] candidates = {n: decode_path(n) for n in leaf_names} print("total leaves:", len(leaf_names)) # 3) survey decoys (do not rely on text to pick the winner) flags = {s for s in candidates.values() if s.startswith("FortID{")} print("unique FortID{...} decoys:", len(flags)) # 4-5) length-outlier on the tEXt Comment value lengths = {} for name in leaf_names: data = zf.read(name) comment = "" for kw, val in png_text_comments(data): if kw == "Comment": comment = val lengths[name] = len(comment) hist = Counter(lengths.values()) print("comment-length histogram:", hist.most_common()) common_len = hist.most_common(1)[0][0] outliers = [n for n, L in lengths.items() if L != common_len] assert len(outliers) == 1, outliers real = outliers[0] # 6) decode the single outlier's path to the real flag (not printed/stored here) print("real path:", real) # print(candidates[real]) # the actual FortID{...} flag
Use this technique when:
eow.png = end of word) — a directory tree used as a trie / data store.chr(int(component)).grep/Ctrl-F → the real flag is NOT findable by text;
look for a structural discriminator.tEXt/Comment carrying per-file random hex is
noise — histogram its length and pick the single outlier.$ cat /etc/motd
Liked this one?
Pro unlocks every complete writeup and expanded API access. $9/mo.
$ cat pricing.md$ grep --similar