i春秋CTF实战:破解Crypto ezxor谜题,从异或迷阵到Flag重现
在CTF(Capture The Flag)竞赛中,密码学(Crypto)题目常常是选手们既爱又恨的挑战。它既考验逻辑思维,也检验对加密算法底层原理的理解。今天,我们将深入剖析一道典型的Crypto题目------"ezxor",结合i春秋平台常见的出题风格,带你一步步揭开这道看似复杂、实则逻辑清晰的异或加密谜题。
一、题目背景:什么是"ezxor"?
"ezxor"这个名字颇具迷惑性------"ez"暗示"easy",而"xor"则直指核心操作:异或(XOR)。然而,正如许多CTF题目一样,表面的"简单"背后往往隐藏着层层嵌套的加密逻辑。
题目提供了一段Python加密脚本和一段PHP解密脚本,目标是还原出原始的flag
。加密过程涉及多个步骤:Base64编码、SM3哈希、随机数生成、位移操作、异或累积等。乍一看眼花缭乱,但只要我们抓住"异或"这一核心线索,就能抽丝剥茧,找到突破口。
二、加密流程深度解析
我们先来梳理Python脚本中的加密逻辑:
1. Flag预处理:Base64编码
python
flag = base64.b64encode(flag[5:-1].encode()).decode()
fg = [flag[i:i+4] for i in range(0, len(flag), 4)]
- 原始flag格式为
flag{...}
,去除前后5个字符后,对中间内容进行Base64编码。 - 编码后的字符串被每4个字符分割成一个片段,便于后续逐段加密。
✅ 考点1:数据编码与分块处理
CTF中常见将flag进行Base64、Hex、URL等编码后再加密,考察选手对编码格式的识别与处理能力。
2. 密钥生成:SM3哈希
python
def generate_key():
random_string = ''.join(random.choice(letters) for i in range(4))
hash_key = sm3_hash(random_string.encode('utf-8')).hex()
return random_string, hash_key
- 生成一个4位小写字母组成的随机字符串作为密钥。
- 使用国密算法SM3计算其哈希值(但实际加密中只用了原始字符串,哈希值未使用)。
✅ 考点2:国密算法SM3的应用
国内CTF平台如i春秋常引入国密算法,考察选手对SM2/SM3/SM4的熟悉程度。本题虽未直接使用哈希值,但其存在增加了干扰。
3. 加密核心:异或累积 + 位移混淆
python
for i, j in enumerate(fg):
k_box = random_num(i, 10000000, 100000000)
for z,t in enumerate(k_box):
shifted_t = t << z
k_box[z] = shifted_t
a = (reduce(xor, k_box)) >> 3 ^ s2n(j) ^ s2n(key[0]) >> 5
a_boxs.append(a)
加密公式可简化为:
ciphertext = (XOR(k_box << shifts) >> 3) ^ s2n(plaintext) ^ (s2n(key) >> 5)
其中:
k_box
是随机生成的整数列表。- 每个元素根据索引左移
z
位,形成位移混淆。 - 所有元素进行异或累积(
reduce(xor, ...)
)。 - 最终结果右移3位,再与明文数字值和密钥右移5位后的值异或。
✅ 考点3:异或的可逆性与累积操作
异或操作满足交换律、结合律,且
a ^ a = 0
,因此具备可逆性。这是解密的关键!尽管加入了位移和随机数,但只要知道
k_box
和key
,就能逆向计算出原始明文。
三、解密思路:逆向推导,逐段还原
PHP脚本已经给出了完整的解密逻辑,我们可以总结出解密步骤:
1. 已知条件
- 密钥
key = 'vyxj'
(由题目或环境给出) k_boxs
和a_boxs
存储在random_numbers.txt
中
2. 逆向公式
由加密公式:
a = (xor_result >> 3) ^ s2n(j) ^ (s2n(key) >> 5)
可得:
s2n(j) = a ^ (xor_result >> 3) ^ (s2n(key) >> 5)
3. 解密流程
- 读取
k_boxs
和a_boxs
- 对每个
k_box
:- 还原位移(但代码中位移已应用在
k_box
中,直接使用即可) - 计算
xor_result = k_box[0] ^ k_box[1] ^ ... ^ k_box[n-1]
- 还原位移(但代码中位移已应用在
- 计算
s2n(key) >> 5
- 代入公式,得到
s2n(j)
- 使用
n2s()
将数值转为字符串 - 所有片段拼接后进行
base64_decode
- 加上
flag{}
格式,得到最终flag
四、CTF考点总结
考点 | 说明 | 难度 |
---|---|---|
✅ Base64编码与解码 | 对flag内容进行编码后再加密,增加识别难度 | ★★☆ |
✅ 异或(XOR)加密原理 | 核心加密操作,考察可逆性理解 | ★★★ |
✅ 位移操作混淆 | 左移/右移增加分析复杂度 | ★★☆ |
✅ s2n / n2s 数值转换 | 字符串与大整数之间的转换,常见于Crypto题 | ★★☆ |
✅ SM3哈希算法 | 国密算法引入,提升题目专业性 | ★★☆ |
✅ 随机数生成与固定种子 | random_num 使用 sample ,若无种子则需爆破 |
★★★(若无密钥) |
✅ 多层嵌套加密 | 多种操作组合,考验逻辑梳理能力 | ★★★★ |
五、实战建议:如何应对类似题目?
- 识别加密模式 :看到
xor
、reduce(xor)
、^
等符号,立即想到"异或可逆"。 - 关注数据分块 :
[flag[i:i+4] for ...]
是典型分组加密,需逐段处理。 - 利用已知密钥 :本题密钥已知(
vyxj
),极大降低难度;若未知,需考虑爆破4位小写字母(26^4 ≈ 45万种)。 - 善用脚本自动化 :编写Python脚本读取
random_numbers.txt
,自动解密。 - 注意数据类型转换 :
s2n
和n2s
是关键,避免数值溢出或编码错误。
六、结语:从"ezxor"看CTF Crypto设计哲学
"ezxor"虽名为"ez",实则通过多层混淆 + 标准算法组合,构建了一个看似复杂的加密系统。它的巧妙之处在于:
- 不依赖高强度算法(如RSA、AES),而是用基础操作堆叠出安全性;
- 考察选手对异或性质的深刻理解;
- 结合国密SM3,体现本土化出题趋势。
在i春秋等平台的CTF比赛中,这类题目屡见不鲜。掌握其核心逻辑,不仅能解出flag,更能提升密码学实战能力。
Flag不是终点,而是理解加密世界的起点。
附:快速解密脚本(Python版)
python
from libnum import n2s
import base64
# 假设从文件读取
k_boxs = [...] # 从random_numbers.txt解析
a_boxs = [...] # 同上
key = 'vyxj'
fragments = []
for i in range(len(a_boxs)):
xor_result = 0
for x in k_boxs[i]:
xor_result ^= x
plain_num = a_boxs[i] ^ (xor_result >> 3) ^ (int.from_bytes(key.encode(), 'big') >> 5)
fragments.append(n2s(plain_num))
base64_flag = ''.join(fragments)
real_flag = 'flag{' + base64.b64decode(base64_flag).decode() + '}'
print(real_flag)
i春秋CTF提示:多刷题、多总结、多复盘,每一个"ez"背后,都是通往高手之路的阶梯。