2022-强网杯部分题解


  • re

    • gamemaster
  • crypto

gamemaster

c#写的程序,用dnspy打开,最上面打开了一个文件(gamemessage),把他存给memory

再在goldfunc里找到^34的操作

再往下有对goldfunc,aes的操作

扔cyberchef里,找到MZ文件头(exe的文件头)

1
2
3
4
5
还是一个c#的程序,dnspy打开,找到最下面对flag的操作
array5是已知的,只要带出array4即可,然后往上推
看到parsekey对array操作,生成了array4。
求array的话,就是求出array2。sequenceequal要求array2和first(已知)相等。
所以根据first用check1函数求array即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
array[0] = num;
array[1] = num2;
array[2] = num3;
T1.Check1(array[0], array[1], array[2], array2);
bool flag2 = first.SequenceEqual(array2);
if (flag2)
{
T1.ParseKey(array, array4);
for (int i = 0; i < array5.Length; i++)
{
array5[i] ^= array4[i % array4.Length];
}
MessageBox.Show("flag{" + Encoding.Default.GetString(array5) + "}", "Congratulations!", MessageBoxButtons.OK);
}

根据这里的代码,写z3代码爆破,xyz三个值。
因为tmp的值是由xyz计算得来。所以需要tmp的每位都和first相等,每一条都作为约束添加进去。所以写个z3爆破。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import z3
first=[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]
print(len(first))
tmp=len(first)*[0]
num = -1
x = z3.BitVec("v1", 64) #64位的v1
y = z3.BitVec("v2", 64)
z = z3.BitVec("v3", 64)
for i in range(0,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+=1
tmp[num] = tmp[num] << 1 | (z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1))
solver = z3.Solver()
for i in range(len(first)):
solver.add(first[i] == tmp[i])
solver.check()
print(solver.model())
# [v3 = 3131229747, v1 = 156324965, v2 = 868387187]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void Check1(ulong x, ulong y, ulong z, byte[] KeyStream)
{
int num = -1;
for (int i = 0; i < 320; i++)
{
x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1UL) | x << 1);
y = (((y >> 30 ^ y >> 27) & 1UL) | y << 1);
z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1UL) | z << 1);
bool flag = i % 8 == 0;
if (flag)
{
num++;
}
KeyStream[num] = (byte)((long)((long)KeyStream[num] << 1) | (long)((ulong)((uint)((z >> 32 & 1UL & (x >> 30 & 1UL)) ^ (((z >> 32 & 1UL) ^ 1UL) & (y >> 31 & 1UL))))));
}
}

在根据parsekey求出array4

整合用parsekey和异或求flag
异或的话,可以直接用range(len(flag))的方式。
还可以直接用enumerate函数求(挺方便的,同时遍历列表中的元素和当前的i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
v=[156324965, 868387187,3131229747]
key=[0]*12
for i in range(3):
for j in range(4):
key[i * 4 + j] = (v[i] >> j * 8 & 255)
# print(chr(key))
# print(key)

flag=[60,100,36,86,51,251,167,108,116,245,207,223,40,103,34,62,22,251,227]
for i in range(len(flag)):
flag[i]^=key[i % len(key)]
print(chr(flag[i]),end="")

# for i,j in enumerate(flag):
# # print(i,j)
# print(chr(j^key[i%len(key)]),end="")