-
-
[原创]KCTF 2026 第五题
-
发表于: 22小时前 125
-
题目给出 cm.exe,规则很简单:输入 Key,看到 verify success. 就算通过。样本是 x86 PE,
对照一下SHA1是否题面一致:
最终Flag
这题的难点不在爆破,而在于三件事:控制流被 SEH 和运行时跳板打散,输入实际上是 44 字节数据,最后 16 字节还经过了一次小模数 RSA。下面按真实逆向顺序展开。
字符串窗口里有一组很刻意的提示:
如果跟着这些字符串做,会在几个自定义大整数对象里兜圈子。真正应该先盯住的是成功字符串。最终比较的目标位于 .rdata:0x416380:
长度恰好是 44 字节。交叉引用落在 0x40454A,关键比较代码非常直白:
因此最稳的路线不是猜密码,而是把这 44 字节目标反推回输入。
主函数 0x403D90 读取输入后,先进行格式检查:
注意这里的字符集表面上允许 0-9A-Z,但后续实际解法使用的是大写十六进制字符。0x402100 把输入按 16 进制解析成 11 个 32 位 limb,随后主函数将 limb 反序导出为连续的 44 字节。
对最终 Key 下断点,0x404112 处的缓冲区内容为:
随后有两道前置校验。它们都在 0x403D90 中,静态和动态结果一致:
最终数据的实际结果是:
只满足这两项仍然会失败。真正的校验从 0x404271 调用 0x403500 后才开始。
0x403500 一开始就建立 SEH 链:
函数体里反复出现这种布局:
再加上进入输入路径前的 sub_4033A0,直接让 IDA 按线性控制流读,很容易把大量 ret 当成函数结束。实际运行时这些块由异常处理和跳板串起来,所以这题不能只盯一份伪代码。
我使用的做法是:静态分析只负责确定输入格式、常量和最终比较;运行时在 0x404112、0x4041BC、0x40425F、0x403500、0x404586 下点确认数据确实按预期流动。这样可以避开假控制流,同时不需要 patch 样本。
运行到 0x403500 后,程序会先截取 Key 的后 32 个字符:
它会被解析为 4 个 32 位 limb,也就是 16 字节 RSA 密文块。函数中的查表逻辑最终需要 44 个索引;前 28 个索引直接来自输入,后 16 个索引由 RSA 运算恢复。
把目标 Welcome 串逆查程序的表,得到的索引序列为:
程序对候选密文 c 做的是:
其中:
末 16 个索引正是 m:
为了反推 c,分解这个 128 位模数即可:
因此:
得到:
把前 28 个索引和这个密文拼接,就是最终的 44 字节输入数据。
完整脚本:
它包含从目标串使用到的查表项、p/q/d 推导、RSA 逆运算和两个前置校验
输出:
最后用原程序验证:
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。