首页
社区
课程
招聘
[讨论] 看雪.安恒2020 KCTF春季赛 > 第七题 杯弓蛇影
2020-4-30 08:05 4322

[讨论] 看雪.安恒2020 KCTF春季赛 > 第七题 杯弓蛇影

2020-4-30 08:05
4322

看雪.安恒2020 KCTF春季赛 > 第七题 杯弓蛇影

观察

下载得到的是一个输入用户名和序列号输出是否正确的控制台应用程序,注意到程序需要运行非常久(10秒以上)才能输出判断结果。
简单丢进 IDA 看一下会发现有壳,不过壳的代码没有混淆。

分析

壳的代码里有一堆偏门的反调试,但都没什么用。随便开了个调试器它就检测不出来。找到处理输入表的函数 0x460BC0,稍微分析一下可以找到 magic jump,nop 掉 0x460CD3 处的 jnz 即可。接下来在 0x460EC2 下断,Step Into 到 OEP 处,直接 Scylla dump + 自动修 IAT 即可脱壳。

 

里面的程序简单分析下,核心是把输入的用户名胡乱算某种 hash 之后和序列号一起丢进一个 VM 做一些奇怪的运算,要求出来的结果满足一定条件。可以直接用给出的参考用户名和序列号把需要满足的条件 dump 出来,比较省事。
剩下的部分,这个 VM 比较简单,可以手撕。interp 大循环在 0x40E2B0,先对着写指令解码,然后把每个用到了的指令的长度搞对,一共只有 34 条,接下来看一下 handler 把指令的语义整理出来,简单写个程序“反汇编”一下(见附件)即可。

 

VM 里面的程序里有一大段的无用指令。有用的部分只有最后的很短一部分,是在 Z_p (p = 4294967291) 上的简单运算。

解决

import struct

u32 = lambda x: struct.unpack('<I', x)[0]
F = Zmod(0xfffffffb)

username_serial_part2 = bytes.fromhex("63 E4 C3 D9 78 AF C9 11 9E BF 85 64 5D D0 4B FF 26 97 76 65 88 89 C3 F5 23 24 3A BF C0 8C 71 4B 49 8F 0D C7 15 33 C7 DF 70 00 47 74 71 9F B8 94 B1 F6 60 0E 22 A1 51 20 47 10 06 1F 38 9E ED 4C F9 49 87 4F CA C8 78 BE F9 8A 4B 3B 78 43 D5 6B 48 93 78 CF 82 6B 49 18 66 0B 8C 72 04 51 20 28 01 FC 16 58 82 69 5C CB D5 2A C7 54 6B FC 9F E7 61 D7 E1 EC C9 0D 9E CA CA A2 7A 0A CE 2A 95 50 5B D5 99 6E B1 D8 7A 6A BF 10 55 D1 05 4E 6A 0B 2E AB 0C 68 C5 D7 65 05 A0 68 76 0D CD 67 41 8E 62 A6 3B 86 A4 7C 59 D7 1E 49 EC 5D 86 36 5B 65 E0 1E E4 A1 3B 66 C9 27 A9 14 82 44 8B 08 0E 31 83 4A 7D EF 93 3D 53 CB 07 61 E4 06 81 CC 24 62 B5 11 FA 98 06 66 D6 75 B7 F0 18 3C DC 0B A0 9D 98 FC 34 82 53 62 88 B5 CA 8C B2 5F 1E 16 B4 9C 32 EC FA 62 3F 15 C1 8E CE A2 D7 3B C8 5F D6 D0 BB F4 2A 59 70 EC 46 8E 0F 9F 50 2C A3 49 27 DD 0D 96 20 A0 58 81 57 15 FE 81 46 29 28 E2 CC E4 FD BF 95 DB 09 EF 60 9C FC 57 22 51 D6 70 C7 62 A5 A9 4B A7 97 1C 25 7B A8 2A 6C 93 FC 56 70 71 C7 2B 2A 67 18 DF 1D 9F C7 8E D4")
salt = [
  "E1 04 59 83 4B 94 34 C8 E0 19 7A 02 A3 08 B3 FE 95 F1 1F 62 5C 5C 70 4B D0 D9 B5 3E F4 73 5C 9A",
  "0F A0 FF CC ED 46 0C 49 A1 E5 8B F7 74 62 A5 81 5C EB 5D 16 96 67 F4 F6 46 51 DE 44 4C 98 E4 00",
  "A8 DF 77 DF D8 D8 0E AE 54 A3 4D 06 CC 95 8B 4C 39 CA 34 F9 04 DE E9 C4 93 27 EE 18 C2 C9 5A 94",
]
salt = [bytes.fromhex(x) for x in salt]

wanted = [
  "FB 1E 07 C5 A4 91 2E C3 A4 CC 5F A8 E3 D3 C8 16 13 35 2A 90 3C D4 D5 0B 6A 59 D8 7B 78 75 AE 66 14 15 25 D6 13 35 2A 10 95 BE 08 68 39 A5 DB 00 3F B8 E6 18",
  "FA 34 2A 9F 63 28 60 BB 18 6C 14 BD 20 DA EE F9 27 16 74 97 06 84 F8 4A BB 91 CC 01 D2 D8 E8 01 E4 14 2A 4C 27 96 8A 2B A2 31 C6 3E 6E 23 7C 9E 52 D1 DC ED",
  "E3 52 68 C5 0A D9 4C F1 43 95 D0 73 81 AB 48 30 48 CF BE 80 17 EF A7 7D D2 62 B4 45 BB 2D 75 BB 25 18 E4 84 48 CF BE 00 0D 78 04 33 AC 28 B2 65 00 7E 9C 53",
]
wanted = [bytes.fromhex(x) for x in wanted]

for i in range(13):
  v = vector([u32(username_serial_part2[i*4:i*4+4]) ^^ u32(wanted[j][i*4:i*4+4]) for j in range(3)])
  mat = matrix(F, 3, 3, lambda x, y: F(u32(salt[x][i%8*4:i%8*4+4])) ** y)
  print("".join(["{:08X}".format(int(x)) for x in mat.solve_right(v)]), end="")

print()

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回