-
-
[原创] KCTF 2026 第五题:申时·忆海倒带 Writeup
-
发表于: 8小时前 131
-
最终 Key:
该 Key 是 88 个十六进制字符,程序解析后得到 44 字节数据。
题面给的是 Windows 控制台程序,输入 Key 后出现 verify success. 即通过。
基础识别:
工具主要用:
先扫字符串:

admin123、password 这类字符串是诱饵。直接查“成功”字符串(verify success.)的引用:

输入点也在 main,所以从 main 反汇编往下看即可。
main 里先用 gets_s 读入字符串,然后调用 fcn.00402100:

fcn.00402100 的作用是按 16 进制解析字符串:循环处理每个字符,每次先把当前值乘以 0x10,再加当前 nibble。
后面有长度检查:
var_89ch 是 32-bit limb 数量,var_89ch * 8 == 0x58,即输入解析后为 11 个 DWORD,也就是 44 字节。因此原始 Key 长度应为:
随后程序把这 11 个 DWORD 按大端字节序展开成 44 字节数组 B。关键逻辑在 0x4040c0 附近:
也就是从高 limb 到低 limb,每个 DWORD 按 [b3, b2, b1, b0] 输出。
44 字节数组 B 先过两个约束。
第一个是 XOR:
约束为:
第二个是滚动 checksum:
约束为:
继续往下看,程序并不是直接把 B 和目标字符串比较。
先调用:
var_858h 是原始输入字符串缓冲区,var_820h = var_858h + 0x38。也就是说 fcn.00403500 读取的是输入字符串从偏移 0x38 开始的部分,即最后 32 个 hex 字符。
这 32 个 hex 字符对应 B 的最后 16 字节。
fcn.00403500 内部做了一次 RSA 风格的模幂:
其中:
覆盖位置由 0x40437f 到 0x4043d0 的拷贝逻辑确认,目标地址等价于:
所以最终比较用的数组是:
最终比较前,还有一层查表:
fcn.00404870 是容器索引函数。对应到数据上,查表关系可以写成:
对目标串 "Welcome to KCTF2026! Come and give it a try." 做反向查表,可以得到最终比较前需要的 44 字节:
注意分成两段看:
因此已知:
fcn.00403500 里手工构造了两个大整数容器。数据不是顺序摆放,而是 data[perm[i]]。
模数容器:
取出 4 个 32-bit limb:
小端 limb 合成整数:
指数容器:
得到:
分解 N 得到两个 64-bit 素数:
这里我用的是本地 Python 写的 ECM/Pollard 组合脚本。这个模数只有 128 bit,分解成本很低。
计算私钥指数:
得到:
解 RSA:
得到 Key 的最后 16 字节:
拼接:
最终 Key:
等价静态验证结果:
赞赏
- [原创] KCTF 2026 第五题:申时·忆海倒带 Writeup 57
- [原创]对某移动安全sdk的深入探究 6360
- SIMD指令学习 5455