首页
社区
课程
招聘
[原创] KCTF2607 第七题 暗能潜流 Writeup
发表于: 4天前 41

[原创] KCTF2607 第七题 暗能潜流 Writeup

HHHso 活跃值
26
4天前
41

KCTF2607 第七题 暗能潜流 Writeup

TL;DR

一道名字叫 HexMaze 的自定义密码题:明文进、十六进制出,4 组已知明密文对,密钥 121。本文记录如何用同长度差分 + 可行集交集两把刀,剖开"模 16 循环偏移 + 固定位置重排 + 定长摘要扰动"的三层结构,发现数据在常量的掩护下按块倒序潜行,最终恢复:

flag{T1u_2026_Kc7f_Crypt0_M4ster!}

全程 ZCode × GLM-5.3 自动完成,无人工干预。总用时约 51 分钟,成本约一杯奶茶钱的零头(明细见文末附录)。


0x00 题面:一个不许你猜的密码

题目给出了一个名为 HexMaze 的变换器,自述算法只包含五种操作:

  • 字节编码(bytes → hex)
  • 十六进制位运算(nibble 级运算)
  • 模 16 循环偏移(mod-16 cyclic shift)
  • 固定位置重排(fixed permutation)
  • 固定摘要扰动(fixed digest,只与输入长度有关

并且刻意声明:无随机数、无随机 IV、无外部状态——相同输入必得相同输出。这既是承诺,也是路标:出题人在告诉你,别想暴力碰运气,这题是纯逻辑活。

已知条件(密钥 121):

明文 密文
TLU 94AA48550495
Hello 34BB405504B5223594B94C53
2026 A48844556485223322356483
abcd! 547B475584B5223564BB4553

待解密文(144 个 hex 字符):

14CC4655547594BC475584C5848A43551495448C445584C5D4C9475564C5
34A84B55A4B574BA4355F495A48844556485648C495534A5548C4F5584A5B
4BB405554B522332235A4B3

难点一眼可见:flag 的长度和 4 个样本全都不一样。任何"查表式"的映射分析,都会死在"长度变了怎么办"这一关。题目的灵魂全在那句提示里——摘要扰动只与输入长度有关


0x01 第一步:当格式侦探,而不是密码学家

拿到样本先做最无聊也最值钱的事:数长度

明文长度 L 密文 nibble 数 倍率
3 12 4.0
4 24 6.0
5 24 4.8

倍率不固定,但长度序列 12, 24, 24 像是在说:

out = 12 × ⌈L/3⌉(每 3 个字符一组,每组固定产出 12 个 nibble,即 6 字节)

反推 flag:144 ÷ 12 = 12 组 → ⌈L/3⌉ = 12 → L ∈ {34, 35, 36}。范围已经收窄到 3 个候选。

再把四条密文按 nibble 对齐排成一列(下表取自分析脚本输出):

idx  :  TLU Hell 2026 abcd
[00] :    9    3   10    5
[01] :    4    4    4    4      ← 恒定
[02] :   10   11    8    7
[03] :   10   11    8   11
[04] :    4    4    4    4      ← 恒定
[05] :    8    0    4    7
[06] :    5    5    5    5      ← 恒定
[07] :    5    5    5    5      ← 恒定
[08] :    0    0    6    8
[09] :    4    4    4    4      ← 恒定
[10] :    9   11    8   11
[11] :    5    5    5    5      ← 恒定

第 1、4、6、7、9、11 号 nibble,在四条明文完全不同的密文里纹丝不动。字节视角下更醒目:每组第 3 字节永远是 0x55

这不是巧合,这就是题目自述的"固定摘要扰动"——常量水位线。而水位线之上流动的,才是真正的数据。题目叫"暗能潜流",常量是明面,数据在暗处流——后文会看到这个"流"字有多贴切。


0x02 第二步:同长度差分——给密码做个"减法 CT"

4 个样本里只有 Helloabcd! 同为 5 字符。同长度意味着摘要项完全相同,做差即可消去——这是差分分析的经典切入点。

对两条密文做 nibble 级 mod-16 减法,再与明文 nibble 差分对照:

密文差分(非零位)           明文 nibble 差分对照
out[00] = E   ←──────────  (H−a).hi = E
out[02] = 4   ←──────────  (o−!).hi = 4   ★跨组!
out[05] = 9   ←──────────  (l−c).lo = 9
out[08] = 8   ←──────────  (l−d).lo = 8
out[16] = 3   ←──────────  (e−b).lo = 3
out[19] = E   ←──────────  (o−!).lo = E
out[21] = 7   ←──────────  (H−a).lo = 7
其余位  = 0

每一个非零差分,都能在明文差分里找到唯一(或近乎唯一)的对应。这给出两个重磅结论:

结论一:变换是 nibble 加法性的。 out[i] = in[σ(i)] + T(i) (mod 16)。(顺带证伪了 XOR 假设——XOR 差分会在 0x120x09 这类位置留下无法解释的残渣,而减法差分全部严丝合缝。)

结论二:out[02] 的差分对应第 4 个字符,而它位于第 1 组。 位置重排是全局的、跨组的——按组独立解码的死路就此堵死,同时也预告了"潜流"的存在。


0x03 迷宫的第一次误导:一张"无规律"的 K 表

接下来的惯性思路是:固定 σ 不变,跨长度求每个槽位的偏移 K(i, L),然后拟合 L 的函数。于是得到这样一张表(σ(0)=in0 假设下):

槽位 L=3 L=4 L=5
rel0 4 7 F
rel3 5 5 5
rel5 ? 2 4
rel8 ? 0 4

rel04, 7, F 既非线性也非线性之外的任何讨好公式;rel3 却又恒为 5。同一张表一半在变一半不变——这是典型的"模型错了"信号,而不是"数据错了"。

复盘这一步:差分 Ein0in9 之间存在二义性,而我当时锚定了前者。罪魁不是偏移 K 在随长度变,而是映射 σ 本身在随长度变。 死磕 K 的公式,等于在错误的坐标系里找物理定律。


0x04 突破口:反过来,让证据自己说话

方法论掉个头:不再假设 σ,转而假设槽位偏移 T 跨长度恒定,对每个数据槽位求"四样本可行 T 集合的交集"。

以 rel0 为例,逐样本列出 T = out − in 的所有可能值再取交集:

TLU   (out=9):  T ∈ {4, 5, D}
2026  (out=A):  T ∈ {7, 8, A, 4}
Hello (out=3):  T ∈ {F, B, D, E, 7, 4}
abcd! (out=5):  T ∈ {5, A, 3, 2, 1, 4}
─────────────────────────────────────
交集            T(0) = 4        (唯一!)

六个数据槽位逐一做同样操作,结果干净得不像话:

槽位:    rel0  rel2  rel3  rel5  rel8  rel10
T 值:      4     5     5     4     4     5

进一步看这些 T 对应的明文来源——+4 全部落在字符的 nibble,+5 全部落在 nibble。所谓"模 16 循环偏移",落到实处就是一条字节级规则:

每个字节 b → ((b>>4)+5, (b&15)+4) (mod 16),即整体 +0x54 的高低位错位版。

T 固定后,σ 的真容浮出水面。逐样本反解每个槽位取的是哪个输入 nibble,全部对齐到距输入末尾的距离

槽位 取的是
rel0 倒数第 1 个 nibble
rel2 倒数第 2 个
rel8 倒数第 3 个
rel10 倒数第 4 个
rel5 倒数第 5 个
rel3 倒数第 6 个

迷宫是倒着走的。 输出最左边的组,编码的是明文最右边的 3 个字符;输出最右边的"残缺组",装的才是明文开头。四条样本逐一回代验证,TLU94AA485504952026Helloabcd! 全部命中——这就是"暗能潜流"的题眼:数据逆着读序在常量河床下潜行。


0x05 全貌:完整算法规格

汇总成一张正式的版图。明文从尾部向前按 3 字符切块,块 [a, b, c](a 为时序最早字符)编码为 6 字节:

nibble: [c.lo+4,  4,  c.hi+5,  a.hi+5,  4,  a.lo+4,  5, 5,  b.lo+4,  4,  b.hi+5,  5 ]
字节:     B0        B1               B2               B3      B4        B5
                                              B3 ≡ 0x55(常量水印)
  • 满块:常量槽 {1,4,6,7,9,11} = {4,4,5,5,4,5},数据槽 {0,2,3,5,8,10}
  • 部分块(明文开头剩余 1~2 字符)——这就是"摘要只与长度有关"的真身,长度决定残缺块的形状:
    • 2 字符块 [a,b][2,2,3,5, b.lo+4, 4, b.hi+5, a.hi+5, 4, a.lo+4, 5, 3]
    • 1 字符块 [a][2,2,3,3,2,2,3,5, a.lo+4, 4, a.hi+5, 3]
  • 拼接:输出组按块的逆序连接(最左组 = 最后 3 字符,最右组 = 开头残块)。

对照样本一眼验证:Hello 末组 2235…abcd! 末组 2235… 同为 2 字符残块、前缀相同;2026 末组 2233… 是 1 字符残块的另一套常量。而 flag 的末组 22332235A4B32026 的残块模式逐位同型——flag 的 L ≡ 1 (mod 3),L = 34,三选一落定。

还有一个漂亮的旁证:flag 第 8 组 A488445564852026 的首组完全相同——因为它编码的正是同一个块 ('0','2','6'),而满块布局与总长度无关。flag 里嵌着年份 2026

0x06 解码:顺着河道把水抽干

解码即逆操作。12 个组依次还原:

输出组(hex) 还原出的 3 字符(按明文序)
14CC46555475 r ! }
94BC475584C5 s t e
848A43551495 _ M 4
448C445584C5 p t 0
D4C9475564C5 C r y
34A84B55A4B5 7 f _
74BA4355F495 _ K c
A48844556485 0 2 6
648C495534A5 u _ 2
548C4F5584A5 { T 1
B4BB405554B5 l a g
22332235A4B3 f(残块)

按"残块在前、其余逆序拼接"组装:

f + lag + {T1 + u_2 + 026 + _Kc + 7f_ + Cry + pt0 + _M4 + ste + r!}
= flag{T1u_2026_Kc7f_Crypt0_M4ster!}

一个小插曲:分析中途一度解出 Kc7aT1u_ 之外的乱码段——排查发现是手工转抄 144 位 hex 时抄错了一位,导致某组常量槽出现异常值。改用程序化直接从题目文件提取密文后,所有组常量恢复整齐,解码归位。教训值一行加粗:永远让机器读原始文件,不要让人眼当 USB 线。

最终验证(必须做满两道):

  1. 正向复现:用还原的算法重新加密 4 组样本明文,与题目密文逐位一致
  2. 往返闭合:将解出的 flag 重新加密,与题目 144 位密文逐位一致

由于每个数据 nibble 槽位都被 +4/+5 偏移一一占据、常量槽不携载信息,该密码对固定长度是单射——往返闭合即证明解唯一,不存在第二解。


0x07 复盘:这道题教会我们什么

  1. 同长度差分是自定义对称结构的 CT 扫描。只要拿到两条同长度样本,摘要项自动消去,加法性立刻现形。
  2. 证伪比拟合更快4, 7, F 这种"无规律"K 表不是让你继续猜公式,是模型在报警。改一个假设(σ 变而 T 定),废表瞬间变成常数。
  3. 可行集交集 > 单点硬猜。让每个样本各自陈述"T 可能是什么",再取交集——证据会自己收敛到唯一解,这比任何灵感都可靠。
  4. 验证要闭环。正向复现 4 样本 + 往返重加密 flag,双保险后才敢落笔 flag。
  5. 題面的每一句自述都是线索:*"摘要只与长度有关"*直接指向"残块形状由 L mod 3 决定"。出题人的免责声明,常常就是解题人的藏宝图。

附录:ZCode × GLM-5.3 用时与成本

指标 数值 口径说明
总用时 ≈ 51 分钟(14:18 → 15:09) 取自文件系统时间戳:题目落盘 14:18,首个分析脚本 14:41(此前约 23 分钟为纯推理推演、零代码),模型定稿并解出 flag 15:09
人工干预 0 次 全程单条自然语言指令启动,无中途纠偏
工具调用 ≈ 13 次 文件读取 / Bash(py) / 脚本编写与迭代
产出代码 2 个分析脚本,约 190 行 analyze.py(结构探测)+ analyze2.py(完整编解码 + 双重验证)
Token 消耗(估) 累计输入 ≈ 30–40 万(含每轮上下文重读),输出 ≈ 3 万(含长思维链) 按 14 轮对话、上下文逐步增长估算,非精确计量
成本(估) 按量计费约 ¥1–2;包月 Coding Plan 内边际成本趋近于 0 依所用套餐单价代入上表 token 数即可复算;单价以官方价目为准

一句话总结这次人机协作:51 分钟、两块钱以内、零人工干预,换来一道纯逻辑密码题的完整解剖和唯一解。 对出题人而言,这也标定了"自造对称变换"在 2026 年的真实防御强度——没有随机性,就没有秘密。

—— Writeup by ZCode (GLM-5.3),2026-08-20


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

上传的附件:
收藏
免费 0
打赏
分享
最新回复 (1)
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
zcode这么强吗
3天前
0
游客
登录 | 注册 方可回帖
返回