-
-
[原创]申时·忆海倒带— WriteUp
-
发表于: 2026-8-17 14:55 69
-
目标程序:cm.exe(SHA1: d1c8124c5964af1531c6e311328854a05ca40bca)
判胜条件:输入 Key 后程序输出 verify success. 即成功。
工具:IDA Pro(ida-pro-mcp)、Python
程序主体是一个自研的 2048-limb 大整数运算库(limb 存储带随机置换,但对数值无影响,可等价为普通小端大整数)。main 反编译后的大致流程如下:
注意:二进制中混入了大量伪造提示字符串(如"// FIXME: author confirmed password is 'admin123'"、"TODO: exception handler contains real verification logic"、"NOTE: the int3 in __try is just obfuscation..."),
均无实际作用,全部是干扰项,可直接忽略。
sub_403500(a1=&var_92C, a2=&Buffer[56]):
模数 n 的 4 个 limb(经 perm 索引后取值):
main 中最终比对前的查表逻辑(0x4044F8 附近):
sub_404870(this=&v81, a2):
&v81 是一个由 sub_4033D0 从全局 0x438030 复制的 20 字节容器描述符:
即:v88[i] = byte[0x4263B0 + dword[0x4163B0 + 4*(ArgList[i]-1)]]
定义查表 T[j] = byte[0x4263B0 + table[j]](table 为 0x4163B0 处 dword 数组),
从 IDA 内存提取得到 0..94 项是 95 个互不相同的可打印 ASCII,95..255 均为 0:
因此目标串的每个字符在 T 中都有唯一原像 j,要求 ArgList[i] = j+1。
对目标串 "Welcome to KCTF2026! Come and give it a try." 的每个字节 c,
取 ArgList[i] = invT[c] + 1(invT 为 T 的逆映射):
用 Pollard Rho / sympy 分解 128 位模数:
因为程序计算 R = M^e mod n,所以:
校验(全部通过):
| perm | 数据地址 | limb 值 |
|---|---|---|
| 145 | 0x43625C | 0x5DD67371 |
| 6 | 0x436030 | 0xD6519C94 |
| 101 | 0x4361B4 | 0xEC693F3E |
| 2037 | 0x437FF4 | 0x8C91CB79 |
1. 打印 "Enter your key:"
2. gets_s 读入输入 → Buffer
3. 将输入按 hex 解析为大整数 v76(乘 16 + 加 digit 逐位构建)
4. 校验输入合法性与长度:
for (n = 8*v76; ...) 检查每个字符 ∈ [0-9A-Z]
if (n != 88) fail // 输入必须是 88 个 hex 字符(44 字节)
5. 把 v76 的 limbs(高位 limb 优先、逐 limb 高字节优先)展开为 44 字节 ArgList
6. 校验一:ArgList 全部字节异或 == -113 (0x8F)
7. 校验二:加权校验和 v58 == 0xBEFF
8. sub_403500(&var_92C, &Buffer[56]) // 用后 32 个 hex 字符做 RSA
9. 解析 var_92C(hex 字符串)为大整数 v74
10. v74 的大端字节 → v88[0..15] → 覆盖 ArgList[28..43]
11. 最终:v88[i] = T[ArgList[i]-1](查表),strcmp 与
"Welcome to KCTF2026! Come and give it a try." 比对
n = 0x8C91CB79EC693F3ED6519C945DD67371
e = 65537
v88[i] = *(BYTE*)sub_404870(ArgList[i] - 1); // i = 0..43
strcmp("Welcome to KCTF2026! Come and give it a try.", v88)
if (a2 < *this) return *(this+1) + sub_402D70(a2); // 0x4263B0 + perm[a2]
else return *(this+1);
T[0..94] = {, - ] x ) 8 $ ~ R L " A m } d ; ! u b Z r a ' c 4 9 . P y [ & G X ` s N t + 5 | { J M 6 % \ F < S W : f V 2 i / g H I e B 7 Q = _ C n SP k ? l U 1 E o # q v O @ p w h 3 T z Y K D ( > 0 * ^ j}
ArgList = [50,60,71,24,75,13,60,68,37,75,68,88,66,85,47,54,92,54,44,17,68,66,75,13,60,68,22,67,
15,68,57,55,78,60,68,55,37,68,22,68,37,21,29,27]
R = 0x0F4439374E3C44372544164425151D1B
n = 0x8C91CB79EC693F3ED6519C945DD67371
e = 65537
# 分解结果
p = 0xBD3D59FAC7CC547B
q = 0xBE28EF96C8318203
phi = (p-1)*(q-1)
d = pow(e, -1, phi) # d = 0x721A022D849DE5CC5AD9BBB701F9FB65
M = pow(R, d, n)
M_bytes = M.to_bytes(16, 'big')
# 3b 0d d6 b1 2a 0d 3d 95 fa 65 b5 e0 ad e5 e1 1b
key = key28 + list(M_bytes)
hexkey = bytes(key).hex().upper()
$ printf '323C47184B0D3C44254B445842552F365C362C1144424B0D3C4416433B0DD6B12A0D3D95FA65B5E0ADE5E11B\n' | ./cm.exe
Enter your key:
verify success.
# ---- 1. 从 IDA 提取 T 表 ----
# T[j] = byte[0x4263B0 + dword[0x4163B0 + 4*j]],j = 0..255
T = [44,45,93,120,41,56,36,126,82,76,34,65,109,125,100,59,33,117,98,90,
114,97,39,99,52,57,46,80,121,91,38,71,88,96,115,78,116,43,53,124,
123,74,77,54,37,92,70,60,83,87,58,102,86,50,105,47,103,72,73,101,
66,55,81,61,95,67,110,32,107,63,108,85,49,69,111,35,113,118,79,64,
112,119,104,51,84,122,89,75,68,40,62,48,42,94,106] + [0]*(256-95)
target = b"Welcome to KCTF2026! Come and give it a try."
inv = {c: j for j, c in enumerate(T) if c != 0}
ArgList = [inv[c] + 1 for c in target]
key28 = ArgList[:28]
R_bytes = ArgList[28:44]
R = int.from_bytes(R_bytes, 'big')
# ---- 2. RSA 私钥指数 ----
n = 0x8C91CB79EC693F3ED6519C945DD67371
e = 65537
p, q = 0xBD3D59FAC7CC547B, 0xBE28EF96C8318203
d = pow(e, -1, (p-1)*(q-1))
# ---- 3. 反推 M ----
M = pow(R, d, n)
key = key28 + list(M.to_bytes(16, 'big'))
hexkey = bytes(key).hex().upper()
print(hexkey)
目标程序:
cm.exe(SHA1:d1c8124c5964af1531c6e311328854a05ca40bca)
判胜条件:输入 Key 后程序输出verify success.即成功。
工具:IDA Pro(ida-pro-mcp)、Python
注意:二进制中混入了大量伪造提示字符串(如
"// FIXME: author confirmed password is 'admin123'"、"TODO: exception handler contains real verification logic"、"NOTE: the int3 in __try is just obfuscation..."),
均无实际作用,全部是干扰项,可直接忽略。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。