首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
0
0
[原创] 第五题:申时·忆海倒带 wp
发表于: 2026-8-17 16:36
90
[原创] 第五题:申时·忆海倒带 wp
xoxo999
2026-8-17 16:36
90
# 第五题:申时·忆海倒带 ## Challenge Summary 附件 `cm.rar` 包含 `cm.exe` 与规则说明。规则要求输入序列号并看到 `verify success.`。原文件 SHA-1 为 `d1c8124c5964af1531c6e311328854a05ca40bca`,与题面一致。 ## Clues and Triage `cm.exe` 是未签名的 32 位 PE。真实输入路径从 `0x403F60` 开始:只接受 `0-9`、`A-Z`,并严格要求 88 个字符。输入首先被按十六进制大整数解析;因此 实际可用字符集是十六进制的 `0-9A-F`。 该路径随后把大整数按大端字节展开,检查: - 所有展开字节 XOR 为 `0x8f`; - 滚动和 `sum += ((sum & 0x7f) + 1) * byte` 的低 16 位为 `0xbeff`; - 最终查表结果逐字节等于 `Welcome to KCTF2026! Come and give it a try.`。 字符串中的 `admin123`、异常处理器和 `int3` 注释只在前导诱饵代码中出现,未进入 最终成功比较,不能作为密码使用。 ## Vulnerability / Key Insight 最终映射对象由 `0x4033d0` 建立。`0x404870` 对输入字节 `b` 的实际查找为: ```text index = b - 1 offset = u32[0x4163b0 + 4 * index] output = byte[0x4263b0 + offset] ``` 对目标欢迎语逐字节反查 `b in [1, 127]`,每个字符都有唯一原像。前 28 个原像直接 构成序列号对应大整数的前缀;后 16 个原像是 RSA 变换后的结果。 函数 `0x403500` 取原始大整数的后 16 字节,进行 `pow(x, e, n)`,再把结果覆盖到 最终查表前的后 16 字节。程序的“大整数数组”不是普通连续数组:访问器 `0x402a70` 通过对象 `+0x0c` 的置换索引定位 `+0x04` 的基数组。按该布局还原得到: ```text n = 0x8c91cb79ec693f3ed6519c945dd67371 e = 65537 n = 13702465297157554691 * 13636154180376482939 ``` 对所需的最后 16 个映射前字节作私钥逆运算,即可恢复原始尾块。 ## Exploit / Solve Chain 1. 从 `0x4263b0` / `0x4163b0` 反查最终欢迎语,得到查表前的 44 字节目标流。 2. 保留其前 28 字节;将最后 16 字节解释为 RSA 密文 `y`。 3. 分解 128 位模数,计算 `d = e^-1 mod ((p-1)(q-1))`。 4. 计算 `x = y^d mod n`,并以 16 字节大端形式替换原流尾部。 5. 将 44 字节转为大写十六进制文本。脚本验证 RSA 回代、XOR 和滚动校验。 ## Complete Script / Key Code 实际求解器:[solve.py](solve.py)。完整内容如下: ```python """Construct the verified key for KCTF 2026 Reverse #5 from static evidence.""" from functools import reduce TARGET_AFTER_RSA = bytes.fromhex( "323C47184B0D3C44254B445842552F365C362C1144424B0D" "3C4416430F4439374E3C44372544164425151D1B" ) P = 13702465297157554691 Q = 13636154180376482939 E = 65537 def rolling_check(data: bytes) -> int: total = 0 for byte in data: total = (total + ((total & 0x7F) + 1) * byte) & 0xFFFFFFFF return total & 0xFFFF def main() -> None: n = P * Q phi = (P - 1) * (Q - 1) d = pow(E, -1, phi) encrypted_tail = int.from_bytes(TARGET_AFTER_RSA[-16:], "big") original_tail = pow(encrypted_tail, d, n).to_bytes(16, "big") key_bytes = TARGET_AFTER_RSA[:-16] + original_tail assert len(key_bytes) == 44 assert pow(int.from_bytes(original_tail, "big"), E, n) == encrypted_tail assert reduce(lambda left, right: left ^ right, key_bytes, 0) == 0x8F assert rolling_check(key_bytes) == 0xBEFF key = key_bytes.hex().upper() assert len(key) == 88 and all(char in "0123456789ABCDEF" for char in key) print(key) if __name__ == "__main__": main() ``` ## Key Result `solve.py` output: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` ## Flag ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ```
登录后可查看完整内容
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
收藏
・
0
点赞
・
0
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
xoxo999
2
发帖
0
回帖
10
RANK
关注
私信
他的文章
[原创] 第五题:申时·忆海倒带 wp
90
[原创]巳时·绿光幽语 WP
131
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部