强网杯-2022-GameMaster

二木 王者

强网杯-2022-GameMaster

刚开始看这道题的时候,其实是有点懵的,还是自己做的题太少了T _ T.就此为了加深印象,复现这道题。

丢进Exeinfo PE中,可以发现是c#写的.net程序,我们用Dnspy打开(一个专门反编译c#,.net等的一个软件)。

我们直接找到此软件的主函数,分析其逻辑

![Untitled](/Untitled 1-16954559556731.png)

这里我们可以发现,是读取了我们的附件所给的gamemesage里面的数据,读取到filestream,

Untitled

分析下面的代码,可以知道,这部分实现的代码,就是根据我们的按键,施行对应的操作,其中Enter键和space键,对应的函数下都有deal和stand,hit键,如果简单的玩过一下这个游戏,我们很容易知道,这几个函数实现的功能就是进行输赢的判断和检测自己的金钱还有多少,游戏是否继续。

Untitled

我们分析之后,发现这个esc这个键下的函数十分的可疑,我们跟进去看看。

Untitled

整体来说,这个函数并没有做什么,但是这个函数中调用的另一个函数,goldFUNC,我们继续跟进。

Untitled

发现这个函数里面全是flag判断啥的异常处理函数,这里应该就是我们关键的加密函数了,但是这些判断看起来一头雾水,我们继续分析。

Untitled

我们翻到后面我们发现了一个非常不一样的异常处理函数,而且这里出现了Program.memory,这个就是程序的开头,将我们文件读取的数据存储的地方。我们继续向下分析,看还有没有同样的操作。

Untitled

这里有一个AES-ECB的加密

Untitled

我们发现了一个函数调用,我们进去看看。

Untitled

这里也是AES-ECB加密,但是我们分析之后,我们可以发现它并没有对我们的文件的数据进行改变,因此我们不管它。

Untitled

到这里我们就可以知道了,我们的gamemesage是被加密过的文件,首先异或了34,之后又进行了AES-ECB加密,我们写一个脚本进行解密即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Cipher import AES

# 定义AES加密算法的密钥和块大小
key = b'Brainstorming!!!'
block_size = 16

# 创建AES加密算法对象
cipher = AES.new(key, AES.MODE_ECB)

# 打开待解密的文件
with open('gamemessage', 'rb') as f:
ciphertext = f.read()

# 对读取的数据进行异或操作
ciphertext = bytes([byte ^ 34 for byte in ciphertext])

# 对密文进行解密
plaintext = cipher.decrypt(ciphertext)

# 将解密后的明文写入到新文件中
with open('data', 'wb') as f:
f.write(plaintext)

将解密后的文件输出到data

我们放入winhex中分析,可以发现是.net的一个输出文件,但是并未有文件头,我们在这里面进行搜索,看看是否能找到一些看信息

Untitled

我们可以找到一个MZ的头,我们将其前面的数据删除,然后将其加入dll的后缀,因为此文件是以dll文件的形式载入我们的程序的

Untitled

我们将其放入dnspy中分析。

Untitled

有两个关键函数,分析这两个函数是将先前的三段数据进行求解,下一个函数就是将解变成密钥后对我们的数据进行异或,我们先写个脚本爆破出x,y,z.

Untitled

Untitled

Untitled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from z3 import *

x, y, z = BitVecs('x y z', 64)
s = Solver()

KeyStream = [0] * 40
key1 = [101, 5, 80, 213, 163, 26, 59, 38, 19, 6, 173, 189, 198, 166, 140, 183, 42, 247, 223, 24, 106,
20, 145, 37, 24, 7, 22, 191, 110, 179, 227, 5, 62, 9, 13, 17, 65, 22, 37, 5]

num = -1
for i in range(320):
x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
flag = i % 8 == 0
if flag:
if i!=0:
s.add(KeyStream[num] == key1[num])
num += 1
KeyStream[num] = (KeyStream[num] << 1) | (((z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1))))

print(s.check())
print(s.model())
# [y = 868387187, x = 156324965, z = 3131229747]

解出我们的x,y,z之后,在写解密脚本,解出我们的flag

1
2
3
4
5
6
7
8
9
l=[156324965, 868387187, 3131229747]
arr=[0]*12
for i in range(3):
for j in range(4):
arr[i*4+j]=(l[i]>>j*8)&0xff
enc=[60, 100, 36, 86, 51, 251, 167, 108, 116, 245,
207, 223, 40, 103, 34, 62, 22, 251, 227]
for i in range(len(enc)):
print(chr(enc[i]^arr[i%len(arr)]),end='')

即可得出flag: Y0u_@re_G3meM3s7er!

 评论