1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| """CodeShell.kr — Time 3 (Stegano, 50p) solver.
The PNG carries a zsteg b1,r,lsb,xy payload whose ASCII header states the setup: three messages encrypted with the SAME pad from byte zero, plus the plaintext of message 1. XORing C1 with the known plaintext recovers the pad; the same pad decrypts C2 and C3.
Usage: uv run python solvers/time3.py """
import re import subprocess from pathlib import Path
PNG = "assets/challenge-images/time-3-stego.png"
def extract_payload(png=PNG): """Pull the R-channel LSB (b1,r,lsb,xy) plane via zsteg.""" out = subprocess.run( ["zsteg", "-e", "b1,r,lsb,xy", png], capture_output=True, check=True, ).stdout return out
def main(): raw = extract_payload() text = raw.decode("latin1") head = text[:4096]
known = re.search(r"KNOWN PLAINTEXT 1 \(ASCII\):\s*\n(.*?)\nCIPHERTEXT 1", head, re.S).group(1) cts = [bytes.fromhex(h) for h in re.findall(r"CIPHERTEXT \d \(hex\):\s*\n([0-9a-f]+)", head)] c1, c2, c3 = cts[0], cts[1], cts[2] p1 = known.encode()
print(f"P1 len={len(p1)} C1={len(c1)} C2={len(c2)} C3={len(c3)}") pad = bytes(a ^ b for a, b in zip(c1, p1))
for name, ct in (("P2", c2), ("P3", c3)): pt = bytes(a ^ b for a, b in zip(ct, pad)) print(f"{name}: {pt!r}")
if __name__ == "__main__": main()
|