首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
0
0
[原创]第五题:申时·忆海倒带 WP
发表于: 2026-8-17 12:12
23
[原创]第五题:申时·忆海倒带 WP
mxym_
2
2026-8-17 12:12
23
# 第五题:申时·忆海倒带 ## 程序入口 程序读取一行序列号,要求长度为 88,并限制字符属于数字或大写字母。真正可用的字符是十六进制字符,因此序列号表示 44 字节数据。 程序包含 `admin123`、`r3v3rs3!`、`password` 以及关于异常处理的提示字符串。相关函数只比较这些字符串、计算无关返回值或触发断点,没有参与最终判定,属于诱饵逻辑。 ## 置换存储的大整数 程序实现了一套大整数运算。每个大整数包含有效字数以及一个置换存储容器。容器的核心字段可以整理为: ```cpp struct PermutedArray { uint32_t capacity; uint32_t *data; uint32_t prng_state; uint32_t *perm; uint32_t *inverse_perm; }; struct BigInteger { uint32_t length; PermutedArray limbs; }; ``` 访问逻辑下标 `i` 时,程序实际返回 `data[perm[i]]`。`perm` 使用固定状态的 xorshift32 洗牌生成。分析常量时必须先读取置换表,再按逻辑下标取数据,直接查看 `data` 开头会看到大量无效零值。 输入按十六进制逐字符执行 `value = value * 16 + digit`,随后按大端序还原成 44 字节。程序先检查两个完整性条件: ```text 全部 44 字节异或值 = 0x8F s = 0 for b in data: s = (s + b * ((s & 0x7F) + 1)) & 0xFFFF 最终 s = 0xBEFF ``` ## 最终字节置换 最终比较的目标明文为: ```text Welcome to KCTF2026! Come and give it a try. ``` 每个待比较字节经过如下变换: ```text output = data[perm[input_byte - 1]] ``` 枚举合法的单字节下标并反查目标明文,可以唯一得到变换前的 44 字节: ```text 323c47184b0d3c44254b445842552f365c362c1144424b0d3c441643 0f4439374e3c44372544164425151d1b ``` 前 28 字节就是序列号解码后的前 28 字节。后 16 字节来自一次固定 RSA 模幂,会覆盖序列号解码结果的最后 16 字节。 ## RSA 逆运算 从置换存储的大整数中按逻辑顺序恢复出以下常量: ```text n = 0x8c91cb79ec693f3ed6519c945dd67371 e = 65537 c = 0x0f4439374e3c44372544164425151d1b ``` 程序计算 `c = m^e mod n`。模数分解为: ```text p = 13636154180376482939 q = 13702465297157554691 ``` 计算私钥指数并解密: ```text d = e^(-1) mod ((p - 1)(q - 1)) m = c^d mod n = 0x3b0dd6b12a0d3d95fa65b5e0ade5e11b ``` 将前 28 字节与恢复出的 16 字节拼接,再编码为大写十六进制,即得到序列号。 ## Exp ```python #!/usr/bin/env python3 from functools import reduce from operator import xor TARGET = b"Welcome to KCTF2026! Come and give it a try." # Inverse images of TARGET under data[perm[input_byte - 1]]. MAPPED_PREIMAGE = bytes.fromhex( "323c47184b0d3c44254b445842552f365c362c1144424b0d3c441643" "0f4439374e3c44372544164425151d1b" ) P = 13636154180376482939 Q = 13702465297157554691 N = 0x8C91CB79EC693F3ED6519C945DD67371 E = 0x10001 def rolling_checksum(data: bytes) -> int: value = 0 for byte in data: value = (value + byte * ((value & 0x7F) + 1)) & 0xFFFF return value def solve() -> str: assert P * Q == N assert len(TARGET) == len(MAPPED_PREIMAGE) == 44 ciphertext = int.from_bytes(MAPPED_PREIMAGE[28:], "big") phi = (P - 1) * (Q - 1) d = pow(E, -1, phi) message = pow(ciphertext, d, N) rsa_plaintext = message.to_bytes(16, "big") key_bytes = MAPPED_PREIMAGE[:28] + rsa_plaintext key = key_bytes.hex().upper() transformed = key_bytes[:28] + pow( int.from_bytes(key_bytes[28:], "big"), E, N ).to_bytes(16, "big") assert transformed == MAPPED_PREIMAGE assert reduce(xor, key_bytes, 0) == 0x8F assert rolling_checksum(key_bytes) == 0xBEFF assert len(key) == 88 return key if __name__ == "__main__": print(solve()) ``` ## Flag ```text 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B ```
登录后可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
0
点赞
・
0
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
mxym_
2
11
发帖
2
回帖
120
RANK
关注
私信
他的文章
[原创] 第十题:卯时·曦光初现 WP
1515
[原创]第九题:丑寅同墟·星海抉择 WP
64
[原创]第八题:亥子合辰·塔影迷楼 WP
44
[原创]第七题:戌时·暗能潜流
19
[原创]第六题:酉时·书院迷局 WP
1502
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部