ECB Pattern Leakage
Summary
一道 AES-ECB 弱密钥爆破题目。附件名 otp_07.zip 是干扰项,真实加密方式为 AES-ECB(电子密码本模式)。通过构建”常见单词+分隔符+特殊字符”模式的 16 字节密钥字典,逐条尝试 AES-ECB 解密,最终爆出密钥 VERY_SECRET_KEY! 并获得 flag。
Solution
1. 题目分析
题目名 “ECB Pattern Leakage” 直接提示了加密模式:
- ECB = AES-ECB(电子密码本模式),无 IV,加密解密仅依赖 16 字节密钥
- Pattern Leakage = ECB 的经典弱点:相同明文块产生相同密文块,泄露数据结构
附件 otp_07.zip 解压得到 ciphertext.bin,长度 80 字节 = 5 个 AES 块(80 / 16 = 5),进一步确认是 AES 加密。
密文 hex: 97c266c5b1c929e1ac07ccf592599dd8 39677b7c0a37f1772c158da16cd0e9a4 31324b424c712cbf200443c4ec7fc624 92b016e07838e966cfde3f6f93903698 84163f757a2ab28337aefa7aeb72e087核心思路:CTF 中常硬编码弱密钥,密钥由「常见英文单词 + 分隔符(_、- 等)+ 特殊字符」组合成恰好 16 字节。需要系统性地生成候选密钥字典并逐一爆破。
2. 字典生成策略
字典由以下来源合并,共生成约 838 万 个 16 字节候选密钥:
来源一:常见密码词 + 填充补齐
收集约 150 个常见密码关键词(secret, key, password, admin, master, flag, aes 等),包含三种大小写变体(原形 / 全大写 / 首字母大写)。对不足 16 字节的,用 0、!、#、 、*、@、$、1、_ 填充到 16 字节。
来源二:单词组合模式
- 28 个基础词库:
very,secret,key,pass,flag,code,safe,lock,open,hard,soft,test,back,hide,deep,blue,gold,red,hot,big,old,new,raw,aes,ctf,crypto,password,admin,root,master,super - 分隔符:
_、-、.、+、@、# - 双词 / 三词组合 × 大小写变体 × 特殊字符后缀 → 海量 16 字节候选
来源三:数字编号模式
如 key0000 ~ key9999,aes0000 ~ aes9999 等,填充到 16 字节。
来源四:题目特定猜测
根据 otp_07 命名生成针对性候选(OTP_KEY_007!!!、ECB_KEY_007!!!、MASTER_KEY_007! 等)。
3. 爆破脚本
from Crypto.Cipher import AESimport re
ct = open("otp_07_extracted/ciphertext.bin", "rb").read()
def pkcs7_unpad(data): pad_len = data[-1] if 1 <= pad_len <= 16 and data[-pad_len:] == bytes([pad_len]) * pad_len: return data[:-pad_len] return data
candidates = set()
# ——— 来源一:常见密码 + 填充 ———common = [ "very", "VERY", "Very", "secret", "SECRET", "Secret", "key", "KEY", "Key", "pass", "PASS", "Pass", "flag", "FLAG", "Flag", "admin", "Admin", "ADMIN", "master", "MASTER", "Master", "super", "SUPER", "Super", "aes", "AES", "Aes", "ctf", "CTF", "Ctf", "crypto", "CRYPTO", "Crypto", "password", "PASSWORD", "very_secret", "VERY_SECRET", "super_secret", "SUPER_SECRET", "master_key", "MASTER_KEY", "top_secret", "TOP_SECRET",]for pw in common: wb = pw.encode() if len(wb) == 16: candidates.add(wb) for pad in [b"0", b"!", b"#", b" ", b"*", b"@", b"$", b"1", b"_"]: candidates.add(wb.ljust(16, pad))
# ——— 来源二:单词组合 ———base = [ "very", "secret", "key", "pass", "flag", "code", "safe", "lock", "open", "hard", "soft", "test", "back", "hide", "deep", "blue", "gold", "red", "hot", "big", "old", "new", "raw", "aes", "ctf", "crypto", "password", "admin", "root", "master", "super",]seps = ["_", "-", ".", "+", "@", "#"]specials = ["!", "@", "#", "$", "%", "&", "*", "1", "0"]
def variants(w): return {w, w.upper(), w.capitalize()}
for w1 in base: for v1 in variants(w1): for w2 in base: for v2 in variants(w2): for sep in seps: b = v1 + sep + v2 if len(b) > 14: continue for w3 in base: for v3 in variants(w3): combo = b + sep + v3 if len(combo) > 16: continue if len(combo) == 16: candidates.add(combo.encode()) for s in specials: full = (combo + s)[:16] if len(full) == 16: candidates.add(full.encode()) for s in specials: full = b.ljust(16, s[-1] if s else "!") full = full[:16] if len(full) == 16: candidates.add(full.encode())
# ——— 来源三:数字编号 ———for prefix in ["key", "KEY", "Key", "aes", "AES", "Aes"]: for i in range(10000): key = f"{prefix}{i:04d}".encode() candidates.add(key.ljust(16, b"0")) candidates.add(key.ljust(16, b"!"))
# ——— 爆破 ———for key in candidates: try: cipher = AES.new(key, AES.MODE_ECB) pt = cipher.decrypt(ct) text = pt.decode("ascii") except: continue if not any(kw in text for kw in ["CTF", "flag", "FLAG", "Flag"]): continue clean = pkcs7_unpad(pt) print(f"[+] Key: {key!r}") print(f"[+] Plaintext: {clean.decode()}") match = re.search(rb"flag\{[^}]+\}", clean) if match: print(f"[+] Flag: {match.group().decode()}") break4. 运行结果
[*] 总候选密钥数: 8380467[+] Key: b'VERY_SECRET_KEY!'[+] Plaintext: CTF{SECRET_FLAG:flag{dt6g0oomiiiyqb2jtbm93h5dsi07alzp}}END_OF_FLAG[+] Flag: flag{dt6g0oomiiiyqb2jtbm93h5dsi07alzp}在第约 120 万个候选时命中,密钥与 otp_02 相同(均为 VERY_SECRET_KEY!),但 flag 不同,说明同一套题用了统一密钥、不同明文。
Flag
flag{dt6g0oomiiiyqb2jtbm93h5dsi07alzp}总结
| 考点 | 说明 |
|---|---|
| AES-ECB 模式 | 电子密码本,无 IV,解密仅需密钥 |
| 弱密钥爆破 | 密钥由常见单词组合成 16 字节,可用字典爆破 |
| 文件名干扰 | otp_07 是误导,实际与 OTP 无关 |
| PKCS#7 填充 | 用于验证解密正确性 |
关键教训:题目名是最可靠的线索(“ECB Pattern Leakage”),附件名往往是干扰项。CTF 中弱密钥常遵循 WORD_SEP_WORD_SPECIAL 模式,系统性地生成这种字典可覆盖绝大多数情况。
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 76 天
部分内容可能已过时