强网杯2022GameMaster复现

2023-12-25 16:35:48

GameMaster

题目下载到手三个文件

image-20231225151444369

优先查看exe,是个游戏。

image-20231225151552516

32位PE文件以及.net编写的,用dnSpy打开。

image-20231225151832460

读取了gamemessage文件存放到Program.memory里。

接下来都是一些键盘控件的处理,按Enter会进入俩个分支,有一个地方不同的是Escape处:

image-20231225153405102

这里点击一下,跟到函数的地方。

image-20231225153424900

会紧跟着调用一个goldFunc的函数,再跟过去,

image-20231225153506696

从这里一直看下去,直到再次看到Program.memory

image-20231225152123599

这里很明显做了一个异或34的处理,之后赋给AchivePoint1

image-20231225152335485

中间的加减大概就是分数,一直到这里flag39,可能会调用函数genCode。这个函数在dll中,先不管。

image-20231225152528895

这里又是对Program.memory进行了一个加密,用了ECB加密模式,填充方式是PaddingMode.Zeors,这是一个典型的AES加密。这里也是给到了AchivePoint2。

image-20231225153002639

这里就是AchivePoint3了,进行了一个反序列化的操作,但是没有对文件进行处理。不明所以。

大概这个exe就看完了,下面也不太清楚都做了什么,可以明白的是gamemessage是可以解密的。

解密脚本:

from Crypto.Cipher import AES

with open("gamemessage","rb") as f:
    data = f.read()
dataArr = [t for t in data]

for i in range(len(dataArr)):
    dataArr[i] ^= 34
data = bytes(dataArr)

key = [66,114,97,105,110,115,116,111,114,109,105,110,103,33,33,33]
key = bytes(key)

cipher = AES.new(key, AES.MODE_ECB)

p = cipher.decrypt(data)
# print(p)

filename = "decrypt"
with open(filename, 'wb') as f:
    f.write(p)

之后可以得到一个decrypt文件。

image-20231225153938845

发现并不是一个exe或dll文件。用Winhex打开,搜索MZ,将其前面所有内容删掉

image-20231225154137242

保存,再用dnSpy打开。

image-20231225154254128

image-20231225160528742

给了俩组密文,依次解密,第一组用z3求解。可以得到x,y,z。三个数据根据ParseKey可以得到长度为12的array4,已知array5,俩者异或就可以得到flag。

EXP:

from z3 import *

sol = Solver()
xorkey = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227]
cmp = [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]

x = BitVec('x', 63)
y = BitVec('y', 63)
z = BitVec('z', 63)
dup = [x, y, z]

arr = [BitVecVal(0, 63) for i in range(len(cmp))]
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)
    if i % 8 == 0:
        num = num + 1
    arr[num] = ((arr[num] << 1) | (
        ((z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1))) & 0xffffffff) & 0xff)

for i in range(len(cmp)):
    sol.add(cmp[i] == arr[i])

assert sol.check() == sat
sol = sol.model()
fake = [sol.eval(i).as_long() & 0xffffffff for i in dup]
Key = [0] * 12
for i in range(3):
    for j in range(4):
        Key[i * 4 + j] = fake[i] >> j * 8 & 255
print(bytearray([(xorkey[i] ^ Key[i % len(Key)]) & 255 for i in range(len(xorkey))]))

文章来源:https://blog.csdn.net/Sciurdae/article/details/135202405
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。