2026-07-12 20:22:15 +01:00

90 lines
3.0 KiB
Python

#!/usr/bin/env python3
import os
import sys
import zipfile
LAYER_COUNT = 5
OUTER_NAME = "matryoshka.png"
FLAG_TEXT = "CTF{h3ll0_d3xt3r_m0rg4n_m4try0shk4!}"
def append_file_to_png(png_path: str, extra_path: str, out_path: str):
with open(png_path, "rb") as f_png, open(extra_path, "rb") as f_extra, open(out_path, "wb") as f_out:
f_out.write(f_png.read())
f_out.write(f_extra.read())
def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <folder_with_5_pngs>")
sys.exit(1)
input_dir = sys.argv[1]
if not os.path.isdir(input_dir):
print(f"[-] Not a directory: {input_dir}")
sys.exit(1)
# Collect PNGs and sort them for deterministic order
pngs = [f for f in os.listdir(input_dir) if f.lower().endswith(".png")]
pngs.sort()
if len(pngs) < LAYER_COUNT:
print(f"[-] Need at least {LAYER_COUNT} PNG files in {input_dir}, found {len(pngs)}")
sys.exit(1)
# Use exactly the first LAYER_COUNT PNGs
pngs = pngs[:LAYER_COUNT]
print("[+] Using these PNGs as layers (outermost -> innermost):")
for i, name in enumerate(pngs, start=1):
print(f" Layer {i}: {name}")
os.makedirs("build", exist_ok=True)
# 1) Create innermost: flag.txt -> zipN -> imageN_with_zip
flag_path = os.path.join("build", "flag.txt")
with open(flag_path, "w") as f:
f.write(FLAG_TEXT + "\n")
# Innermost index
innermost_idx = LAYER_COUNT - 1
innermost_png_original = os.path.join(input_dir, pngs[innermost_idx])
zip_path = os.path.join("build", f"layer{LAYER_COUNT}.zip")
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as z:
z.write(flag_path, arcname="flag.txt")
embedded_png_path = os.path.join("build", f"layer{LAYER_COUNT}_embedded.png")
append_file_to_png(innermost_png_original, zip_path, embedded_png_path)
inner_file = embedded_png_path # this will be zipped into the next outer layer
# 2) Build outer layers (N-1 down to 1)
for layer in range(LAYER_COUNT - 1, 0, -1):
png_name = pngs[layer - 1]
png_original = os.path.join(input_dir, png_name)
# zip containing the previous (inner) embedded image
zip_path = os.path.join("build", f"layer{layer}.zip")
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as z:
# Store it under a generic name inside the zip
z.write(inner_file, arcname=f"inner_layer.png")
# append that zip to this layer's original PNG
embedded_png_path = os.path.join("build", f"layer{layer}_embedded.png")
append_file_to_png(png_original, zip_path, embedded_png_path)
inner_file = embedded_png_path
# 3) Copy the outermost embedded PNG as final challenge file
with open(inner_file, "rb") as f_in, open(OUTER_NAME, "wb") as f_out:
f_out.write(f_in.read())
print(f"[+] Created final challenge file: {OUTER_NAME}")
print("[+] Intermediate files are in the build/ directory.")
if __name__ == "__main__":
main()