-
-
[原创]KCTF 2026 第五题:申时·忆海倒带 writeup
-
发表于: 7小时前 134
-
一、程序逻辑梳理
题目是一个 32 位的 Windows PE 文件,要求输入一串 44 字节(88 个十六进制字符)的密钥。
二、前置校验绕过
程序早期的 XOR 校验要求整体异或和等于 0x8F,Checksum 校验要求递推结果为 0xBEFF。
由于这两个校验仅仅是放行条件,不参与后续的数据变换,处理起来非常简单。在实际分析时,既可以在 IDA 中将对应的条件跳转指令直接 Patch 掉,也可以用脚本随机生成一组符合异或和 Checksum 规律的垃圾数据作为跳板,强制让程序走到终点的查表逻辑处。
三、查表逻辑与终态逆推
程序在启动时会通过 sub_4033D0 函数初始化一张查表矩阵。
分析汇编可以发现,该表所需的核心数据全部在 PE 文件中静态写死:数据基址 data 位于 0x4263B0,置换表 permutation 位于 0x4163B0,逻辑索引范围是 0x4000。
既然数据是静态固定的,就可以直接放弃动态调试,利用 pefile 库离线读取这两个内存段的内容,在本地重现程序的字节映射逻辑。遍历 1 到 127 的有效输入字符建立反查字典,然后拿硬编码的目标字符串去字典里逐个查表,就可以得到查表前内存中真正需要的 44 字节中间状态:
四、RSA 128 解密
拿到中间状态后,按照程序逻辑将其切分为两部分:
前 28 字节为固定前缀:
后 16 字节为 RSA 密文:
提取程序中的公钥数据,N = 0x8C91CB79EC693F3ED6519C945DD67371,e = 65537。由于 N 只有 128 位,可以直接用常规工具分解出两个素数:
有了 p 和 q 即可算出私钥 d,对后 16 字节密文进行标准 RSA 解密,最后将解密结果与前 28 字节拼接,就是最终的 Flag。
五、完整求解脚本
结合 pefile 静态解析、逆向查表和 RSA 解密,完整的纯静态求解代码如下: