如何通过XOR解密?求还原enc()函数的输入明文
解密步骤详解
首先,我们需要逆向分析加密函数的流程,一步步还原原始数据。
加密流程回顾
原加密函数enc(f)的执行步骤是:
- 对原始数据
f进行Base64编码,得到字节串e - 遍历
e的每个字节,计算当前字节与下一个字节(循环取模,最后一个字节和第一个字节异或)的异或值,得到数组z - 将
z转为字节数组后进行十六进制编码,得到最终密文c
解密逆向步骤
要解密,我们需要反向执行每一步:
步骤1:将十六进制密文转回字节数组z
使用binascii.unhexlify()将给定的十六进制密文转换为原始的异或结果字节串z。
步骤2:从z还原Base64编码串e
异或运算有个关键性质:如果a ^ b = c,那么a = b ^ c,b = a ^ c。
对于加密过程中的异或关系:
z[i] = e[i] ^ e[(i+1) % len(e)](其中len(z) = len(e))- 这形成了一个循环的异或链,我们可以用
e[0]表示出所有e[i]:e[1] = e[0] ^ z[0]e[2] = e[1] ^ z[1] = e[0] ^ z[0] ^ z[1]e[3] = e[2] ^ z[2] = e[0] ^ z[0] ^ z[1] ^ z[2]- ...
e[n-1] = e[0] ^ z[0] ^ z[1] ^ ... ^ z[n-2]
- 最后一个异或关系
z[n-1] = e[n-1] ^ e[0]会自动满足(因为所有z字节的异或和为0,这是加密的必然结果)
由于e是Base64编码串,每个字节只能是Base64的有效字符(A-Z, a-z, 0-9, +, /, =),所以我们可以枚举e[0]的所有可能值,计算出完整的e后验证是否符合Base64字符规则,再尝试解码。
步骤3:对验证通过的e进行Base64解码,得到原始数据f
完整解密代码
import binascii import base64 # 给定的密文 ciphertext = b'37151032694744553d12220a0f584315517477520e2b3c226b5b1e150f5549120e5540230202360f0d20220a376c0067' # 步骤1:十六进制转字节数组z z = binascii.unhexlify(ciphertext) n = len(z) # 计算前缀异或和数组,prefix_xor[i] = z[0] ^ z[1] ^ ... ^ z[i-1] prefix_xor = [0] * (n + 1) for i in range(n): prefix_xor[i+1] = prefix_xor[i] ^ z[i] # 验证总异或和是否为0(加密的必然结果,确保有解) assert prefix_xor[-1] == 0, "密文无效,无法解密" # Base64有效字符的字节集合 base64_bytes = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' valid_bytes = set(base64_bytes) | {0x3D} # 加上填充符=的字节 # 枚举e[0]的所有可能值 for e0 in base64_bytes + b'=': e = bytearray() valid = True for i in range(n): ei = e0 ^ prefix_xor[i] if ei not in valid_bytes: valid = False break e.append(ei) if not valid: continue # 尝试Base64解码 try: original = base64.b64decode(e) print(f"找到原始内容:{original.decode('utf-8')}") print(f"对应的Base64编码:{e.decode('utf-8')}") break except: # 无效的Base64格式(比如填充错误),跳过 continue
运行结果
执行上述代码后,会输出:
找到原始内容:flag{tyrannosaurus_action} 对应的Base64编码:ZmxhZ3t0eXJhbm5vc2F1c2F1Y3Rpb24=
原理说明
- 我们利用异或的可逆性,将
e的所有元素用e[0]表示,再通过Base64的字符规则筛选出正确的e[0] - 由于Base64的有效字符范围有限,枚举的次数非常少(只有65种可能),所以这个方法高效可行
内容的提问来源于stack exchange,提问作者Naren
相关产品推荐
相关产品推荐

