bash -lc cat > /mnt/data/ctf_solve.py <<'PY'
#!/usr/bin/env python3
import base64, itertools, pathlib, struct, zlib
STD = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
KEY = b"CCB_M4gic_K3y_2026"
def ks(n: int) -> bytes:
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + KEY[i % len(KEY)]) & 0xff
S[i], S[j] = S[j], S[i]
i = j = 0
out = []
for _ in range(n):
i = (i + 1) & 0xff
a = S[i]
j = (j + a) & 0xff
b = S[j]
S[i], S[j] = b, a
out.append(S[((S[i] * S[j] + 0x72) & 0xff)] ^ 0x37)
return bytes(out)
def remove_rc4_layer(path: str) -> bytes:
c = pathlib.Path(path).read_bytes()
return bytes(x ^ y for x, y in zip(c, ks(len(c))))
def add_mapping(mapping, plain_b64: bytes, sub_b64: bytes):
for p, s in zip(plain_b64, sub_b64):
if p == ord('='):
continue
idx = STD.index(p)
if idx in mapping and mapping[idx] != s:
raise ValueError(f"mapping conflict for {chr(p)}")
mapping[idx] = s
def png_crc_ok(data: bytes) -> bool:
if not data.startswith(b"\x89PNG\r\n\x1a\n"):
return False
off = 8
while off + 12 <= len(data):
length = struct.unpack(">I", data[off:off + 4])[0]
typ = data[off + 4:off + 8]
off += 8
if off + length + 4 > len(data):
return False
chunk = data[off:off + length]
crc = struct.unpack(">I", data[off + length:off + length + 4])[0]
if zlib.crc32(typ + chunk) & 0xffffffff != crc:
return False
off += length + 4
if typ == b"IEND":
return True
return False
def decode_with_inverse(inv, sub: bytes) -> bytes:
b64 = bytes(STD[inv[b]] if b != ord('=') else ord('=') for b in sub)
return base64.b64decode(b64, validate=True)
def main():
mapping = {}
add_mapping(mapping, base64.b64encode(pathlib.Path("readme.txt").read_bytes()), remove_rc4_layer("readme.txt.enc"))
text
# Add known file headers to recover more of the shuffled base64 alphabet.
add_mapping(mapping, base64.b64encode(bytes.fromhex("89504e470d0a1a0a0000000d49484452")), remove_rc4_layer("合同扫描件.png.enc"))
add_mapping(mapping, base64.b64encode(bytes.fromhex("ffd8ffe000104a4649460001")), remove_rc4_layer("logo.jpg.enc")[:16])
inv = {v: k for k, v in mapping.items()}
targets = [remove_rc4_layer("flag.txt.enc"), remove_rc4_layer("logo.jpg.enc"), remove_rc4_layer("合同扫描件.png.enc")]
unknown_outputs = sorted((set().union(*map(set, targets)) - set(inv) - {ord('=')}))
missing_indices = [i for i in range(64) if i not in mapping]
best_inv = None
for perm in itertools.permutations(missing_indices, len(unknown_outputs)):
trial = dict(inv)
trial.update(dict(zip(unknown_outputs, perm)))
try:
png = decode_with_inverse(trial, targets[2])
except Exception:
continue
if png_crc_ok(png):
best_inv = trial
break
if best_inv is None:
raise RuntimeError("failed to recover alphabet")
pathlib.Path("flag.txt").write_bytes(decode_with_inverse(best_inv, targets[0]))
pathlib.Path("logo.jpg").write_bytes(decode_with_inverse(best_inv, targets[1]))
pathlib.Path("合同扫描件.png").write_bytes(decode_with_inverse(best_inv, targets[2]))
print(pathlib.Path("flag.txt").read_text())
if name == "main":
main()
PY
chmod +x /mnt/data/ctf_solve.py
cd /mnt/data/ctf_work && zip -q /mnt/data/recovered_files.zip flag.txt logo.jpg '合同扫描件.png' && ls -l /mnt/data/ctf_solve.py /mnt/data/recovered_files.zip
Thought for 7m 3s