这是ctf题目,分析这个文件夹中的文件给我flag和write

創建於:2026年4月28日

使用 GPT-5.5 Thinking 回答 Chat01

問題

粗心的员工下载了奇怪的程序,运行后公司的文件全被加密了,请你恢复.zip

这是ctf题目,分析这个文件夹中的文件给我flag和write

思考

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

回答

拿到了。

Flag:

text
flag{1jn90vkvljgemd0escrqcujlhk9k4dpt}

恢复文件与脚本:

Writeup

题目给了一个 UPX 壳的 ELF 程序 distorted,以及若干 .enc 文件。静态看字符串能发现:

text
/dev/urandom %s.enc CCB_M4gic_K3y

程序逻辑大致是:

  1. 生成一张随机打乱的 Base64 字符表;
  2. 将原文件内容用这张随机表做 Base64 编码;
  3. 再用一个 RC4-like 流加密变体异或编码结果;
  4. 输出为 原文件名.enc

关键点是同一次运行里随机 Base64 表相同,而且 readme.txtreadme.txt.enc 同时存在,可以做已知明文攻击。

逆出来的 RC4-like key 是:

text
CCB_M4gic_K3y_2026

RC4-like PRGA 的核心不是标准 S[S[i]+S[j]],而是:

python
keystream = S[((S[i] * S[j] + 0x72) & 0xff)] ^ 0x37

用这个 keystream 先异或 .enc,可以去掉第二层加密,得到“随机表 Base64”。
然后用 readme.txt 的标准 Base64 与去掉 RC4 后的 readme.txt.enc 对照,恢复大部分随机 Base64 字符表。

剩余少数字符用文件头补齐:

text
PNG: 89 50 4E 47 0D 0A 1A 0A ... JPG: FF D8 FF E0 00 10 4A 46 49 46 ...

最后用 PNG chunk CRC 校验枚举剩余映射,确定唯一正确字符表,解出 flag.txt.enc

text
flag{1jn90vkvljgemd0escrqcujlhk9k4dpt}

分享這個問答