CTF中AES解密后字节转字符串报UnicodeDecodeError如何解决
问题解决方法
报错根本原因
- 你当前尝试的seed值错误,解密得到的是随机乱码字节,不符合UTF-8编码规则,直接调用
decode()就会抛出UnicodeDecodeError - 你当前代码只循环测试了1种seed值(毫秒补9位0的情况),几乎不可能命中正确的加密seed,同时存在seed格式、IV类型两个逻辑错误,导致解密结果必然错误
具体修正步骤
1. 修正seed的毫秒位数
原加密代码中str(datetime.now())输出的时间字符串微秒部分为6位数字,不是你代码里写的9位,你补9位0会导致seed和加密时的格式完全不匹配,永远无法生成正确的密钥。
2. 修正IV的类型
AES初始化要求IV为字节类型,你当前代码里写的16 * '\x00'是字符串类型,部分版本的加密库会直接报错,需要改为字节格式:IV = b'\x00' * 16
3. 优化解密结果判断逻辑
不要直接对解密结果调用decode(),先判断解密字节是否符合flag特征(比如CTF常见的flag{前缀),匹配成功后再转字符串输出,避免无效值报错。
4. 扩大爆破范围
如果你确认加密时间的秒级部分是2021-07-06 03:16:51,只需要爆破0~999999的6位微秒值即可。
修正后的示例代码
#! /usr/local/bin/python from Crypto.Cipher import AES import hashlib seedOrg = '2021-07-06 03:16:51.' IV = b'\x00' * 16 mode = AES.MODE_CBC with open('/home/teja_mxx/Desktop/CapStone/encDec/flag.enc.txt', 'rb') as f: encText = f.read() # 爆破6位微秒 for x in range(1000000): milli = f"{x:06d}" seed = seedOrg + milli key = hashlib.sha256(seed.encode('utf-8')).digest() decryptor = AES.new(key, mode, IV=IV) decryptedText = decryptor.decrypt(encText) # 判断是否存在flag前缀,匹配就输出 if b'flag{' in decryptedText: # 去掉末尾填充的0再输出 plaintext = decryptedText.rstrip(b'0').decode('utf-8') print(f"找到正确seed: {seed}") print(f"解密结果: {plaintext}") break
内容的提问来源于stack exchange,提问作者Pavan Teja
相关产品推荐
相关产品推荐

