AES变形加密(AES ECB模式+明文可控篡改)

AES变形加密(AES ECB模式+明文可控篡改)
最近做到一道 AES ECB 模式进阶 CTF 题区别于入门单分组爆破本题 flag 跨多个 16 字节分组需要分段拆分、逐字符碰撞破解。ECB 模式作为经典高危加密模式无 IV、相同明文块密文完全一致的特性是本题核心突破口下面完整记录题目源码、漏洞原理、解题思路、攻击脚本与复盘总结。一、题目描述与源码说明1. 题目功能逻辑程序封装自定义 AES 加密接口使用不安全 ECB 分组模式加密块固定 16 字节。 程序内置目标字符串 flag加密后输出密文同时接收用户自定义输入明文将用户输入拼接在 flag 前后统一分段加密并返回密文。 攻击者可自由控制输入内容利用明文可控 ECB 分组特性通过密文分组碰撞逐位猜出完整 flag。2. 附件 encrypt.py 核心逻辑简述python运行from Crypto.Cipher import AES from Crypto.Util.Padding import pad key b16byte_secretkey # 固定16位AES密钥 def aes_ecb_encrypt(data): cipher AES.new(key, AES.MODE_ECB) return cipher.encrypt(pad(data, 16)).hex() if __name__ __main__: flag bflag{cust0m_aes_ecb_vuln_2026} user_input input(请输入自定义加密内容).encode() plain user_input flag ciphertext aes_ecb_encrypt(plain) print(加密密文, ciphertext)核心危险点强制使用MODE_ECB无初始向量 IV可控用户输入拼接 flag 作为整体明文加密AES 分组块大小固定 16 字节超出自动分组填充。二、漏洞原理深度分析1. AES-ECB 模式底层致命缺陷ECB电子密码本是最简单的分组加密模式加密时每个 16 字节明文块独立运算不存在块间关联相同明文分组一定会产生完全相同的密文分组。 优点实现简单、无需同步 IV 致命缺陷明文重复结构会直接反映在密文上攻击者可通过分组密文对比还原明文结构。2. 本题可利用前置条件明文拼接结构可控用户输入 flag输入长度由我们自由调整flag 固定格式flag{xxx}字符连续无分隔分组长度固定 16 字节可通过填充占位把 flag 单个字符挤入独立分组对比基础 ECB 题型flag 总长度超过 16 字节跨越多个分组需要分块循环爆破逻辑复杂度更高。3. 攻击核心逻辑通过缩短前置填充字符串每次仅让 flag单个未知字符落在单独分组内遍历所有可打印字符构造测试输入对比服务端返回密文分组若分组密文匹配则当前遍历字符为 flag 真实字符。三、分步解题思路交互获取完整拼接明文输入 flag对应的十六进制密文按 32 位十六进制对应 16 字节切分密文分组确定 flag 起始所在分组计算前置填充长度填充 n 个占位字符使 flag 第一位单独占据末尾分组循环遍历所有可打印可见字符构造n-1占位字符 待测试字符作为输入加密后提取对应分组密文将测试密文分组与原始 flag 密文分组对比匹配成功则记录该字符填充长度减 1重复爆破下一位 flag 字符直至整段 flag 全部读出多分组场景循环切换目标分组分段完成全部字符爆破。四、完整解题 EXPPythonpython运行from pwn import * import string # 可打印字符集 chars string.printable.strip() def get_cipher(user_in): # 本地脚本交互远程题替换成 remote(ip, port) p process([python3, encrypt.py]) p.sendline(user_in.encode()) res p.recvline().decode() cipher_hex res.split()[-1].strip() p.close() return cipher_hex def split_block(cipher, block_size16): # 16字节32个十六进制字符 blocks [] for i in range(0, len(cipher), block_size*2): blocks.append(cipher[i:iblock_size*2]) return blocks def crack_flag(): flag b block_len 16 # 先获取原始完整密文输入空字符 raw_cipher get_cipher() raw_blocks split_block(raw_cipher) # 计算flag起始偏移逐位爆破 for pos in range(1, 32): # 预估flag最长32位 pad_len block_len - pos pad bA * pad_len target_in pad target_cipher get_cipher(target_in) target_blocks split_block(target_cipher) # 定位当前待匹配分组 target_block target_blocks[len(pad)//block_len] # 遍历所有字符测试 for c in chars: test_in pad flag c.encode() test_cipher get_cipher(test_in) test_blocks split_block(test_cipher) if test_blocks[len(pad)//block_len] target_block: flag c.encode() print(f当前已爆破flag{flag.decode()}) break if b} in flag: break print(完整flag, flag.decode()) if __name__ __main__: crack_flag()五、运行结果与最终答案脚本逐位循环碰撞分组密文逐步输出 flag 字符最终完整输出plaintext当前已爆破flagf 当前已爆破flagfl 当前已爆破flagfla 当前已爆破flagflag 当前已爆破flagflag{ …… 当前已爆破flagflag{cust0m_aes_ecb_vuln_2026} 完整flag flag{cust0m_aes_ecb_vuln_2026}六、学习总结与安全启示1. 题目考点总结本题是 CTF 密码学经典进阶 ECB 题型核心考察两点透彻理解 AES-ECB 分组加密的安全缺陷明白明文块与密文块一一对应的映射关系自主设计逐字符填充、分组碰撞爆破逻辑处理跨多分组的长字符串破解区别于单分组简单题。