首页
社区
课程
招聘
[原创]KCTF2026 第5题 解析
发表于: 23小时前 130

[原创]KCTF2026 第5题 解析

23小时前
130

题目cm.exe(看雪 / KCTF 2026,规则 5.1.1)
样本 SHA1d1c8124c5964af1531c6e311328854a05ca40bca(与 readme.txt 一致)
判胜条件:运行程序,输入序列号后回车,输出 verify success.
结论状态:已在原版 cm.exe 与工作副本上独立验证通过

本地复现:

期望输出:

一键脚本见同目录 solve.py

程序中嵌入大量误导信息,不是真校验路径:

真逻辑在主校验函数(约 0x403D90 起)的线性路径中,并带有控制流花指令(ret; mov edi,edi; jmp; stc 垫片)。

整体流水线:

对解码得到的 44 字节 b[0..43]

动态确认方式:Frida 挂钩模幂例程 0x402510,转储 limb,得到 e=65537n 的 4 个 32-bit limb,并用已知 (m,c) 对验证 pow(m,e,n)==c

覆盖完成后:

静态表(ImageBase 0x400000):

因此可对 Welcome 每个字符反查最小 idx,令 key[i] = idx + 1,得到「查表成功」所需的最终 44 字节 final

注意:final[0..27] 来自输入前缀(RSA 不改);final[28..43] 必须等于 RSA 输出 c,故输入后缀应取:

碰巧本样本在该构造下 XOR / 加权约束自动满足,无需再搜索多解。

完整实现:答案提交/solve.py

详见同目录 工具与环境.md。摘要:

本题是「自定义大整数 + 128-bit RSA + 置换查表」组合的序列号校验。表面 SEH/strcmp 注释为诱饵;核心是还原 44 字节最终形态,再对 RSA 段求逆。模数仅 128 位,分解成本极低,适合作为 CTF 可解的 RSA 变体。

一键求解脚本 solve.py 仅需

项目 结论
格式 PE32 控制台程序,MSVC(VCRUNTIME140)
入口 EP RVA 0x4D00,ImageBase 0x400000(有 ASLR)
加壳 无明显壳 / 无 overlay
输入 gets_s,提示 Enter your key:
PDB ...\rsa_tf-20260802\Release\ca_tf6.pdb(暗示 RSA)
成功串 verify success.
目标明文 Welcome to KCTF2026! Come and give it a try.(44 字节)
VA 内容
0x4163B0 置换 P,为 0..0x3FFF 的排列
0x4263B0 字节表 DATA(可打印 ASCII 等)
0x416380 目标串 Welcome…
类别 工具
静态 Python、pefileCapstone(去花指令反汇编)
动态 Frida(校验点 / 模幂 / keybuf 覆盖观测)
密码 sympy.factorint(128-bit RSA)
辅助 z3(构造过校验的测试向量)
验证 subprocess 调用原 cm.exe
文件 说明
答案提交/解题分析.md 本文(分析文章)
答案提交/工具与环境.md 工具、依赖、关键地址
答案提交/solve.py 一键求 key 并调用原程序验证
答案提交/README.md 提交材料目录说明
FLAG_RESULT.md 简洁结论与复现命令(题根目录)
work/ 分析过程脚本与反汇编草稿(可选附录,非提交必需)
项目 说明
系统 Windows 10/11 x64
样本 cm.exe(SHA1 d1c8124c5964af1531c6e311328854a05ca40bca,与题目 readme 一致)
Python 3.10+(本机实测 3.14 可用)
工具 用途
pefile PE 节区、导入表、RVA/文件偏移、字符串定位
Capstone x86 反汇编;配合脚本去除 ret; mov edi,edi; jmp; stc 花指令
Frida 动态挂钩:XOR/加权校验、RSA 模幂入口、limb 转储、覆盖前后 keybuf
sympy 分解 128-bit 模数 n,求 RSA 私钥指数 d
z3-solver 早期构造满足 XOR/加权约束的测试向量(辅助动态分析)
Python 标准库 subprocess 喂入序列号验证 verify success.
地址 含义
0x403D90 主校验函数附近
0x402100 十六进制字符串 → 大整数
0x402510 模幂 m^e mod n
0x403500 RSA 包装(后缀 hex → 加密 → 写回)
0x4033D0 安装查表对象(指向 P/DATA)
0x404870 查表 DATA[P[idx]]
0x416380 目标串 Welcome to KCTF2026! ...
0x4163B0 置换表 P(0..16383 的排列)
0x4263B0 字节表 DATA(可打印 ASCII 等)
323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B
echo 323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B| cm.exe
Enter your key:
verify success.
88 个十六进制字符
    │  parse(base16 → 大整数 → 44 字节缓冲)
    ▼
keybuf[0..43](44 字节)
    │  ① XOR 全字节 == 0x8F
    │  ② 递推加权低 16 位 == 0xBEFF
    ▼
取后 16 字节 m,做 RSA:c = m^e mod n(e=65537)
    │  用 c 的大端 16 字节覆盖 keybuf[28..43]
    ▼
对最终 44 字节逐字节查表:
    out[i] = DATA[ P[ (int8)keybuf[i] - 1 ] ]
    (有效 key 字节 ∈ [1,127])
    ▼
out == "Welcome to KCTF2026! Come and give it a try."
    ▼
打印 verify success.
sum = 0
for each byte b:
    sum = sum + ((sum & 0x7F) + 1) * b
要求 (sum & 0xFFFF) == 0xBEFF
n = 0x8c91cb79ec693f3ed6519c945dd67371
e = 65537
p = 0xbd3d59fac7cc547b
q = 0xbe28ef96c8318203
d = 0x721a022d849de5cc5ad9bbb701f9fb65
idx = (signed char)keybuf[i] - 1
out[i] = *(DATA + P[idx])    // idx 需落在合法范围;key∈[1,127]
m = pow(final[28..43]_as_int, d, n)

冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

最后于 6小时前 被kanxue编辑 ,原因:
上传的附件:
收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回