首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
0
6
[原创]KCTF 2026 - 签到题:辰时·钟鸣破晓 分析
发表于: 2026-8-12 11:17
156
[原创]KCTF 2026 - 签到题:辰时·钟鸣破晓 分析
V1NKe
2
2026-8-12 11:17
156
## 1. 题目信息 | 项目 | 内容 | |------|------| | 题目名称 | KCTF 2026 - Rosetta Calibration | | 二进制文件 | `kctf_rosetta.exe` | | 架构 | x86-64 (PE64) | | SHA256 | `caaa1c964b15d9b3250be0dc64412e5f64c29e297a971c226e8dd705d6b87e67` | | 公共有效对 | Name: `CAAA1C964B15D9B3` / Serial: `$/.;-):,(-#!%*-&?+@` | | 目标 | 求出 Name `KCTF` 对应的唯一 Serial | ## 2. 二进制概览 | 指标 | 数值 | |------|------| | 函数总数 | 5 | | 字符串总数 | 12 | | 代码段 | `.text` (0x140001000–0x140002000, 4KB) | | 只读数据段 | `.rdata` (0x140002000–0x140003000) | | 导入函数 | `GetStdHandle`, `ReadFile`, `WriteFile`, `ExitProcess` (均来自 KERNEL32.dll) | | 入口点 | `start` (0x140001000) | 程序无 CRT 依赖,直接使用 Windows API 进行 I/O,是一个纯手写的紧凑验证器。 ## 3. 函数清单 | 地址 | 名称 | 大小 | 功能 | |------|------|------|------| | 0x140001000 | `start` | 905B | 主函数:读取 Name/Serial,执行全部校验逻辑 | | 0x140001390 | `sub_140001390` | 68B | WriteFile 封装(打印字符串) | | 0x1400013E0 | `sub_1400013E0` | 318B | 核心算法:由 Name 计算期望排列 | | 0x140001520 | `sub_140001520` | 28B | 符号→值映射(含特殊 XOR 处理) | | 0x140001540 | `sub_140001540` | 27B | 查表:ASCII 字符 → 值 0-15 或 -1 | ## 4. 主流程分析 (`start`) ### 4.1 输入读取 程序依次提示并读取两行输入: ``` Name : <用户输入 Name> Serial : <用户输入 Serial> ``` - Name 存入栈缓冲区 `v16`,长度记录于 `v4`(最大 39 字节,`v4 + 1 <= 0x27`)。 - Serial 存入栈缓冲区 `NumberOfBytesWritten`,长度记录于 `n19`(最大 47 字节,`n19 + 1 <= 0x2F`)。 - 读取以 CR(`\r`)或 LF(`\n`)作为行尾终止符。 ### 4.2 Name 格式校验 ```c if ( v4 - 33 >= 0xFFFFFFE0 ) // 无符号比较,等价于 1 <= v4 <= 32 ``` - Name 长度必须为 1–32。 - 每个字符须满足 `(unsigned char)(c - 33) < 0x5E`,即 ASCII 33–126(可打印非空白字符)。 - 若不满足,输出 `[-] Invalid name format.` 并 `ExitProcess(2)`。 ### 4.3 Serial 格式校验 Serial 必须恰好 19 字符,结构为: ``` SSSS-SSSSS-SSSSS-SS ^ ^ ^ 位置 4/9/14 为 '-' 分隔符 ``` 关键常量 `n16912 = 16912 = 0x4210`,其二进制位 4、9、14 置 1,标记分隔符位置。 ```c n19 == 19 // 长度校验 while ( n0xE > 14 || !_bittest(&n16912, n0xE) ) // 非分隔符位置 n0xF = sub_140001520(serial[n0xE]); // 符号→值 if ( n0xF > 0xF || _bittest(&n0xFFFF, n0xF) ) // 值须 0-15 且不重复 goto error; n0xFFFF |= 1 << n0xF; // 记录已用值 lpBuffer_[n16++] = n0xF; // 存入解码数组 // 分隔符位置 if ( serial[n0xE] != '-' ) goto error; // 必须为 '-' ``` 最终校验 `n16 == 16 && n0xFFFF == 0xFFFF`:恰好 16 个符号,值 0-15 各出现一次(构成排列)。 ### 4.4 核心验证 ```c sub_1400013E0(name, name_len, &Buffer); // 由 Name 计算期望排列 → Buffer if ( _mm_movemask_epi8( _mm_cmpeq_epi8( _mm_load_si128(&lpBuffer_), // Serial 解码出的排列 Buffer // Name 计算出的期望排列 ) ) == 0xFFFF ) // 16 字节完全相等 { // 成功:Calibration accepted } ``` 使用 SSE2 `pcmpeqb` + `pmovmskb` 做一次性 16 字节比较,`0xFFFF` 表示全等。 ## 5. 符号映射表 ### 5.1 查表函数 `sub_140001540` ```asm add cl, 0DFh ; cl = c - 33 mov eax, 0FFFFFFFFh ; 默认返回 -1(无效) cmp cl, 1Fh ja ret ; 若 c-33 > 31 则无效 movzx eax, cl lea rcx, dword_140002000 mov eax, [rcx+rax*4] ; 查表 ret ``` ### 5.2 XOR 处理函数 `sub_140001520` ```c __int64 sub_140001520(char c) { return (c == '(') ^ (unsigned int)sub_140001540(c); } ``` 当字符为 `(` (ASCII 40) 时,查表值 3 与 1 异或,结果为 2。其余字符不受影响。 ### 5.3 完整映射表 数据位于 `0x140002000`,32 个 DWORD 条目,覆盖 ASCII 33–64: | 符号 | ASCII | 表索引 | 查表值 | XOR | 最终值 | |------|-------|--------|--------|-----|--------| | `!` | 33 | 0 | 4 | 0 | **4** | | `"` | 34 | 1 | -1 | — | 无效 | | `#` | 35 | 2 | 7 | 0 | **7** | | `$` | 36 | 3 | 12 | 0 | **12** | | `%` | 37 | 4 | 1 | 0 | **1** | | `&` | 38 | 5 | 9 | 0 | **9** | | `'` | 39 | 6 | -1 | — | 无效 | | `(` | 40 | 7 | 3 | 1 | **2** | | `)` | 41 | 8 | 11 | 0 | **11** | | `*` | 42 | 9 | 14 | 0 | **14** | | `+` | 43 | 10 | 6 | 0 | **6** | | `,` | 44 | 11 | 13 | 0 | **13** | | `-` | 45 | 12 | -1 | — | 无效(分隔符) | | `.` | 46 | 13 | 8 | 0 | **8** | | `/` | 47 | 14 | 10 | 0 | **10** | | `0`–`8` | 48–56 | 15–23 | -1 | — | 无效 | | `9` | 57 | 24 | -1 | — | 无效 | | `:` | 58 | 25 | 15 | 0 | **15** | | `;` | 59 | 26 | 5 | 0 | **5** | | `<` | 60 | 27 | -1 | — | 无效 | | `=` | 61 | 28 | -1 | — | 无效 | | `>` | 62 | 29 | -1 | — | 无效 | | `?` | 63 | 30 | 0 | 0 | **0** | | `@` | 64 | 31 | 3 | 0 | **3** | 有效符号共 16 个,映射到值 0–15 形成双射: | 值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |----|---|---|---|---|---|---|---|---|---|---|----|----|----|----|----|----| | 符号 | `?` | `%` | `(` | `@` | `!` | `;` | `+` | `#` | `.` | `&` | `/` | `)` | `$` | `,` | `*` | `:` | ## 6. 核心算法 `sub_1400013E0` ### 6.1 算法概述 该函数以 Name 为输入,输出一个 16 字节的排列(值 0–15 的置换)。 算法分为两阶段: 1. **Fisher-Yates 式洗牌**:以 `[0,1,...,15]` 为初始状态,遍历 Name 的每个字符,根据字符值交换状态数组中的元素。 2. **旋转输出**:将洗牌后的状态按累加和 `v5 & 0xF` 旋转,作为最终排列。 ### 6.2 伪代码 ``` 输入: name[0..n-1], n 输出: perm[0..15] state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] v3 = 0 // 计数器,每轮 +3 v5 = 0 // 累加器 for v4 = 0 to n-1: c = name[v4] v6 = c XOR (c >> 4) // 字符混合 v5 = (v5 + v6) mod 256 // 累加(8位) v7 = (v3 XOR v6) AND 0xF // 交换目标索引 swap(state[v4 AND 0xF], state[v7]) v3 = v3 + 3 rot = v5 AND 0xF for i = 0 to 15: perm[i] = state[(rot + i) AND 0xF] ``` > **注意**:当 Name 长度超过 16 时,`v4 & 0xF` 会回绕,同一位置可能被多次交换。 ### 6.3 数据初始化 初始状态 `xmmword_140002080` 位于 `0x140002080`,内容为: ``` 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ``` 即 `[0, 1, 2, ..., 15]`,通过 `movdqa` 一次性加载。 ## 7. 验证公共对 ### 7.1 Serial 解码 公共 Serial `$/.;-):,(-#!%*-&?+@`(19 字符): | 位置 | 符号 | 值 | |------|------|----| | 0 | `$` | 12 | | 1 | `/` | 10 | | 2 | `.` | 8 | | 3 | `;` | 5 | | 4 | `-` | 分隔符 | | 5 | `)` | 11 | | 6 | `:` | 15 | | 7 | `,` | 13 | | 8 | `(` | 2 | | 9 | `-` | 分隔符 | | 10 | `#` | 7 | | 11 | `!` | 4 | | 12 | `%` | 1 | | 13 | `*` | 14 | | 14 | `-` | 分隔符 | | 15 | `&` | 9 | | 16 | `?` | 0 | | 17 | `+` | 6 | | 18 | `@` | 3 | 解码排列:`[12, 10, 8, 5, 11, 15, 13, 2, 7, 4, 1, 14, 9, 0, 6, 3]` ### 7.2 Name 计算 对 Name `CAAA1C964B15D9B3`(16 字符)执行算法: | 轮次 | 字符 | ASCII | v6=c^(c>>4) | v5(累加) | v3 | v7=(v3^v6)&0xF | 交换位置 | state 变化 | |------|------|-------|-------------|----------|----|----------------|----------|-----------| | 0 | C | 67 | 71 | 71 | 0 | 7 | [0]↔[7] | [7,1,2,3,4,5,6,0,...] | | 1 | A | 65 | 69 | 140 | 3 | 6 | [1]↔[6] | [7,6,2,3,4,5,1,0,...] | | 2 | A | 65 | 69 | 209 | 6 | 3 | [2]↔[3] | [7,6,3,2,4,5,1,0,...] | | 3 | A | 65 | 69 | 278 | 9 | 12 | [3]↔[12] | [7,6,3,12,...,2,...] | | 4 | 1 | 49 | 50 | 328 | 12 | 14 | [4]↔[14] | [...,14,...,4,...] | | 5 | C | 67 | 71 | 399 | 15 | 8 | [5]↔[8] | [...,8,...,5,...] | | 6 | 9 | 57 | 58 | 457 | 18 | 8 | [6]↔[8] | [...,5,...,1,...] | | 7 | 6 | 54 | 53 | 510 | 21 | 0 | [7]↔[0] | [0,...,7,...] | | 8 | 4 | 52 | 55 | 565 | 24 | 15 | [8]↔[15] | [...,15,...,1] | | 9 | B | 66 | 70 | 635 | 27 | 13 | [9]↔[13] | [...,13,...,9,...] | | 10 | 1 | 49 | 50 | 685 | 30 | 12 | [10]↔[12] | [...,2,...,10,...] | | 11 | 5 | 53 | 54 | 739 | 33 | 7 | [11]↔[7] | [...,11,...,7,...] | | 12 | D | 68 | 64 | 803 | 36 | 4 | [12]↔[4] | [...,10,...,14,...] | | 13 | 9 | 57 | 58 | 861 | 39 | 13 | [13]↔[13] | (无变化) | | 14 | B | 66 | 70 | 931 | 42 | 12 | [14]↔[12] | [...,4,...,14,...] | | 15 | 3 | 51 | 48 | 979 | 45 | 13 | [15]↔[13] | [...,1,...,9] | 最终 state = `[0, 6, 3, 12, 10, 8, 5, 11, 15, 13, 2, 7, 4, 1, 14, 9]` 旋转量 `rot = 979 & 0xF = 3` 输出排列 `perm[i] = state[(3+i) & 0xF]`: ``` [12, 10, 8, 5, 11, 15, 13, 2, 7, 4, 1, 14, 9, 0, 6, 3] ``` 与 Serial 解码排列完全一致,**验证通过**。 ## 8. 求解 Name = KCTF ### 8.1 执行算法 Name `KCTF`(4 字符),ASCII: K=75, C=67, T=84, F=70 | 轮次 | 字符 | ASCII | v6=c^(c>>4) | v5(累加) | v3 | v7=(v3^v6)&0xF | 交换 | state 变化 | |------|------|-------|-------------|----------|----|----------------|------|-----------| | 0 | K | 75 | 79 | 79 | 0 | 15 | [0]↔[15] | `[15,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0]` | | 1 | C | 67 | 71 | 150 | 3 | 4 | [1]↔[4] | `[15,4,2,3,1,5,6,7,8,9,10,11,12,13,14,0]` | | 2 | T | 84 | 81 | 231 | 6 | 7 | [2]↔[7] | `[15,4,7,3,1,5,6,2,8,9,10,11,12,13,14,0]` | | 3 | F | 70 | 66 | 297 | 9 | 11 | [3]↔[11] | `[15,4,7,11,1,5,6,2,8,9,10,3,12,13,14,0]` | 最终 state = `[15, 4, 7, 11, 1, 5, 6, 2, 8, 9, 10, 3, 12, 13, 14, 0]` 旋转量 `rot = 297 & 0xF = 9` 输出排列 `perm[i] = state[(9+i) & 0xF]`: | i | (9+i)&0xF | state[...] | 值 | |---|-----------|------------|----| | 0 | 9 | state[9] | 9 | | 1 | 10 | state[10] | 10 | | 2 | 11 | state[11] | 3 | | 3 | 12 | state[12] | 12 | | 4 | 13 | state[13] | 13 | | 5 | 14 | state[14] | 14 | | 6 | 15 | state[15] | 0 | | 7 | 0 | state[0] | 15 | | 8 | 1 | state[1] | 4 | | 9 | 2 | state[2] | 7 | | 10 | 3 | state[3] | 11 | | 11 | 4 | state[4] | 1 | | 12 | 5 | state[5] | 5 | | 13 | 6 | state[6] | 6 | | 14 | 7 | state[7] | 2 | | 15 | 8 | state[8] | 8 | 期望排列:`[9, 10, 3, 12, 13, 14, 0, 15, 4, 7, 11, 1, 5, 6, 2, 8]` ### 8.2 排列转 Serial 将 16 个值按值→符号反查表编码,并按 `SSSS-SSSSS-SSSSS-SS` 格式插入分隔符: | Serial 位置 | 值 | 符号 | |-------------|----|------| | 0 | 9 | `&` | | 1 | 10 | `/` | | 2 | 3 | `@` | | 3 | 12 | `$` | | 4 | — | `-` | | 5 | 13 | `,` | | 6 | 14 | `*` | | 7 | 0 | `?` | | 8 | 15 | `:` | | 9 | — | `-` | | 10 | 4 | `!` | | 11 | 7 | `#` | | 12 | 11 | `)` | | 13 | 1 | `%` | | 14 | — | `-` | | 15 | 5 | `;` | | 16 | 6 | `+` | | 17 | 2 | `(` | | 18 | 8 | `.` | ### 8.3 最终答案 ``` Name : KCTF Serial : &/@$-,*?:-!#)%-;+(. ``` ## 9. 算法流程图 ``` ┌─────────────────────────────────────────────────┐ │ 输入: Name (1-32 字符, 可打印 ASCII 33-126) │ │ 输入: Serial (19 字符, 含 3 个 '-' 分隔符) │ └──────────────────────┬──────────────────────────┘ │ ┌─────────────▼──────────────┐ │ Serial 解码 │ │ 16 符号 → 值 0-15 (双射) │ │ 查表 0x140002000 │ │ '(' 特殊 XOR 处理 │ │ 须为完整排列 (0-15 各一次) │ └─────────────┬──────────────┘ │ ┌─────────────▼──────────────┐ │ Name → 期望排列 │ │ sub_1400013E0: │ │ 1. 初始 state = [0..15] │ │ 2. 逐字符 Fisher-Yates 洗牌 │ │ 3. 按累加和旋转输出 │ └─────────────┬──────────────┘ │ ┌─────────────▼──────────────┐ │ SSE2 16 字节比较 │ │ pcmpeqb + pmovmskb == 0xFFFF│ └─────────────┬──────────────┘ │ ┌────────┴────────┐ │ │ 匹配 ✓ │ │ 不匹配 ✗ ▼ ▼ "Calibration "Calibration accepted" rejected" ``` ## 10. 关键数据地址 | 地址 | 内容 | |------|------| | `0x140002000` | 符号查表(32 个 DWORD) | | `0x140002080` | 初始状态 `[0,1,...,15]`(16 字节) | | `0x140002090` | 字符串 `"Serial : "` | | `0x14000209A` | 字符串 `"Name : "` | | `0x1400020A4` | 字符串 `"[-] Calibration rejected..."` | | `0x1400020D1` | 字符串 `"[-] Invalid name format..."` | | `0x1400020EE` | 字符串 `"[-] The inscription..."` | | `0x14000211C` | 字符串 `"[+] The symbols have found..."` | | `0x140002173` | Banner 字符串 | ## 11. 注 由 AI 完成。
回复或点赞可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
0
点赞
・
6
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
git_51951meggadf3df
非常支持你的观点!
4天前
mb_lthgjpwj
为你点赞!
2026-8-21 07:34
huangyalei
谢谢你的细致分析,受益匪浅!
2026-8-17 16:20
Kcuaghx
你的分享对大家帮助很大,非常感谢!
2026-8-15 13:44
工丁
你的帖子非常有用,感谢分享!
2026-8-13 13:51
微笑:)
非常支持你的观点!
2026-8-13 11:38
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
1
)
xingbing
雪 币:
158
活跃值:
(5651)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
1373
粉丝
2
关注
私信
xingbing
2
楼
感谢分享
2026-8-12 14:39
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
V1NKe
2
12
发帖
56
回帖
196
RANK
关注
私信
他的文章
[原创]KCTF 2026 - 第十题:卯时·曦光初现 分析
212
[原创]KCTF 2026 - 第九题:丑寅同墟·星海抉择 分析
26
[原创]KCTF 2026 - 第二题:巳时·绿光幽语 分析
715
[原创]KCTF 2026 - 签到题:辰时·钟鸣破晓 分析
156
[原创]Tcache利用总结
17998
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部