首页
社区
课程
招聘
[原创]KCTF 2026 第三题:午时·永数囚笼 Writeup
发表于: 1天前 426

[原创]KCTF 2026 第三题:午时·永数囚笼 Writeup

1天前
426

分析中使用的关键地址如下:

输入读入后会去除 CR/LF0x14000306C 内部最多复制 0x1A 字节,同时在返回前把长度与 0x1A 的差写入最终差异量。因此通过条件包含:

对 VMCode 计算出的两个常量为:

在正常桌面环境中,调试探测与完整性检查均走未触发分支。为了排除仿真误差,低级指令模型、Unicorn 和 Windows 原生进程分别对多组 26 字节样本进行了比较;每份 240 字节 worker 记录和 16 字节汇总值均一致。

这一步得到的结论很具体:后续求解可以使用已经抽出的整数模型,候选仍需交还原程序确认。

设用户数据为 M[0..25]。进入 0x140002BA0 前,程序构造:

随后按小端解释为 A[0..7] 八个 DWORD。初始加白为:

r 轮先更新两个位置:

然后调用一次固定的八字 ARX 置换。这样的轮次共八次,输出记作 X[0..31]

所有算子都存在明确逆操作:加法用减法撤销,循环左移用循环右移撤销,异或再次执行即可。八字置换也可按中间量逐项回代。逆回初始数组后,合法状态必须满足:

这 48 个固定位用于淘汰无法来自 26 字节输入的 X

本题最终恢复的内部状态为:

将它逆回去,八个原始 DWORD 为:

去掉固定尾部后正好留下 26 个答案字节。

每个 worker 写出 15 个 DWORD:

其中 error 的精确计算式为:

VM 内部的停止标志只负责离开循环。它与记录中的 error 字段分开保存。外层函数不会看到 error != 0 就立即返回;整个 DWORD 会作为第七个字段继续参与 0x140002940 的运算。

答案对应的实际记录状态是:

因此只有编号 2 的 worker 符合自身参考记录,其余三份记录依然是外层计算所需的数据。

最终选择器要求 0x140002940 的四个输出 DWORD 等于:

汇总函数尾部是 128 位线性变换。构造它对 128 个基向量的响应矩阵,得到秩 128,所以末态唯一。再把前面的四段 32 位递推按顺序消元,只剩一个 32 位闭合方程。枚举该方程的根并逐个阻断后,只找到下列一组 worker 摘要:

把二进制内置的四份 worker 参考记录分别送入摘要函数,编号 2 的参考记录恰好产生 47D3D751。这给出了一个可直接求原像的单路条件:

从参考 post words 撤销末尾四轮 ARX 与状态注入后,得到 worker 2 的原始 32 字节目标:

这里没有要求另外三个 worker 也套用各自的参考输出。解出一个满足 worker 2 的 X 后,再运行四 worker 的总验证即可判断它是否同时生成另外三个所需摘要。

worker 2 的一次完整运行包含 257 条 VM 指令。逐条记录 opcode、PC、code key 和跨轮寄存器后,可以看到:

每组只有一次 primary byte 读取和一次 raw byte 提交。把固定的 8 条指令折叠成一项参数后,第 p 组可以表示成以下过程。

先由当前两个 32 位状态计算索引:

I_p 的常量全部来自该组解码后的 load 指令。primary 经过本组专属的 8 位双射:

普通组满足:

带交叉读取的组满足:

交叉组只出现在这些记录号:

其中 2/322/23 分别互相引用;12..1524..27 各自在一个四字节窗口内切换次序。

提交输出后,两个跨组状态更新为:

第二式中的 K_p 由 code key 指令、记录号和 raw byte 组成;所有量在进入下一组前已经确定。

抽出的 32 组模型用随机 X 与低级 VM 逐组比较,检查项包括 primary index、raw byte、r_nexts_next、PC 和 code key。它们全部相等后才用于恢复答案。

搜索状态只保存:

U_p 由 8 位加减、旋转、异或和奇数乘法构成。奇数在模 256 下有乘法逆元,所以:

然后检查 X[j] 是否已经被赋成不同的值。普通记录通常只产生一个后继状态。

令 secondary 位置为 k

赋值冲突当场丢弃,无需等到 32 组结束。

worker 2 的 error 必须为零,因此:

索引域也是 32 个元素,所以最终自然覆盖全部 0..31。每次得到 j 后先查占用位图,重复索引直接终止该分支。

答案分支的索引顺序为:

进入记录 12 时,统计 X[12..15] 已经填入几个位置。答案路径的计数为 2。枚举器仅保留该计数等于 2 的任务;记录 22 和 24 处不额外限制。

另一个任务维度是 X 的 12 位桶号。桶计算为:

worker 的 s0h 计算,因而每个桶可以独立执行。本次复现取:

依次处理 0, 8, 16, ...,在 h=0x110 时找到唯一完整叶子。

记录 31 完成后依次检查:

编译参数为:

本机复现耗时 8.59 秒,关键输出为:

候选的 worker 2 raw output 与目标逐字节相等:


冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

上传的附件:
收藏
免费 18
打赏
分享
最新回复 (18)
雪    币: 400
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
6666
12小时前
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
6666
12小时前
0
雪    币: 900
活跃值: (1051)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
坑了不少token
11小时前
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
66666
11小时前
0
雪    币: 177
活跃值: (775)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
666
11小时前
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
666
11小时前
0
雪    币: 29
活跃值: (890)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
666666666
11小时前
0
雪    币: 51
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
111
10小时前
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
11
10小时前
0
雪    币: 653
活跃值: (330)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
10小时前
0
雪    币: 209
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
nb
10小时前
0
雪    币: 854
活跃值: (1383)
能力值: ( LV7,RANK:101 )
在线值:
发帖
回帖
粉丝
13
nb
10小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
nb
6小时前
0
雪    币: 0
活跃值: (1929)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
66666
5小时前
0
雪    币: 366
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
nb
5小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
66
3小时前
0
雪    币: 528
活跃值: (1790)
能力值: ( LV3,RANK:37 )
在线值:
发帖
回帖
粉丝
18
111
1小时前
0
雪    币: 3430
活跃值: (2168)
能力值: ( LV13,RANK:254 )
在线值:
发帖
回帖
粉丝
19
666
43分钟前
0
游客
登录 | 注册 方可回帖
返回