首页
社区
课程
招聘
[原创]第七题「戌时·暗能潜流」解析
发表于: 2026-8-21 14:22 16

[原创]第七题「戌时·暗能潜流」解析

2026-8-21 14:22
16

(FLAG 密文实际是一整行,共 144 个十六进制字符,此处为排版折行。)

做密码分析题,第一件事不是看数据,是把自然语言描述翻译成可利用的数学约束。逐条拆:

关键推论:

"模16循环偏移 + 固定位置重排"意味着:密文的每一个十六进制位,都等于某一个明文半字节加上一个固定常数。

形式化:存在置换 π 和常量数组 k,使得 C[i] = (P[π(i)] + k[i]) mod 16

这个模型极强——它把破解降级成了"求一个置换 + 一组常量",可以纯靠列比对解出来,不需要爆破。

比值不固定 → 存在填充(padding)

反过来推:如果"每个字符固定产出 4 个十六进制位",那么

即:明文按 3 字符对齐填充,每 3 字符产出 12 个十六进制位。这是唯一自洽的解释。

FLAG 密文 144 位 ÷ 12 = 12 块,对应填充后 36 个字符。

因为算法是确定性的,如果分块独立(类似 ECB),那么相同的 3 字符块在任何位置都会产生相同的 12 位密文。于是去 FLAG 里搜已知密文的 12 位块:

这一条命中同时证明了三件事:

第 3 点尤其宝贵:它直接排除了 CBC 式链接和"随位置递增的偏移",让每块可以单独求解。

把 FLAG 切成 12 块:

块 11 长得和别人完全不一样(22332235 这种规整的低值),先记下,后面处理。

把 4 组已知明文的第一块(都是完整的 3 字符块)按位摊开:

pos 1 / 4 / 9 恒为 4;pos 6 / 7 / 11 恒为 5

再拿 FLAG 的 11 个正常块交叉验证 —— 全部符合。6 个固定位,6 个数据位

数据位是 {0, 2, 3, 5, 8, 10},正好 6 个,而 3 个 ASCII 字符 = 6 个半字节。一一对应,信息量刚好守恒,验证了"膨胀率 = 每半字节 1 个十六进制位 + 1 个标记位"的模型。

这一步的关键推理:为什么这 6 个位是"结构性常量"而不是巧合?
因为如果它们承载明文数据,4 组差异极大的明文(TLU / Hel / 202 / abc,高半字节分别是 5,4,5 / 4,6,6 / 3,3,3 / 6,6,6)不可能全都撞成同一个值。
4 出现 3 次、5 出现 3 次的 3:3 结构,强烈暗示它们是"高半字节标记"和"低半字节标记"——即"字节编码"这一步的产物。

可打印 ASCII 字符(0x20–0x7E)的高半字节只能是 2..7,只有 6 种取值;而低半字节 0..F 全都可能。

所以:承载高半字节的密文位,其取值必然被压缩在一个宽度 ≤ 6 的连续窗口内(模 16 意义下)。

统计 FLAG 的 11 个正常块,每个数据位的取值集合:

这是一个非常好用的通用技巧:当明文是可打印 ASCII 时,高半字节的熵远低于低半字节。只需统计每一列的取值分布,就能把"高位列"和"低位列"分开,完全不需要已知明文。

结论:pos2 / pos3 / pos10 承载 3 个高半字节;pos0 / pos5 / pos8 承载 3 个低半字节。

窗口都落在 8..C,而高半字节值域是 2..7,差值 = +5。用已知明文核对:

卡住了。 两组对、两组错。

这里我先走了一段弯路,值得完整记下来,因为它是这类题最典型的思维陷阱。

当时的(错误)推理链:

这个假设是怎么被证伪的:

Helloabcd! 长度都是 5,扰动必然相同。可实测:

同一长度却要求两个不同的扰动量 → 假设直接矛盾,证伪

同样的方法把 pos0pos8 也试了一遍,全都在"同长度双样本"上自相矛盾。

教训(很重要)
当一个"合理的解释"能覆盖部分样本时,人会本能地给它打补丁(加一个自由参数)来解释剩下的。
正确做法是找一组能同时约束该参数的样本去证伪它。
这里 Hello / abcd! 同为长度 5,就是天然的"对照组"。只要有两个同长度样本,任何'只与长度有关'的自由参数都会被立刻锁死。

另一个反证同样致命:如果 pos0 = hi(c0) + 常量,那 FLAG 11 个块的 pos0 值必须落进 6 个格子里;但实测 pos011 个互不相同的值——鸽笼原理直接排除。这也提示 pos0 根本不是高半字节列。

排除了扰动之后,矛盾就必须从结构上解释:既然 pos2 / pos3 / pos10 是三个高半字节,而 pos3 / pos10 都能对上、只有 pos2 对不上,那问题只可能出在**"哪个字符是 c0"** 上——也就是顺序

回头看那些"异常"的第 2 块:

规整的低值 2233/2235 出现在块的开头,而"看起来像真实数据"的部分在块的末尾。如果填充字符是加在明文尾部的,填充产物本该出现在块尾。它出现在块首 → 顺序被翻转了

R = S[::-1](明文整体反转),再按 3 字符分块:

重新核对 pos2 = hi(c0) + 5

4/4 全中! 顺带 pos3pos10 在新顺序下依然成立:

之前"对了两组"是因为 TLUULT202620 恰好高半字节相同或对称(T/U 同为 5,2/0/6 同为 3),属于假阳性巧合

教训202TLU 这种字符高位高度重复的样本,会掩盖顺序错误。
做已知明文分析时,优先信任字符差异大的样本(这里是 Hello / abcd!),它们的信息量更高、更容易暴露结构错误。

顺序修正后,把 pos0 / pos5 / pos8 与反转块的 3 个低半字节对齐求差:

12/12 全部等于 4,无一例外,且与输入长度完全无关。

至此主体变换彻底还原:高半字节 +5,低半字节 +4,全都是模 16。没有任何长度相关的扰动。

正常块搞定后,只剩"不足 3 字符"的尾块。它就是题面说的固定摘要扰动——形态只由"剩余字符个数"(即输入长度 mod 3)决定,与内容无关,完美对应提示"摘要扰动过程只与输入长度有关"。

样本(反转后剩下的 2 个字符):

逐段对照(a = 第 1 个剩余字符,b = 第 2 个):

注意第 2 个字符的 hi / lo 顺序是反的(先 hi 后 lo),与正常块中 c2 的排布风格一致——这正是"固定位置重排"的延续。

对 FLAG 尾块 22332235A4B3 应用此规则:

FLAG 的第一个字符是 f —— 因为反转后的最后一块,对应的正是原文的开头。符合 flag{...} 预期。

TLU 长度 3,正好整除,不产生尾块(密文只有 12 位)。所以填充只在需要时添加。

hi(c) = c >> 4lo(c) = c & 0xF,全部运算模 16:

用一句话记:

c0 的低位在最前,c0 的高位紧随;c2 的高低位分居 3、5 号位;c1 的高低位被挤到 8、10 号位;45 各三个当填充标记。

现在回头把还原出的规则,映射回题面声称的 5 个步骤,就能看清设计者的意图。

每个字符被拆成 2 个半字节,各自扩展成 1 个"带标记的字节":

这就解释了为什么密文里恰好有 3 个 4 和 3 个 5:3 个字符 × (1 低 + 1 高)。膨胀率 = 1 字符 → 2 字节 → 4 个十六进制字符,与观测完全一致。

这就是"模 16 循环偏移"的全部内容——两个常量,4 和 5,与位置、长度、内容都无关

值得注意的是:偏移量和标记值相同(低位标记 4 / 偏移 4,高位标记 5 / 偏移 5)。所以整个编码可以更优雅地写成:

这是它伪装成"哈希/密文"的关键:偏移让 hi2..7 搬到 7..C,于是密文里到处是 ABC 这类高位字符,看起来"很随机",实际上熵一点没增加。

编码后,一个块的原始 12 位序列(按字符顺序、每字符先低后高)是:

观测到的输出是:

于是置换 P(输出位置 → 取自输入索引)为:

验证:{1,0,3,11,4,9,2,6,5,8,7,10} 恰好是 0..11 的一个排列 ✅ —— 模型自洽

说明:因为 3 个 4 之间、3 个 5 之间可以互换,这个置换的具体写法不唯一(有 3!×3! = 36 种等价写法),但数据位的映射是唯一确定的,不影响解密。

再叠加 Step 1 的整串反转——这是"重排"的第二层,也是本题最大的迷惑点:它让密文块顺序与明文块顺序相反,破坏了人眼最依赖的"从左到右"直觉。

尾块中的 2233 / 2235 / 53 / 3 这些魔数,作用是:

只与 len(S) mod 3 有关,与明文内容无关——完全对应题面提示。所谓"摘要"其实一个哈希都没有,就是个长度指纹。

核心弱点C[i] = (P[π(i)] + k[i]) mod 16 —— 这是一个逐位仿射映射,没有任何非线性、没有轮函数、没有密钥调度。整个密码可以用一张 12 行的查表完全描述。

假设你手上只有密文,下面是从零开始的完整操作流程

不是的话,说明分块假设错了,回头重新推膨胀率。

FLAG:144 % 12 = 0 ✅ → 12 块。

最后一块

不会误判正常块:正常块 pos1 恒为 4,而两种尾块前缀的第 2 位都是 2

FLAG 最后一块 22332235A4B322332235 开头 → 尾块,1 个字符。
所以:前 11 块 × 3 + 1 = 34 个字符

对每个完整块检查:

任何一块不满足 → 说明块边界错位或密文抄错,立刻停下排查。这是免费的纠错机制,一定要用。

记忆口诀

含 1 个字符22332235....):

含 2 个字符2235........):

⚠️ 注意 b 的 hi/lo 位置顺序与 a 相反,这是最容易写错的地方。

⚠️ 不要忘记最后这一步反转 —— 这是本题最大的坑。

用还原的算法把 S 重新加密,比对是否与原密文逐位相同。不做这一步,永远不能确定答案对不对。

本章是自包含的。 前面十二章讲的是"规律是怎么推出来的",本章只讲"知道规律后怎么算"。
只看这一章,不回头翻任何其他章节,也能独立完成加密和解密的全部手工计算。所有需要用到的规则、对照表、字符编码都在 13.0 里给全。

一句话记住拆分方法:把字符写成两位十六进制,左边那位是 hi,右边那位是 lo

全部运算在模 16 下进行:加法超过 F 就减 16;减法出现负数就加 16。

加密方向 —— 低半字节 +4

加粗的 4 列是回绕发生的地方:C+4=0x10,超出一位,只保留 0

加密方向 —— 高半字节 +5

可打印 ASCII 的 hi 只可能是 2..7,所以加 5 后必落在 7..C永远不会回绕
反过来说:解密时如果某个"高位列"的值不在 7..C 内,说明你取错位置了。

解密方向 —— 低半字节 −4

加粗的 4 列是必须 +16 回绕的情况。例:1 − 4 = −3−3 + 16 = D
⚠️ 直接写成 3 是本题最高频的错误,会让整个 flag 全错。

解密方向 —— 高半字节 −5

设一块的三个字符为 c0, c1, c2按 R 中的顺序,即已经反转过的顺序):

背下这两条就够了:

注意 c1c2 的位置是交叉错开的(c2 在前、c1 在后),这是"固定位置重排"造成的,不是笔误。

尾块数据位速查:

⚠️ 两个坑:
r=2 时,a 是"先 lo 后 hi",b 是"先 hi 后 lo",顺序相反,写反了必错。
r=1 的尾块虽然名义上是 2233 + 2235 两段拼接,但实际是以 2233 开头的,判别时不能只写"以 2235 开头"。

len(R) = 5

按位号 0→11 顺序读出:

a = 'e' = 0x65 → hi=6, lo=5
b = 'H' = 0x48 → hi=4, lo=8

与题面给出的 Hello -> 34BB405504B5223594B94C53 逐位一致

c0='6', c1='2', c2='0';剩余字符 c='2'

c = '2' = 0x32 → hi=3, lo=2

与题面 2026 -> A48844556485223322356483 一致

与题面 TLU -> 94AA48550495 一致 ✅ 密文只有 12 位,印证了 r=0 时确实不追加尾块。

6/6 通过 → 这是一个结构正确的完整块,可以继续。
(若有任何一项不符,说明块边界切错了密文抄错了,应立即停下排查,而不是硬算下去。)

因为整串明文是反转态,这 3 个字符对应原文最末尾 3 个字符的倒序 → 原文以 r!} 结尾。对于一个 flag{...} 格式的 flag,结尾是 },完全合理 ✅

本例最大的坑d[0] − 4 = 1 − 4
很多人算成 −3 后直接取绝对值当成 3,得到 0x73 = 's',于是 flag 结尾变成 s!r,整题全错。
凡是减法结果为负,一律 +16 查 13.0 表 (3) 的"解密方向 −4"那一行也可以直接得到 1 → D

前 8 位是 22332235 → 查 13.0 表 (5):这是 r=1 的尾块,只含 1 个真实字符

为什么不会和完整块搞混? 完整块的位 1 恒为 4,而这里位 1 是 2,天然互斥。

反转态的最后一个字符 = 原文的第一个字符 → flag 以 f 开头

前 4 位是 2235(且不是 22332235)→ r=2 的尾块,含 2 个真实字符

这正是 13.1 中 Hello 反转后 R="olleH" 的最后两个字符 ✅ 加解密闭环。

FLAG 密文(144 位,实际为一整行):

最后一块 22332235A4B3:以 22332235 开头 → r=1 的尾块,含 1 个字符。
前 11 块位 1 全是 4,均为完整块。

下表把每块的三次"取位—减法—合成"全部展开。减法列中标 +16 的即发生了回绕。

全表共出现 6 次负数回绕(块 0、2、5、6、8、10 各一次)。这 6 处是全题最容易翻车的地方,逐一核对过再往下走。

把还原出的明文重新加密一遍,与原密文逐位比对:

与题面 FLAG 密文 144 位逐位相同

语义自检:flag 内容是 leetspeak —— T1u + 2026 + Kc7f(KCTF,t7)+ Crypt0o0)+ M4stera4)。各段均为可读的英文单词/年份变形,语义自洽,进一步佐证结果正确。

保存为 hexmaze.py

运行输出:

⚠️ 实现踩坑:尾块判据不能只写 startswith("2235")
余 1 的尾块是 2233 + 2235 拼接,实际以 2233 开头(例如 2026 的尾块 223322356483),只判 2235 会漏掉它,导致该块被当成正常块送进 _dec_block,触发标记位断言失败。
正确判据要同时覆盖 22332235(余 1)和 2235(余 2)两种前缀。

反过来问:正常块会不会被误判成尾块?不会 —— 正常块的 pos1 恒为 4,而两种尾块前缀的第 2 位都是 2,天然互斥。这个判据是安全的。

题面给了"密钥: 121",但还原出的算法里没有任何一处用到它

判据很硬:上面的实现在完全不引用 121 的前提下,已经能把 4 组已知样本 + FLAG 全部双向精确复现(144 位逐位相同)。如果密钥真的参与了运算,必然存在至少一个无法用固定常量解释的位——但一个都没有。

几种可能:

处理这类信息的正确姿势:先假设它无关,用数据说话;只有当模型出现无法用常量解释的残差时,才回头引入密钥变量。 本题残差为零,所以密钥无关的结论是充分的。

这道题的通用解题套路,可以复用到绝大多数"自制古典/位级密码"的已知明文分析:

len(密文) vs len(明文) 的比值决定了膨胀率和分组边界。比值不整齐就一定有填充,反推填充规则往往能直接定出块大小。

题面明说"无随机数/无 IV" → 相同明文片段必产生相同密文片段。拿已知密文块去目标密文里搜,命中即同时确认块长、块对齐、块间独立性三件事。本题 A48844556485 在 FLAG 偏移 84 处命中,一击定三事。

把所有块按位对齐成矩阵,逐列看取值集合。恒定列 = 结构性标记(送你免费的完整性校验);变化列 = 载荷。

可打印 ASCII 的高半字节只有 2..7 六种取值。统计每列的取值宽度:

这一步甚至不需要已知明文,纯唯密文就能做。

高位列窗口落在 8..C,明文值域 2..7,差 5 → 偏移就是 +5。不用爆破。

202TLU 这种高半字节重复的样本容易产生假阳性(顺序错了也能对上)。Helloabcd! 信息量大,是真正的试金石。

把还原的明文重新加密,逐位比对。不回验的答案不算答案。

最终答案

题面表述 技术含义 对分析的价值
固定算法 / 无随机数 / 无 IV / 无外部状态 确定性函数 C = E(P) 相同明文片段必产生相同密文片段 → 可以做"片段比对"
字节编码 明文字符先被拆/映射成某种中间表示 密文长度 ÷ 明文长度 会暴露膨胀率
十六进制位运算 操作粒度是 nibble(4 bit / 1 个十六进制字符),不是 byte 分析单位应该是"十六进制位",不是"字节"
模16循环偏移 (x + k) mod 16 数据位与明文位之间是加法常量差关系
固定位置重排 一个固定置换 P 明文位与密文位是一一对应的,只是位置乱了
固定摘要扰动 一个附加的、非主体的扰动步骤 大概率只影响"边角",不影响主体
摘要扰动只与输入长度有关 扰动 ≠ 明文内容的函数 这是最重要的提示:主体变换与长度无关
明文块 pos0 1 2 3 4 5 6 7 8 9 10 11
TLU 9 4 A A 4 8 5 5 0 4 9 5
Hel 3 4 B B 4 0 5 5 0 4 B 5
202 A 4 8 8 4 4 5 5 6 4 8 5
abc 5 4 7 B 4 7 5 5 8 4 B 5
数据位 FLAG 11 块中的取值集合 不同值个数 窗口宽度 判定
pos0 1,9,8,4,D,3,7,A,6,5,B 11 散布全域 低半字节
pos2 8,A,B,C 4 5(8..C) 高半字节
pos3 8,9,A,B,C 5 5(8..C) 高半字节
pos5 0,3,4,6,7,9,B,F 8 散布全域 低半字节
pos8 1,3,5,6,8,A,F 7 散布全域 低半字节
pos10 7,8,9,A,B,C 6 6(7..C) 高半字节
原文 反转 R 第 0 块
TLU ULT ULT
Hello olleH oll
2026 6202 620
abcd! !dcba !dc
c0 hi(c0) +5 实测 pos2
ULT U=0x55 5 A A
oll o=0x6F 6 B B
620 6=0x36 3 8 8
!dc !=0x21 2 7 7
hi(c1)+5 实测 pos10 hi(c2)+5 实测 pos3
ULT hi(L)+5=9 9 ✅ hi(T)+5=A A ✅
oll hi(l)+5=B B ✅ hi(l)+5=B B ✅
620 hi(2)+5=8 8 ✅ hi(0)+5=8 8 ✅
!dc hi(d)+5=B B ✅ hi(c)+5=B B ✅
lo(c0) pos0 lo(c1) pos8 lo(c2) pos5
ULT 5 9 4 C 0 4 4 8 4
oll F 3 4 C 0 4 C 0 4
!dc 1 5 4 4 8 4 3 7 4
620 6 A 4 2 6 4 0 4 4
eH 实测 ba 实测 规律
[0:4] 2235 2235 固定头(余 2 的标志)
[4] 9 6 lo(a)+4:lo(e)=5→9 ✅ / lo(b)=2→6 ✅
[5] 4 4 固定标记 4
[6] B B hi(a)+5:hi(e)=6→B ✅ / hi(b)=6→B ✅
[7] 9 B hi(b)+5:hi(H)=4→9 ✅ / hi(a)=6→B ✅
[8] 4 4 固定标记 4
[9] C 5 lo(b)+4:lo(H)=8→C ✅ / lo(a)=1→5 ✅
[10:12] 53 53 固定尾
含义
[0:8] = 22332235 固定头(余 1 的标志,可理解为"两个填充位"的编码)
[8] lo(c)+4:lo(2)=2→6 ✅
[9] 固定标记 4
[10] hi(c)+5:hi(2)=3→8 ✅
[11] 固定尾 3
密文位 0 1 2 3 4 5 6 7 8 9 10 11
内容 lo(c0)+4 4 hi(c0)+5 hi(c2)+5 4 lo(c2)+4 5 5 lo(c1)+4 4 hi(c1)+5 5
余数 r 尾块(12 位)
0 (无尾块)
1,剩余字符 c 2233 2235 + [lo(c)+4] 4 [hi(c)+5] 3
2,剩余字符 a,b 2235 + [lo(a)+4] 4 [hi(a)+5] + [hi(b)+5] 4 [lo(b)+4] + 53
已知密文位 还原出
pos2 − 5 c0 的高半字节
pos0 − 4 c0 的低半字节
pos10 − 5 c1 的高半字节
pos8 − 4 c1 的低半字节
pos3 − 5 c2 的高半字节
pos5 − 4 c2 的低半字节
pos1,4,9 恒为 4(校验用)
pos6,7,11 恒为 5(校验用)
性质 实际情况
混淆(confusion) 。每个密文位只依赖 1 个明文半字节
扩散(diffusion) 。改 1 个明文字符只影响 4 个密文位
密钥参与 (见第十五节)
本质 单表代换 + 固定置换,等价于凯撒密码的 nibble 版
已知明文攻击 1 组样本即可完全破解(本题给 4 组是为了容错)
唯密文攻击 也可行:靠 ASCII 高半字节的窄值域即可定位高位列并求出偏移
符号 含义 举例
c 一个 ASCII 字符 'H'
hi(c) 该字符 ASCII 码的半字节(十六进制第 1 位) 'H'=0x48hi=4
lo(c) 该字符 ASCII 码的半字节(十六进制第 2 位) 'H'=0x48lo=8
R 明文整体反转后的字符串 HelloolleH
blk / d[i] 一个 12 位的密文块 / 它的第 i 位(i 从 0 数起) blk="14CC46555475", d[2]='C'
r len(R) mod 3,即最后剩几个字符不够凑一块 len("olleH")=5, r=2
字符 十六进制 hi lo 字符 十六进制 hi lo
! 0x21 2 1 T 0x54 5 4
0 0x30 3 0 U 0x55 5 5
1 0x31 3 1 _ 0x5F 5 F
2 0x32 3 2 a 0x61 6 1
4 0x34 3 4 b 0x62 6 2
6 0x36 3 6 c 0x63 6 3
7 0x37 3 7 d 0x64 6 4
C 0x43 4 3 e 0x65 6 5
H 0x48 4 8 f 0x66 6 6
K 0x4B 4 B g 0x67 6 7
L 0x4C 4 C l 0x6C 6 C
M 0x4D 4 D o 0x6F 6 F
p 0x70 7 0
{ 0x7B 7 B r 0x72 7 2
} 0x7D 7 D s 0x73 7 3
t 0x74 7 4
u 0x75 7 5
y 0x79 7 9
原值 0 1 2 3 4 5 6 7 8 9 A B C D E F
+4 后 4 5 6 7 8 9 A B C D E F 0 1 2 3
原值 2 3 4 5 6 7
+5 后 7 8 9 A B C
密文位 0 1 2 3 4 5 6 7 8 9 A B C D E F
−4 后 C D E F 0 1 2 3 4 5 6 7 8 9 A B
密文位 7 8 9 A B C
−5 后 2 3 4 5 6 7
情况 尾块 12 位构成 前缀特征(解密时靠它识别)
r=0 不产生尾块 密文最后一块的位 1 是 4
r=1,剩 c 2 2 3 3 2 2 3 5 · lo(c)+4 · 4 · hi(c)+5 · 3 22332235 开头
r=2,剩 a b 2 2 3 5 · lo(a)+4 · 4 · hi(a)+5 · hi(b)+5 · 4 · lo(b)+4 · 5 3 2235 开头
情况 字符 hi 在第几位(减 5) lo 在第几位(减 4)
r=1 c 10 8
r=2 a(第 1 个) 6 4
r=2 b(第 2 个) 7 9
变量 字符 十六进制 hi lo
c0 o 0x6F 6 F
c1 l 0x6C 6 C
c2 l 0x6C 6 C
位号 模板内容 代入 加法过程 结果
0 lo(c0)+4 F+4 15+4=1919−16=3回绕 3
1 固定标记 4
2 hi(c0)+5 6+5 =11 B
3 hi(c2)+5 6+5 =11 B
4 固定标记 4
5 lo(c2)+4 C+4 12+4=1616−16=0回绕 0
6 固定标记 5
7 固定标记 5
8 lo(c1)+4 C+4 12+4=1616−16=0回绕 0
9 固定标记 4
10 hi(c1)+5 6+5 =11 B
11 固定标记 5
位号 模板内容 代入 结果
0–3 固定头 2 2 3 5
4 lo(a)+4 5+4=9 9
5 固定标记 4
6 hi(a)+5 6+5=11 B
7 hi(b)+5 4+5=9 9
8 固定标记 4
9 lo(b)+4 8+4=12 C
10–11 固定尾 5 3
变量 字符 十六进制 hi lo
c0 6 0x36 3 6
c1 2 0x32 3 2
c2 0 0x30 3 0
位号 模板 代入 结果
0 lo(c0)+4 6+4=10 A
1 标记 4
2 hi(c0)+5 3+5=8 8
3 hi(c2)+5 3+5=8 8
4 标记 4
5 lo(c2)+4 0+4=4 4
6 标记 5
7 标记 5
8 lo(c1)+4 2+4=6 6
9 标记 4
10 hi(c1)+5 3+5=8 8
11 标记 5
位号 模板 代入 结果
0–7 固定头 2 2 3 3 2 2 3 5
8 lo(c)+4 2+4=6 6
9 标记 4
10 hi(c)+5 3+5=8 8
11 固定尾 3
位号 模板 代入 结果
0 lo(c0)+4 5+4=9 9
1 标记 4
2 hi(c0)+5 5+5=10 A
3 hi(c2)+5 5+5=10 A
4 标记 4
5 lo(c2)+4 4+4=8 8
6 标记 5
7 标记 5
8 lo(c1)+4 C+4=16→0回绕 0
9 标记 4
10 hi(c1)+5 4+5=9 9
11 标记 5
检查项 要求 实测 结果
d[1] 4 4
d[4] 4 4
d[9] 4 4
d[6] 5 5
d[7] 5 5
d[11] 5 5
# 密文块
0 14CC46555475
1 94BC475584C5
2 848A43551495
3 448C445584C5
4 D4C9475564C5
5 34A84B55A4B5
6 74BA4355F495
7 A48844556485
8 648C495534A5
9 548C4F5584A5
10 B4BB405554B5
11 22332235A4B3
# 密文块 c0d[2]−5 / d[0]−4 c1d[10]−5 / d[8]−4 c2d[3]−5 / d[5]−4 明文
0 14CC46555475 C−5=7 / 1−4+16=D → 0x7D } 7−5=2 / 5−4=1 → 0x21 ! C−5=7 / 6−4=2 → 0x72 r }!r
1 94BC475584C5 B−5=6 / 9−4=5 → 0x65 e C−5=7 / 8−4=4 → 0x74 t C−5=7 / 7−4=3 → 0x73 s ets
2 848A43551495 8−5=3 / 8−4=4 → 0x34 4 9−5=4 / 1−4+16=D → 0x4D M A−5=5 / 3−4+16=F → 0x5F _ 4M_
3 448C445584C5 8−5=3 / 4−4=0 → 0x30 0 C−5=7 / 8−4=4 → 0x74 t C−5=7 / 4−4=0 → 0x70 p 0tp
4 D4C9475564C5 C−5=7 / D−4=9 → 0x79 y C−5=7 / 6−4=2 → 0x72 r 9−5=4 / 7−4=3 → 0x43 C yrC
5 34A84B55A4B5 A−5=5 / 3−4+16=F → 0x5F _ B−5=6 / A−4=6 → 0x66 f 8−5=3 / B−4=7 → 0x37 7 _f7
6 74BA4355F495 B−5=6 / 7−4=3 → 0x63 c 9−5=4 / F−4=B → 0x4B K A−5=5 / 3−4+16=F → 0x5F _ cK_
7 A48844556485 8−5=3 / A−4=6 → 0x36 6 8−5=3 / 6−4=2 → 0x32 2 8−5=3 / 4−4=0 → 0x30 0 620
8 648C495534A5 8−5=3 / 6−4=2 → 0x32 2 A−5=5 / 3−4+16=F → 0x5F _ C−5=7 / 9−4=5 → 0x75 u 2_u
9 548C4F5584A5 8−5=3 / 5−4=1 → 0x31 1 A−5=5 / 8−4=4 → 0x54 T C−5=7 / F−4=B → 0x7B { 1T{
10 B4BB405554B5 B−5=6 / B−4=7 → 0x67 g B−5=6 / 5−4=1 → 0x61 a B−5=6 / 0−4+16=C → 0x6C l gal
11 22332235A4B3 (尾块,规则不同) d[10]−5 = B−5=6 / d[8]−4 = A−4=6 → 0x66 f (无) f
# 易错点 后果 规避方法
1 忘记最后的整体反转 得到 }!rets4M_... 这种倒序串 加密第一步反转、解密最后一步反转,两头都别漏
2 减法出负数没 +16 单个字符错,如 }s 查 13.0 表 (3) 的解密行,或牢记"负了就加 16"
3 加法超 F 没 −16 加密结果对不上,如 C+4 写成 10 C/D/E/F 加 4 必回绕,见表 (3)
4 c1c2 的取位记反 每块中间两个字符互换 口诀:c0→(2,0)c1→(10,8)c2→(3,5)
5 r=2 尾块中 b 的 hi/lo 顺序写反 末尾 1 个字符错 a 是"先 lo 后 hi",b 是"先 hi 后 lo"
6 尾块判别只写"以 2235 开头" r=1 的尾块被当成完整块,自检断言失败 r=1 实际以 2233 开头,两种前缀都要判
7 跳过固定位自检 块边界错位却毫无察觉,一路算到底才发现全错 每个完整块先查 6 个固定位,1 秒钟的事
8 不做回验 自以为对了 encrypt(解出的明文) == 原密文,逐位比对
HexMaze 使用固定算法对 ASCII 字符串进行变换。

算法仅包含:
- 字节编码;
- 十六进制位运算;
- 模16循环偏移;
- 固定位置重排;
- 固定摘要扰动。

不包含:
- 随机数;
- 随机 IV;
- 外部状态。

相同输入和密钥一定产生唯一输出。

提示:摘要扰动过程只与输入长度有关。

已提供4组已知明文/密文,请分析变换规律并恢复 FLAG。

HexMaze
密钥: 121

TLU   -> 94AA48550495
Hello -> 34BB405504B5223594B94C53
2026  -> A48844556485223322356483
abcd! -> 547B475584B5223564BB4553

FLAG:
14CC4655547594BC475584C5848A43551495448C445584C5D4C9475564C534A84B55A4B5
74BA4355F495A48844556485648C495534A5548C4F5584A5B4BB405554B522332235A4B3

传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!

收藏
免费 3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回