-
-
[原创]第五题:申时·忆海倒带wp
-
发表于: 2026-8-17 23:23 105
-
最终 Key
323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B
思路
先拉字符串,verify success. 和 Welcome to KCTF2026! Come and give it a try. 两条引用把 main(0x403d90)锁死。校验链:
字符只认 0-9/A-Z,长度要求 88 hex(11 limb 大数)
Key 解码成 44 字节数组 var_470h,过两道校验:
校验1:44 字节折叠 XOR(16B 块异或 + psrldq 8/4/2/1)最低字节 == 0x8f
校验2:状态加权和 Σ((sum&0x7f)+1)*byte[i] 低 16 位 == 0xbeff
关键迷惑点:有个 fcn.00403500 看着像模幂,结果"丢弃"——其实不然,它的输出经 hex 串再解析成 16 字节,覆盖 var_470h[28..43]
覆盖后用双射查表,输出比对 welcome
破法
查表是双射,welcome 逆查直接定死前 28 字节(Key 前 56 hex),跟校验无关。
难点在覆盖值:真实程序里覆盖值 = RSA 模幂 pow(key[56:88], e, n) 的 hex 串解析结果。程序要求这个值 = 固定 16 字节(查表需要)。所以 key[56:88] 不是随便凑的,必须让模幂结果等于目标值。
RSA 参数从哪来:Unicorn 仿真在模幂调用点(0x403a21)hook 读栈参数,指数容器 data=0x430018、模数容器 data=0x436018。注意大数 limb 是按洗牌索引映射的(data + idx[i]*4),直接 dump 是全零假象。重映射后:
e = 0x10001
n = 0x8c91cb79ec693f3ed6519c945dd67371 (128 位!)
128 位 RSA,秒分解:
p = 0xbd3d59fac7cc547b
q = 0xbe28ef96c8318203
d = e^-1 mod φ(n) = 0x721a022d849de5cc5ad9bbb701f9fb65
目标 m = 0x0F4439374E3C44372544164425151D1B(覆盖需要的 16 字节),key[56:88] = m^d mod n = 0x3B0DD6B12A0D3D95FA65B5E0ADE5E11B。
拼起来就是上面的 Key。校验1/2 也恰好满足(这 Key 是出题人设计的正确解)。
验证
verify_key2.py:字符/长度、校验1=0x8f、校验2=0xbeff、查表前28B、RSA(c^e mod n = m)、查表28..43 覆盖值,全过
Unicorn 仿真输入 Key → verify success.
[招生]科锐逆向工程师培训(2026年11月13日实地,远程教学同时开班, 第57期)