首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
0
1
[原创]KCTF2026 第5题 解析
发表于: 2026-8-17 18:07
562
[原创]KCTF2026 第5题 解析
自驾游
2026-8-17 18:07
562
# cm.exe Reverse Writeup ## 题目信息 附件给出一个 Windows 32 位控制台程序 `cm.exe`,运行后要求输入序列号。题目目标是构造正确 Key,使程序输出: ```text verify success. ``` 最终可用序列号为: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` --- ## 1. 基本分析 首先查看压缩包内容,可以看到主要文件为: ```text readme.txt cm.exe ``` `readme.txt` 中说明需要输入一个序列号,成功后程序会输出 `verify success.`。 使用 `file` 或者 PE 工具查看 `cm.exe`,可以确认它是一个 32 位 Windows 控制台程序。随后直接使用 IDA 打开程序。 在字符串窗口中可以看到一些比较明显的字符串,例如: ```text admin123 password n0_4i_c4n_r34d_th1s! verify success. verify failed. Welcome to KCTF2026! Come and give it a try. ``` 一开始容易被 `admin123`、`password` 这类字符串误导,但交叉引用后可以发现它们不是最终序列号校验的关键,真正的校验逻辑在后面的输入处理和大整数运算部分。 --- ## 2. 定位校验逻辑 从 `verify success.` 字符串入手查看交叉引用,可以定位到主校验函数。程序整体逻辑大致如下: 1. 读取用户输入的序列号; 2. 检查输入长度; 3. 将输入按照十六进制字符串解析成字节数组; 4. 做异或校验和加权和校验; 5. 对前半部分做查表映射校验; 6. 对后半部分做 RSA-like 大整数校验; 7. 全部通过后输出 `verify success.`。 关键长度检查可以整理为: ```c if (strlen(input) != 88) { fail(); } ``` 也就是说,输入必须是 **88 个十六进制字符**,转换后正好是 **44 字节**。 --- ## 3. 第一层约束 程序将 88 位十六进制字符串转换成 44 字节后,会先进行两个整体约束检查。 第一个是异或校验: ```c xor_all == 0x8f ``` 第二个是加权和校验: ```c checksum == 0xbeff ``` 这两个检查不是最终求解的核心,但可以用于验证构造出来的 Key 是否满足程序要求。 --- ## 4. 前 28 字节查表逆推 继续分析可以看到,程序将前 28 字节经过某种表映射后,与目标字符串的一部分进行比较。 目标明文字符串为: ```text Welcome to KCTF2026! Come and give it a try. ``` 由于这里的变换本质上是固定表映射,因此可以通过构造逆表,将目标字符反推回输入字节。 逆推后得到前 28 字节为: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C441643 ``` 这部分长度为 56 个十六进制字符,也就是 28 字节。 --- ## 5. 后 16 字节 RSA-like 校验 剩下的 16 字节进入大整数校验函数。该函数核心形式类似 RSA 加密: ```c c = m^e mod n ``` 其中: ```text e = 0x10001 n = 0x8c91cb79ec693f3ed6519c945dd67371 ``` 也就是程序会把输入后 16 字节当作大整数 `m`,计算 `m^0x10001 mod n`,再与程序内部的目标值比较。 程序内部目标密文为: ```text 0F4439374E3C44372544164425151D1B ``` 因此需要对这个 RSA-like 过程求逆。 对模数 `n` 分解: ```text p = 13636154180376482939 q = 13702465297157554691 ``` 计算: ```text phi = (p - 1) * (q - 1) d = inverse(e, phi) ``` 得到私钥指数: ```text d = 0x721a022d849de5cc5ad9bbb701f9fb65 ``` 于是可以解出明文: ```python n = int("8c91cb79ec693f3ed6519c945dd67371", 16) e = 0x10001 c = int("0F4439374E3C44372544164425151D1B", 16) p = 13636154180376482939 q = 13702465297157554691 phi = (p - 1) * (q - 1) d = pow(e, -1, phi) m = pow(c, d, n) print(m.to_bytes(16, "big").hex().upper()) ``` 运行结果: ```text 3B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` 因此后 16 字节为: ```text 3B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` --- ## 6. 拼接最终序列号 将前 28 字节和后 16 字节拼接即可得到完整序列号: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` 长度检查: ```text 56 + 32 = 88 ``` 正好满足程序要求的 88 位十六进制输入。 --- ## 7. 验证 将该序列号输入程序: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ``` 程序输出: ```text verify success. ``` 说明序列号构造正确。 --- ## 总结 本题表面上出现了 `admin123`、`password` 等诱导字符串,但真正逻辑并不是普通账号密码比较,而是分为两段进行校验: - 前 28 字节通过固定表映射逆推得到; - 后 16 字节通过 RSA-like 大整数运算求逆得到; - 最后拼接并满足整体异或和校验后即可通过验证。 最终序列号: ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ```
登录后可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
最后于
2026-8-18 13:28 被kanxue编辑 ,原因:
上传的附件:
cm_writeup.md
(4.76kb,6次下载)
收藏
・
0
点赞
・
1
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
PLEBFE
你的帖子非常有用,感谢分享!
2026-8-25 12:15
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
自驾游
2
发帖
0
回帖
10
RANK
关注
私信
他的文章
[原创]密码学wpKCTF07 - HexMaze Writeup
28
[原创]KCTF2026 第5题 解析
562
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
谁下载
×
kanxue
huangyalei
pzhxbz
ONewTach
mb_lthgjpwj
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部