跳转至

CPCTF - Bitwise Scrumble Writeup

题目信息

  • 比赛: CPCTF
  • 题目: Bitwise Scrumble
  • 类别: Crypto
  • 难度: 简单
  • 附件/URL: letsbitwise_04aed83f977321dd26f1e7d4d033e271d28a8490f406e37efb45f0606d6f1ae3.py
  • 附件链接: 下载附件 · 仓库位置
  • Flag格式: CPCTF{...}
  • 状态: 已解

Flag

CPCTF{B1twis3_r0t4t10n!_3tim3s}

解题过程

1. 初始侦察/文件识别

  • 题目给了一个 Python 加密脚本和密文:
encrypted_flag : 10aa77170b38758c146245779086332e5e8237430f362d317310124333b999b890043152135
  • 附件核心逻辑如下:
key = "0123456789012109876543210"

textnum = str(bytes_to_long(text.encode()))
first_part = textnum[:25]
second_part = textnum[25:50]
third_part = textnum[50:75]

encrypted_f = format(((f | k) & (f ^ k)), 'x')
encrypted_s = format(((s & k) ^ (s | k)), 'x')
encrypted_t = format((t ^ ((t | k) & k)), 'x')
  • 明文会先被转成一个 75 位十进制整数串,再切成三个 25 位块。
  • 每个块的同一位置都和 key[i] 做一个 bitwise 表达式,输出为一位十六进制字符。

2. 关键突破点一

  • 题目提示说“每个比特执行的操作都是独立的”,因此不需要把 0..9 的十进制数字整体看成复杂对象。
  • 对单个 bit 设明文 bit 为 \(x\),key bit 为 \(y\),逐个写真值表。

第一段

\[ (x \lor y) \land (x \oplus y) \]
x y x OR y x XOR y result
0 0 0 0 0
0 1 1 1 1
1 0 1 1 1
1 1 1 0 0
  • 结果等价于:
\[ x \oplus y \]

第二段

\[ (x \land y) \oplus (x \lor y) \]
x y x AND y x OR y result
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
  • 结果同样等价于:
\[ x \oplus y \]

第三段

\[ x \oplus ((x \lor y) \land y) \]
  • 其中:
\[ (x \lor y) \land y = y \]
  • 因此第三段直接化简为:
\[ x \oplus y \]

3. 关键突破点二

  • 三个加密表达式虽然长得不同,但对每个 bit 来说都等价于:
\[ \mathrm{encrypted\_digit} = \mathrm{original\_digit} \oplus \mathrm{key\_digit} \]
  • XOR 自反,所以解密时再异或同一个 key_digit
\[ \mathrm{original\_digit} = \mathrm{encrypted\_digit} \oplus \mathrm{key\_digit} \]
  • 由于加密输出是十六进制字符,解密时要先把每个字符按 hex nibble 解析:
digit = int(encrypted_nibble, 16) ^ int(key_digit)
  • 对三个 25 位分块分别恢复后拼接,得到原始 75 位十进制整数串。

4. 获取 Flag

  • 恢复出的十进制串是:
118932708239548593070656909407782612255397407903631131065430989999835411325
  • 将这个大整数转回字节串即可得到:
CPCTF{B1twis3_r0t4t10n!_3tim3s}

攻击链/解题流程总结

阅读附件 -> 发现 flag 被转成 75 位十进制串并三等分 -> 对三个 bitwise 表达式写单 bit 真值表 -> 三者都化简为 digit ^ key_digit -> 密文逐位再异或 key -> 拼回十进制整数 -> long_to_bytes 得到 Flag

漏洞分析 / 机制分析

根因

  • 附件中的三个 bitwise 表达式看起来不同,但每个 bit 的真值表完全等价于 XOR。
  • 由于每个十进制数字位置都独立处理,没有跨位扩散、没有随机 IV,也没有不可逆步骤。
  • 因此只要识别等价表达式,就能逐位恢复原始数字。

影响

  • 密文中的每个 hex nibble 都可以独立解密。
  • 不需要爆破 flag,也不需要求解复杂方程。
  • 题目实际退化成了“真值表化简 + XOR 自反”。

修复建议(适用于漏洞类题目)

  • 不要把可逆的简单 bitwise 表达式当作加密方案。
  • 如果要隐藏明文,应使用标准对称加密,并引入密钥、随机 IV / nonce 与认证机制。
  • 自定义混淆至少应避免每个位置完全独立,否则极易被真值表逐位还原。

知识点

  • bitwise 运算的单 bit 真值表
  • XOR 的自反性质:\(a \oplus b \oplus b = a\)
  • 大整数与字节串转换:bytes_to_long / long_to_bytes

使用的工具

  • Go — 按题解思路还原十进制数字并转回字节
  • Python 3 — 编写等价复现脚本

脚本归档

命令行提取关键数据(无 GUI)

go run CTF_Writeups/scripts_go/CPCTF_Bitwise_Scrumble.go

python CTF_Writeups/scripts_python/CPCTF_Bitwise_Scrumble.py

推荐工具与优化解题流程

本题提示已经点明“每个比特独立”,最有效的方法就是写真值表并做布尔表达式化简。

工具对比总结

工具 适用阶段 本题耗时 优点 缺点
真值表 建模 1-3 分钟 直接看出三个表达式都等价于 XOR 需要逐个表达式验证
Go / Python 脚本 解密 秒级 适合逐位处理与大整数转字节 需要注意 hex nibble 解析
盲目爆破 误区 不定 完全没必要,题目是可逆逐位变换

推荐流程

推荐流程:先把三个 bitwise 表达式降到单 bit 真值表 -> 发现都等价于 XOR -> 对密文每个 hex 字符异或对应 key 数字 -> 拼接十进制串 -> 转回字节得到 flag。

工具 A(推荐首选)

  • 安装:Go 或 Python 3
  • 详细步骤
  • 把密文按 25/25/25 切成三段
  • 遍历每段每个位置
  • int(hex_char, 16) ^ int(key[i]) 还原原始十进制数字
  • 拼接 75 位十进制数
  • 转为大整数,再转回 bytes
  • 优势:完全复现加密逆过程,代码短且稳定

工具 B(可选)

  • 安装:任意布尔代数 / 真值表工具
  • 详细步骤:验证三个表达式的真值表均为 XOR。
  • 优势:适合快速确认化简是否正确

评论