-
-
[原创]KCTF2026第四题:未时·车流困城
-
发表于: 2026-8-17 00:34 226
-
题目给出一个 32 位 Windows 控制台程序和一组公开的 Name/Serial,目标是求 Name=`KCTF` 对应的合法 Serial。
程序对密钥进行多轮验证,并使用了Heaven's Gate执行(32位程序中运行64位代码),给静态分析和动态调试增加了很大难度(IDA会把64位代码识别成数据,32位xdbg无法正确解析64位指令)。



TLS Directory 中存在 callback `0x4010C0`,早于普通 OEP 执行:
0x401190 是后续 breakpoint 异常 handler。它的地址经过异或后交给内部初始化函数,说明异常和反调试环境在 OEP 前已经开始建立。
另外,用即使在程序开启运行后用xdbg附加,输入正确的用户名和serial,也会直接报错

主流程中的五次 0x4010E0 调用如下:
阶段
x86 返回点
x64代码地址
输入
0x40131F
0x8386B8
Serial
0x401335
0x7A6920
长度、Name、原 Serial
0x401354
0x7BE8D0
缓冲区、长度、16 字节状态
0x401366
0x8386B4
变换缓冲区、长度、Serial 长
0x4013AE
0x7FA6C0
Name、根列表、元数据
因为本题中普通附加调试得到的路径不可信,这里重点提取了一下两份内存转储:
| 转储 | 状态 | 用途 |
| DMP1| 公开案例成功 | 构造成功 Final 快照 |
| DMP2| 旧 KCTF 候选失败 | 恢复 Stage4 精确入口状态 |
Stage1:Serial 外层解码
1.从成功案例及转储中取得一组已知关系:
输入:公开的 9226 字符 Serial输出:Stage1 解码后的 6912 字节缓冲区
2.修改 Serial 中的单个字符,调用原程序的 Stage1,比较输出差异。
3.通过大量单字符探测恢复 64 字符字母表及字符到 6-bit 数值的映射,逆向生成目标 Serial:
4.用公开 Serial 和转储里的解码结果,计算每个位置独立的旋转量:
5.逆向生成目标 Serial:
Stage2:前置 Boolean 检查
Stage2 没有被完整去虚拟化成独立 Python 函数。它仍使用转储中的原机器代码执行,但我们已经知道构造出的 Serial 如何满足它:
所以 Stage2 对求解不是结构性障碍。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。