HGAME 2023 week3 wp

cpp

hgame{Cpp_1s_much_m0r3_dlff1cult_th4n_C}

加密方式是salsa20,就是流加密,所以只需要找到明文和密文就可以了。不过要注意大小端序。

这段是秘钥流和明文异或的地方。

9e1a04c3ae45cbceba7c1048e390ca5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enc = [0x28, 0x50, 0xC1, 0x23, 0x98, 0xA1, 0x41, 0x36, 0x4C, 0x31, 0xCB, 0x52, 0x90, 0xF1, 0xAC, 0xCC, 0x0F, 0x6C, 0x2A, 0x89, 0x7F, 0xDF, 0x11, 0x84, 0x7F, 0xE6, 0xA2, 0xE0, 0x59, 0xC7, 0xC5, 0x46, 0x5D, 0x29, 0x38, 0x93, 0xED, 0x15, 0x7A, 0xFF]
Mpinput = "hgame{0123456789012345678901234567890123}"
enin = "magh10{e54329876321076541098543298763210"
inenc = [ 0x23, 0xC1, 0x50, 0x28, 0x77, 0x32, 0xA1, 0x98, 0x14, 0xCE,
0x5D, 0x0E, 0x96, 0xE1, 0xAB, 0xF9, 0x8A, 0x75, 0x02, 0x57,
0xD7, 0x78, 0xD9, 0x39, 0xE0, 0xF4, 0xB9, 0x2B, 0x07, 0x9D,
0x81, 0x08, 0x9E, 0x68, 0x6A, 0x34, 0xB1, 0x0B, 0x7B, 0xB3]
for i in range(40):
print(hex(inenc[i] ^ ord(enin[i])),end=', ')
key = [0x4e, 0xa0, 0x37, 0x40, 0x46, 0x2, 0xda, 0xfd, 0x21, 0xfa, 0x6e, 0x3c, 0xaf, 0xd9, 0x9c, 0xcf, 0xb9, 0x47, 0x33, 0x67, 0xe0, 0x4e, 0xec, 0xd, 0xd1, 0xc4, 0x80, 0x13, 0x32, 0xa9, 0xb2, 0x3a, 0xa7, 0x50, 0x5d, 0x2, 0x82, 0x39, 0x4a, 0x83]
print()
for i in range(10):
print(chr(enc[i * 4] ^ key[i * 4 + 3]), end='')
print(chr(enc[i * 4 + 1] ^ key[i * 4 + 2]), end='')
print(chr(enc[i * 4 + 2] ^ key[i * 4 + 1]), end='')
print(chr(enc[i * 4 + 3] ^ key[i * 4]), end='')

patchme

比cpp还简单

找到这个函数

image-20230129130356473

大体猜测是smc,idc脚本模拟一下smc部分就能静态分析了

1
2
3
4
5
6
7
8
9
#include <idc.idc>
static main()
{
auto Address = 0x14c6;
auto i = 0;
for(i = 0;i<=960;i++){
PatchByte(Address+i,Byte(Address+i)^0x66);
}
}

被改变过的就可以直接静态分析了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
int sub_14C6()
{
int result; // eax
__WAIT_STATUS stat_loc; // [rsp+Ch] [rbp-2C4h] BYREF
int i; // [rsp+14h] [rbp-2BCh]
__int64 v3; // [rsp+18h] [rbp-2B8h]
int pipedes[2]; // [rsp+20h] [rbp-2B0h] BYREF
int v5[2]; // [rsp+28h] [rbp-2A8h] BYREF
char *argv[4]; // [rsp+30h] [rbp-2A0h] BYREF
char v7[48]; // [rsp+50h] [rbp-280h] BYREF
__int64 v8; // [rsp+80h] [rbp-250h]
__int64 v9[6]; // [rsp+E0h] [rbp-1F0h]
__int64 v10[6]; // [rsp+110h] [rbp-1C0h]
char buf[80]; // [rsp+140h] [rbp-190h] BYREF
char s1[8]; // [rsp+190h] [rbp-140h] BYREF
__int64 v13; // [rsp+198h] [rbp-138h]
char v14[280]; // [rsp+1A0h] [rbp-130h] BYREF
int v15; // [rsp+2B8h] [rbp-18h]
unsigned __int64 v16; // [rsp+2C8h] [rbp-8h]

v16 = __readfsqword(0x28u);
result = dword_4028;
if ( dword_4028 <= 1 )
{
pipe(pipedes);
pipe(v5);
if ( fork() )
{
close(pipedes[0]);
close(v5[1]);
HIDWORD(stat_loc.__iptr) = 0;
while ( SHIDWORD(stat_loc.__iptr) <= 35 )
{
buf[2 * HIDWORD(stat_loc.__iptr)] = 37;
buf[2 * HIDWORD(stat_loc.__iptr)++ + 1] = 110;
}
buf[72] = 10;
buf[73] = 0;
write(pipedes[1], buf, 0x4AuLL);
*(_QWORD *)s1 = 0LL;
v13 = 0LL;
memset(v14, 0, sizeof(v14));
v15 = 0;
read(v5[0], s1, 0x12CuLL);
wait((__WAIT_STATUS)&stat_loc);
buf[23] = 0;
if ( !LODWORD(stat_loc.__uptr) && !strcmp(s1, buf) )
{
v9[0] = 0x5416D999808A28FALL;
v9[1] = 0x588505094953B563LL;
v9[2] = 0xCE8CF3A0DC669097LL;
v9[3] = 0x4C5CF3E854F44CBDLL;
v9[4] = 0xD144E49916678331LL;
LODWORD(v9[5]) = 0xDA616BAC;
WORD2(v9[5]) = 0xBBD0;
BYTE6(v9[5]) = 0x55;
v10[0] = 0x3B4FA2FCEDEB4F92LL;
v10[1] = 0x7E45A6C3B67EA16LL;
v10[2] = 0xAFE1ACC8BF12D0E7LL;
v10[3] = 0x132EC3B7269138CELL;
v10[4] = 0x8E2197EB7311E643LL;
LODWORD(v10[5]) = 0xAE540AC1;
WORD2(v10[5]) = 0xC9B5;
BYTE6(v10[5]) = 0x28;
result = putchar(10);
for ( i = 0; i <= 46; ++i )
result = putchar((char)(*((_BYTE *)v9 + i) ^ *((_BYTE *)v10 + i)));
}
else
{
return puts("\nthere are still bugs...");
}
}
else
{
fflush(stdin);
sub_1AB0(*(_QWORD *)qword_4020, v7);
v3 = v8;
if ( v8 == 14472 )
{
close(pipedes[1]);
close(v5[0]);
dup2(pipedes[0], 0);
dup2(v5[1], 1);
dup2(v5[1], 2);
argv[0] = *(char **)qword_4020;
argv[1] = "1";
argv[2] = 0LL;
return execve(*(const char **)qword_4020, argv, 0LL);
}
else
{
puts("\nyou cannot modify the file size");
return 0;
}
}
}
return result;
}

不难看出,这里是成功的提示

image-20230129130203114

就复制粘贴跑一下就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>

int main() {
__int64 v9[5], v13[5];
int v10,v14;
__int16 v11,v15;
char v12,v16;
v9[0] = 0x5416D999808A28FALL;
v9[1] = 0x588505094953B563LL;
v9[2] = 0xCE8CF3A0DC669097LL;
v9[3] = 0x4C5CF3E854F44CBDLL;
v9[4] = 0xD144E49916678331LL;
v10 = 0xDA616BAC;
v11 = 0xBBD0;
v12 = 0x55;
v13[0] = 0x3B4FA2FCEDEB4F92LL;
v13[1] = 0x7E45A6C3B67EA16LL;
v13[2] = 0xAFE1ACC8BF12D0E7LL;
v13[3] = 0x132EC3B7269138CELL;
v13[4] = 0x8E2197EB7311E643LL;
v14 = 0xAE540AC1;
v15 = 0xC9B5;
v16 = 0x28;
for (int i = 0; i <= 4; ++i) {
for (int j = 0; j < 8; ++j) {
char a = v9[i]&0xff;
char b = v13[i]&0xff;
printf("%c",a^b);
v9[i] >>= 8;
v13[i] >>= 8;
}
}
for (int i = 0; i < 4; ++i) {
char a = v10 & 0xff;
char b = v14 & 0xff;
printf("%c",a^b);
v10 >>= 8;
v14 >>= 8;
}
for (int i = 0; i < 2; ++i) {
char a = v11 & 0xff;
char b = v15 & 0xff;
printf("%c",a^b);
v11 >>= 8;
v15 >>= 8;
}
printf("%c",v12^v16);
return 0;
}

kmusic

呃呃,我z3脚本有毛病

dnspy在随便边一个按钮下断点,动调点击那个按钮就能看到check函数:

image-20230130144454774

z3解咯:

自己第一次写的脚本很乱,找不到像个正常的flag,就截取了跑出来的前面一部分:

1
hgame{z3

然后和密文异或得到的数据再加进约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from z3 import *
s = Solver()
num = [0] * 13
for i in range(13):
num[i] = BitVec("num[{}]".format(i), 8)
print("start add")
s.add(num[0] + 52296 + num[1] - 26211 + num[2] - 11754 + (num[3] ^ 41236) + num[4] * 63747 + num[5] - 52714 + num[
6] - 10512 + num[7] * 12972 + num[8] + 45505 + num[9] - 21713 + num[10] - 59122 + num[11] - 12840 + (
num[12] ^ 21087) == 12702282)
s.add(num[0] - 25228 + (num[1] ^ 20699) + (num[2] ^ 8158) + num[3] - 65307 + num[4] * 30701 + num[5] * 47555 + num[
6] - 2557 + (num[7] ^ 49055) + num[8] - 7992 + (num[9] ^ 57465) + (num[10] ^ 57426) + num[11] + 13299 + num[
12] - 50966 == 9946829)
s.add(num[0] - 64801 + num[1] - 60698 + num[2] - 40853 + num[3] - 54907 + num[4] + 29882 + (num[5] ^ 13574) + (
num[6] ^ 21310) + num[7] + 47366 + num[8] + 41784 + (num[9] ^ 53690) + num[10] * 58436 + num[11] * 15590 +
num[12] + 58225 == 2372055)
s.add(num[0] + 61538 + num[1] - 17121 + num[2] - 58124 + num[3] + 8186 + num[4] + 21253 + num[5] - 38524 + num[
6] - 48323 + num[7] - 20556 + num[8] * 56056 + num[9] + 18568 + num[10] + 12995 + (num[11] ^ 39260) + num[
12] + 25329 == 6732474)
s.add(num[0] - 42567 + num[1] - 17743 + num[2] * 47827 + num[3] - 10246 + (num[4] ^ 16284) + num[5] + 39390 + num[
6] * 11803 + num[7] * 60332 + (num[8] ^ 18491) + (num[9] ^ 4795) + num[10] - 25636 + num[11] - 16780 + num[
12] - 62345 == 14020739)
s.add(num[0] - 10968 + num[1] - 31780 + (num[2] ^ 31857) + num[3] - 61983 + num[4] * 31048 + num[5] * 20189 + num[
6] + 12337 + num[7] * 25945 + (num[8] ^ 7064) + num[9] - 25369 + num[10] - 54893 + num[11] * 59949 + (
num[12] ^ 12441) == 14434062)
s.add(num[0] + 16689 + num[1] - 10279 + num[2] - 32918 + num[3] - 57155 + num[4] * 26571 + num[5] * 15086 + (
num[6] ^ 22986) + (num[7] ^ 23349) + (num[8] ^ 16381) + (num[9] ^ 23173) + num[10] - 40224 + num[
11] + 31751 + num[12] * 8421 == 7433598)
s.add(num[0] + 28740 + num[1] - 64696 + num[2] + 60470 + num[3] - 14752 + (num[4] ^ 1287) + (num[5] ^ 35272) + num[
6] + 49467 + num[7] - 33788 + num[8] + 20606 + (num[9] ^ 44874) + num[10] * 19764 + num[11] + 48342 + num[
12] * 56511 == 7989404
)
s.add((num[0] ^ 28978) + num[1] + 23120 + num[2] + 22802 + num[3] * 31533 + (num[4] ^ 39287) + num[5] - 48576 + (
num[6] ^ 28542) + num[7] - 43265 + num[8] + 22365 + num[9] + 61108 + num[10] * 2823 + num[11] - 30343 + num[
12] + 14780 == 3504803
)
s.add(num[0] * 22466 + (num[1] ^ 55999) + num[2] - 53658 + (num[3] ^ 47160) + (num[4] ^ 12511) + num[5] * 59807 + num[
6] + 46242 + num[7] + 3052 + (num[8] ^ 25279) + num[9] + 30202 + num[10] * 22698 + num[11] + 33480 + (
num[12] ^ 16757) == 11003580
)
s.add(num[0] * 57492 + (num[1] ^ 13421) + num[2] - 13941 + (num[3] ^ 48092) + num[4] * 38310 + num[5] + 9884 + num[
6] - 45500 + num[7] - 19233 + num[8] + 58274 + num[9] + 36175 + (num[10] ^ 18568) + num[11] * 49694 + (
num[12] ^ 9473) == 25546210
)
s.add(num[0] - 23355 + num[1] * 50164 + (num[2] ^ 34618) + num[3] + 52703 + num[4] + 36245 + num[5] * 46648 + (
num[6] ^ 4858) + (num[7] ^ 41846) + num[8] * 27122 + (num[9] ^ 42058) + num[10] * 15676 + num[11] - 31863 +
num[12] + 62510 == 11333836
)
s.add(num[0] * 30523 + (num[1] ^ 7990) + num[2] + 39058 + num[3] * 57549 + (num[4] ^ 53440) + num[5] * 4275 + num[
6] - 48863 + (num[7] ^ 55436) + (num[8] ^ 2624) + (num[9] ^ 13652) + num[10] + 62231 + num[11] + 19456 + num[
12] - 13195 == 13863722)
s.add(num[0] == 236)#多加的约束
s.add(num[1] == 72)
s.add(num[2] == 213)
s.add(num[3] == 106)
s.add(num[4] == 189)
s.add(num[5] == 86)
s.add(num[6] == 62)
s.add(num[7] == 53)#多加的约束
print("start check")
arr = [132, 47, 180, 7, 216, 45, 68, 6, 39, 246, 124, 2, 243, 137, 58, 172, 53, 200, 99, 91, 83, 13, 171, 80, 108, 235,
179, 58, 176, 28, 216, 36, 11, 80, 39, 162, 97, 58, 236, 130, 123, 176, 24, 212, 56, 89, 72]
if s.check() == sat:
k = 0
while s.check() == sat:
condition = []
m = s.model()
print("[%d]" % k)
for i in range(len(arr)):
print(chr(m[num[i % 13]].as_long() ^ arr[i]),end='')
print()
k += 1
for i in range(13):
condition.append(num[i] != BitVec("%s" % (m[num[i]]).as_long(), 8))
s.add(Or(condition))
else:
print("wrong")

然后就跑出这个:hgame{z3_±s_öery_u5efuì_1î_rever5e_ångén3ering} 怪诶,因为num是13位的,所以把非ascii字符替换然后找其他的约束

1
2
3
4
5
6
7
arr = [132, 47, 180, 7, 216, 45, 68, 6, 39, 246, 124, 2, 243, 137, 58, 172, 53, 200, 99, 91, 83, 13, 171, 80, 108, 235,
179, 58, 176, 28, 216, 36, 11, 80, 39, 162, 97, 58, 236, 130, 123, 176, 24, 212, 56, 89, 72]
a = "hgame{z3_@s_@ery_u5efu@_1@_rever5e_@ng@n3ering}"
for i in range(13):
if a[i] == '@':
continue
print("s.add(num[{}] == {})".format(i,(arr[i]^ord(a[i]))&0xff))
1
2
3
4
5
6
7
8
9
10
11
s.add(num[0] == 236)
s.add(num[1] == 72)
s.add(num[2] == 213)
s.add(num[3] == 106)
s.add(num[4] == 189)
s.add(num[5] == 86)
s.add(num[6] == 62)
s.add(num[7] == 53)
s.add(num[8] == 120)
s.add(num[10] == 15)
s.add(num[11] == 93)

再加上去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

s.add(num[0] == 236)
s.add(num[1] == 72)
s.add(num[2] == 213)
s.add(num[3] == 106)
s.add(num[4] == 189)
s.add(num[5] == 86)
s.add(num[6] == 62)
s.add(num[7] == 53)
s.add(num[8] == 120)
s.add(num[10] == 15)
s.add(num[11] == 93)
print("start check")
arr = [132, 47, 180, 7, 216, 45, 68, 6, 39, 246, 124, 2, 243, 137, 58, 172, 53, 200, 99, 91, 83, 13, 171, 80, 108, 235,
179, 58, 176, 28, 216, 36, 11, 80, 39, 162, 97, 58, 236, 130, 123, 176, 24, 212, 56, 89, 72]
if s.check() == sat:
k = 0
while s.check() == sat:
condition = []
m = s.model()
print("[%d]" % k)
for i in range(len(arr)):
print(chr(m[num[i % 13]].as_long() ^ arr[i]),end='')
print()
k += 1
for i in range(13):
condition.append(num[i] != BitVec("%s" % (m[num[i]]).as_long(), 8))
s.add(Or(condition))
else:
print("wrong")

就得到flag

hgame{z3_1s_very_u5eful_1n_rever5e_engin3ering}