arrow_backUS Cyber Games 2026
Miscmedium

Up to Date

by Pavel Knespl (capyplivl)

A Zen-C source file is split into 5 stride chunks, wrapped in a tiny TCP-style protocol, mixed with noise packets, shuffled, and hex-encoded into output.txt. A genuine packet is the only one whose payload starts with its own sequence id, so that rule filters the noise. The recovered source XORs a byte array with 0x42 to print the flag.

Solve

  1. A valid packet is [ZN][seq:1][len:1][payload:len] where the payload begins with str(seq). Noise is either a bad magic or ZN with a payload that does not start with its seq. Scan for ZN, keep packets where seq < 5 and payload[0] == str(seq), then de-stride with zenc[j] = chunk[j % 5][j // 5].
data = bytes.fromhex(open("output.txt").read().strip())
chunks = {}
for i in range(len(data) - 4):
    if data[i:i+2] != b"ZN":
        continue
    seq, ln = data[i+2], data[i+3]
    payload = data[i+4:i+4+ln]
    if len(payload) == ln and seq < 5 and payload[:1] == str(seq).encode():
        chunks.setdefault(seq, payload[1:].decode("utf-8", "replace"))

out = []
for idx in range(max(len(c) for c in chunks.values())):
    for s in range(5):
        if idx < len(chunks[s]):
            out.append(chunks[s][idx])
print("".join(out))
  1. The reconstructed source is:
fn main() -> void {
    let code = [0x11, 0x14, 0x0b, 0x00, 0x05, 0x10, 0x39, 0x38, 0x71, 0x2c,
                0x1d, 0x21, 0x1d, 0x34, 0x73, 0x20, 0x71, 0x1d, 0x26, 0x23,
                0x75, 0x23, 0x1d, 0x25, 0x30, 0x76, 0x2f, 0x3f];
    let key = 0x42;
    for b in code { print(char(b ^ key)); }
}
  1. XOR each byte with 0x42:
code = [0x11,0x14,0x0b,0x00,0x05,0x10,0x39,0x38,0x71,0x2c,0x1d,0x21,0x1d,0x34,
        0x73,0x20,0x71,0x1d,0x26,0x23,0x75,0x23,0x1d,0x25,0x30,0x76,0x2f,0x3f]
print("".join(chr(b ^ 0x42) for b in code))

Flag: SVIBGR{z3n_c_v1b3_da7a_gr4m}