TGCTF 2025 逆向WP

战队名:不知道

排名:3

上次XYCTF是痛失Web手,这次又是痛失Pwn手,啥时候能全队一起打一次()。这次Re难度还行,磨磨唧唧整了一会也是AK了。

Base64

Base64 变种加密

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
_BYTE *__fastcall sub_7FF7DC6C10E0(__int64 a1)
{
__int64 v2; // rbx
__int64 v3; // rbp
int v4; // edx
int v5; // edi
int v6; // edx
__int64 v7; // r14
size_t v8; // rcx
_BYTE *v9; // r8
__int64 v10; // r9
unsigned __int64 v11; // rdx
int v12; // ecx
unsigned int v13; // ecx
unsigned int v14; // eax
int v15; // eax
int v16; // eax
int v17; // eax
int v18; // edi
__int64 v19; // rdx
int v20; // eax
int v21; // eax
int v22; // ecx
unsigned int v23; // edx
int v24; // ecx
int v25; // eax
int v26; // ecx
unsigned int v27; // ecx
unsigned int v28; // eax
char v30[80]; // [rsp+20h] [rbp-68h] BYREF
int v31; // [rsp+90h] [rbp+8h]

v2 = -1;
strcpy(v30, "GLp/+Wn7uqX8FQ2JDR1c0M6U53sjBwyxglmrCVdSThAfEOvPHaYZNzo4ktK9iebI");
do
++v2;
while ( *(_BYTE *)(a1 + v2) );
v3 = 0;
v4 = (int)v2 / 3;
if ( (_DWORD)v2 == 3 * ((int)v2 / 3) )
{
v5 = 0;
v6 = 4 * v4;
}
else if ( (int)v2 % 3 == 1 )
{
v5 = 1;
v6 = 4 * v4 + 4;
}
else if ( (int)v2 % 3 == 2 )
{
v5 = 2;
v6 = 4 * v4 + 4;
}
else
{
v5 = v31;
v6 = v31;
}
v7 = v6;
v8 = v6 + 1LL;
if ( v6 == -1 )
v8 = -1;
v9 = malloc(v8);
if ( (int)v2 - v5 > 0 )
{
v10 = a1 + 2;
v11 = ((int)v2 - v5 - 1LL) / 3uLL + 1;
do
{
v3 += 4;
v12 = *(unsigned __int8 *)(v10 - 2) >> 2;
v10 += 3;
v13 = v12 + 24;
v14 = v13 - 64;
if ( v13 <= 0x40 )
v14 = v13;
v9[v3 - 4] = v30[v14];
v15 = ((*(unsigned __int8 *)(v10 - 4) >> 4) | (16 * (*(_BYTE *)(v10 - 5) & 3))) - 40;
if ( ((*(unsigned __int8 *)(v10 - 4) >> 4) | (16 * (*(_BYTE *)(v10 - 5) & 3u))) + 24 <= 0x40 )
v15 = ((*(unsigned __int8 *)(v10 - 4) >> 4) | (16 * (*(_BYTE *)(v10 - 5) & 3))) + 24;
v9[v3 - 3] = v30[v15];
v16 = ((*(unsigned __int8 *)(v10 - 3) >> 6) | (4 * (*(_BYTE *)(v10 - 4) & 0xF))) - 40;
if ( ((*(unsigned __int8 *)(v10 - 3) >> 6) | (4 * (*(_BYTE *)(v10 - 4) & 0xFu))) + 24 <= 0x40 )
v16 = ((*(unsigned __int8 *)(v10 - 3) >> 6) | (4 * (*(_BYTE *)(v10 - 4) & 0xF))) + 24;
v9[v3 - 2] = v30[v16];
v17 = (*(_BYTE *)(v10 - 3) & 0x3F) - 40;
if ( (*(_BYTE *)(v10 - 3) & 0x3Fu) + 24 <= 0x40 )
v17 = (*(_BYTE *)(v10 - 3) & 0x3F) + 24;
v9[v3 - 1] = v30[v17];
--v11;
}
while ( v11 );
}
v18 = v5 - 1;
if ( !v18 )
{
v25 = (*(unsigned __int8 *)((int)v2 + a1 - 1) >> 2) - 40;
if ( (*(unsigned __int8 *)((int)v2 + a1 - 1) >> 2) + 24 <= 0x40u )
v25 = (*(unsigned __int8 *)((int)v2 + a1 - 1) >> 2) + 24;
v9[v7 - 4] = v30[v25];
v26 = *(_BYTE *)((int)v2 + a1 - 1) & 3;
*(_WORD *)&v9[v7 - 2] = 15677;
v27 = 16 * v26 + 24;
v28 = v27 - 64;
if ( v27 <= 0x40 )
v28 = v27;
v9[v7 - 3] = v30[v28];
goto LABEL_37;
}
if ( v18 != 1 )
{
LABEL_37:
v9[v7] = 0;
return v9;
}
v19 = a1 + (int)v2;
v20 = (*(unsigned __int8 *)(v19 - 2) >> 2) - 40;
if ( (*(unsigned __int8 *)(v19 - 2) >> 2) + 24 <= 0x40u )
v20 = (*(unsigned __int8 *)(v19 - 2) >> 2) + 24;
v9[v7 - 4] = v30[v20];
v21 = ((*(unsigned __int8 *)(v19 - 1) >> 4) | (16 * (*(_BYTE *)(v19 - 2) & 3))) - 40;
if ( ((*(unsigned __int8 *)(v19 - 1) >> 4) | (16 * (*(_BYTE *)(v19 - 2) & 3u))) + 24 <= 0x40 )
v21 = ((*(unsigned __int8 *)(v19 - 1) >> 4) | (16 * (*(_BYTE *)(v19 - 2) & 3))) + 24;
v9[v7 - 3] = v30[v21];
v22 = *(_BYTE *)(v19 - 1) & 0xF;
*(_WORD *)&v9[v7 - 1] = 61;
v23 = 4 * v22 + 24;
v24 = 4 * v22 - 40;
if ( v23 <= 0x40 )
v24 = v23;
v9[v7 - 2] = v30[v24];
return v9;
}

解密代码:

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
#include <iostream>
#include <windows.h>
#include <string>
#include <time.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *base64_decode(const char *_input_)
{
const char *base64_table = "GLp/+Wn7uqX8FQ2JDR1c0M6U53sjBwyxglmrCVdSThAfEOvPHaYZNzo4ktK9iebI";

unsigned char reverse_table[256] = {0};
for (int i = 0; i < 64; i++)
{
reverse_table[(unsigned char)base64_table[i]] = i;
}

size_t input_len = strlen(_input_);
size_t padding = 0;

if (input_len > 0 && _input_[input_len - 1] == '=')
{
padding++;
if (input_len > 1 && _input_[input_len - 2] == '=')
{
padding++;
}
}

size_t output_len = (input_len * 3) / 4 - padding;
unsigned char *output = (unsigned char *)malloc(output_len + 1);
output[output_len] = 0;

size_t i = 0, j = 0;
while (i < input_len - padding)
{
unsigned char b1, b2, b3, b4;

unsigned char v1 = reverse_table[_input_[i++]];
unsigned char v2 = reverse_table[_input_[i++]];
unsigned char v3 = (i < input_len) ? reverse_table[_input_[i++]] : 0;
unsigned char v4 = (i < input_len) ? reverse_table[_input_[i++]] : 0;

b1 = (v1 > 24) ? (v1 - 24) : (v1 + 64 - 24);
b2 = (v2 > 24) ? (v2 - 24) : (v2 + 64 - 24);
b3 = (v3 > 24) ? (v3 - 24) : (v3 + 64 - 24);
b4 = (v4 > 24) ? (v4 - 24) : (v4 + 64 - 24);

if (j < output_len)
output[j++] = (b1 << 2) | (b2 >> 4);
if (j < output_len)
output[j++] = (b2 << 4) | (b3 >> 2);
if (j < output_len)
output[j++] = (b3 << 6) | b4;
}

return (char *)output;
}

int main()
{
const char *Enc= "AwLdOEVEhIWtajB2CbCWCbTRVsFFC8hirfiXC9gWH9HQayCJVbB8CIF=";
char *Decoded= base64_decode(Enc);
printf("%s\n", Decoded);
free(decoded);
return 0;
}

HZNUCTF{ad162c-2d94-434d-9222-b65dc76a32}

水果忍者

主要 dll 目录:\水果忍者\Fruit Ninja_Data\Managed\Assembly-CSharp.dll

拖入 dnSpy 分析,是 AES CBC 加密。

底下有密文、密钥、iv,直接解密即可。

HZNUCTF{de20-70dd-4e62-b8d0-06e}

蛇年的本命语言

python 程序解包得到 pyc(python 3.8),使用 uncompyle6 解密得到代码。

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
from collections import Counter
print("Welcome to HZNUCTF!!!")
print("Plz input the flag:")
ooo0oOoooOOO0 = input()
oOO0OoOoo000 = Counter(ooo0oOoooOOO0)
O0o00 = "".join((str(oOO0OoOoo000[oOooo0OOO]) for oOooo0OOO in ooo0oOoooOOO0))
print("ans1: ", _end_="")
print(O0o00)
if O0o00 != "111111116257645365477364777645752361":
print("wrong_wrong!!!")
exit(1)
iiIII = ""
for oOooo0OOO in ooo0oOoooOOO0:
if oOO0OoOoo000[oOooo0OOO] > 0:
iiIII += oOooo0OOO + str(oOO0OoOoo000[oOooo0OOO])
oOO0OoOoo000[oOooo0OOO] = 0
else:
i11i1Iii1I1 = [ord(oOooo0OOO) for oOooo0OOO in iiIII]
ii1iIi1i11i = [
7 * i11i1Iii1I1[0] == 504,
9 * i11i1Iii1I1[0] - 5 * i11i1Iii1I1[1] == 403,
2 * i11i1Iii1I1[0] - 5 * i11i1Iii1I1[1] + 10 * i11i1Iii1I1[2] == 799,
3 * i11i1Iii1I1[0] + 8 * i11i1Iii1I1[1] + 15 * i11i1Iii1I1[2] + 20 * i11i1Iii1I1[3] == 2938,
5 * i11i1Iii1I1[0] + 15 * i11i1Iii1I1[1] + 20 * i11i1Iii1I1[2] - 19 * i11i1Iii1I1[3] + 1 * i11i1Iii1I1[4] == 2042,
7 * i11i1Iii1I1[0] + 1 * i11i1Iii1I1[1] + 9 * i11i1Iii1I1[2] - 11 * i11i1Iii1I1[3] + 2 * i11i1Iii1I1[4] + 5 * i11i1Iii1I1[5] == 1225,
11 * i11i1Iii1I1[0] + 22 * i11i1Iii1I1[1] + 33 * i11i1Iii1I1[2] + 44 * i11i1Iii1I1[3] + 55 * i11i1Iii1I1[4] + 66 * i11i1Iii1I1[5] - 77 * i11i1Iii1I1[6] == 7975,
21 * i11i1Iii1I1[0] + 23 * i11i1Iii1I1[1] + 3 * i11i1Iii1I1[2] + 24 * i11i1Iii1I1[3] - 55 * i11i1Iii1I1[4] + 6 * i11i1Iii1I1[5] - 7 * i11i1Iii1I1[6] + 15 * i11i1Iii1I1[7] == 229,
2 * i11i1Iii1I1[0] + 26 * i11i1Iii1I1[1] + 13 * i11i1Iii1I1[2] + 0 * i11i1Iii1I1[3] - 65 * i11i1Iii1I1[4] + 15 * i11i1Iii1I1[5] + 29 * i11i1Iii1I1[6] + 1 * i11i1Iii1I1[7] + 20 * i11i1Iii1I1[8] == 2107,
10 * i11i1Iii1I1[0] + 7 * i11i1Iii1I1[1] + -9 * i11i1Iii1I1[2] + 6 * i11i1Iii1I1[3] + 7 * i11i1Iii1I1[4] + 1 * i11i1Iii1I1[5] + 22 * i11i1Iii1I1[6] + 21 * i11i1Iii1I1[7] - 22 * i11i1Iii1I1[8] + 30 * i11i1Iii1I1[9] == 4037,
15 * i11i1Iii1I1[0] + 59 * i11i1Iii1I1[1] + 56 * i11i1Iii1I1[2] + 66 * i11i1Iii1I1[3] + 7 * i11i1Iii1I1[4] + 1 * i11i1Iii1I1[5] - 122 * i11i1Iii1I1[6] + 21 * i11i1Iii1I1[7] + 32 * i11i1Iii1I1[8] + 3 * i11i1Iii1I1[9] - 10 * i11i1Iii1I1[10] == 4950,
13 * i11i1Iii1I1[0] + 66 * i11i1Iii1I1[1] + 29 * i11i1Iii1I1[2] + 39 * i11i1Iii1I1[3] - 33 * i11i1Iii1I1[4] + 13 * i11i1Iii1I1[5] - 2 * i11i1Iii1I1[6] + 42 * i11i1Iii1I1[7] + 62 * i11i1Iii1I1[8] + 1 * i11i1Iii1I1[9] - 10 * i11i1Iii1I1[10] + 11 * i11i1Iii1I1[11] == 12544,
23 * i11i1Iii1I1[0] + 6 * i11i1Iii1I1[1] + 29 * i11i1Iii1I1[2] + 3 * i11i1Iii1I1[3] - 3 * i11i1Iii1I1[4] + 63 * i11i1Iii1I1[5] - 25 * i11i1Iii1I1[6] + 2 * i11i1Iii1I1[7] + 32 * i11i1Iii1I1[8] + 1 * i11i1Iii1I1[9] - 10 * i11i1Iii1I1[10] + 11 * i11i1Iii1I1[11] - 12 * i11i1Iii1I1[12] == 6585,
223 * i11i1Iii1I1[0] + 6 * i11i1Iii1I1[1] - 29 * i11i1Iii1I1[2] - 53 * i11i1Iii1I1[3] - 3 * i11i1Iii1I1[4] + 3 * i11i1Iii1I1[5] - 65 * i11i1Iii1I1[6] + 0 * i11i1Iii1I1[7] + 36 * i11i1Iii1I1[8] + 1 * i11i1Iii1I1[9] - 15 * i11i1Iii1I1[10] + 16 * i11i1Iii1I1[11] - 18 * i11i1Iii1I1[12] + 13 * i11i1Iii1I1[13] == 6893,
29 * i11i1Iii1I1[0] + 13 * i11i1Iii1I1[1] - 9 * i11i1Iii1I1[2] - 93 * i11i1Iii1I1[3] + 33 * i11i1Iii1I1[4] + 6 * i11i1Iii1I1[5] + 65 * i11i1Iii1I1[6] + 1 * i11i1Iii1I1[7] - 36 * i11i1Iii1I1[8] + 0 * i11i1Iii1I1[9] - 16 * i11i1Iii1I1[10] + 96 * i11i1Iii1I1[11] - 68 * i11i1Iii1I1[12] + 33 * i11i1Iii1I1[13] - 14 * i11i1Iii1I1[14] == 1883,
69 * i11i1Iii1I1[0] + 77 * i11i1Iii1I1[1] - 93 * i11i1Iii1I1[2] - 12 * i11i1Iii1I1[3] + 0 * i11i1Iii1I1[4] + 0 * i11i1Iii1I1[5] + 1 * i11i1Iii1I1[6] + 16 * i11i1Iii1I1[7] + 36 * i11i1Iii1I1[8] + 6 * i11i1Iii1I1[9] + 19 * i11i1Iii1I1[10] + 66 * i11i1Iii1I1[11] - 8 * i11i1Iii1I1[12] + 38 * i11i1Iii1I1[13] - 16 * i11i1Iii1I1[14] + 15 * i11i1Iii1I1[15] == 8257,
23 * i11i1Iii1I1[0] + 2 * i11i1Iii1I1[1] - 3 * i11i1Iii1I1[2] - 11 * i11i1Iii1I1[3] + 12 * i11i1Iii1I1[4] + 24 * i11i1Iii1I1[5] + 1 * i11i1Iii1I1[6] + 6 * i11i1Iii1I1[7] + 14 * i11i1Iii1I1[8] - 0 * i11i1Iii1I1[9] + 1 * i11i1Iii1I1[10] + 68 * i11i1Iii1I1[11] - 18 * i11i1Iii1I1[12] + 68 * i11i1Iii1I1[13] - 26 * i11i1Iii1I1[14] + 15 * i11i1Iii1I1[15] - 16 * i11i1Iii1I1[16] == 5847,
24 * i11i1Iii1I1[0] + 0 * i11i1Iii1I1[1] - 1 * i11i1Iii1I1[2] - 15 * i11i1Iii1I1[3] + 13 * i11i1Iii1I1[4] + 4 * i11i1Iii1I1[5] + 16 * i11i1Iii1I1[6] + 67 * i11i1Iii1I1[7] + 146 * i11i1Iii1I1[8] - 50 * i11i1Iii1I1[9] + 16 * i11i1Iii1I1[10] + 6 * i11i1Iii1I1[11] - 1 * i11i1Iii1I1[12] + 69 * i11i1Iii1I1[13] - 27 * i11i1Iii1I1[14] + 45 * i11i1Iii1I1[15] - 6 * i11i1Iii1I1[16] + 17 * i11i1Iii1I1[17] == 18257,
25 * i11i1Iii1I1[0] + 26 * i11i1Iii1I1[1] - 89 * i11i1Iii1I1[2] + 16 * i11i1Iii1I1[3] + 19 * i11i1Iii1I1[4] + 44 * i11i1Iii1I1[5] + 36 * i11i1Iii1I1[6] + 66 * i11i1Iii1I1[7] - 150 * i11i1Iii1I1[8] - 250 * i11i1Iii1I1[9] + 166 * i11i1Iii1I1[10] + 126 * i11i1Iii1I1[11] - 11 * i11i1Iii1I1[12] + 690 * i11i1Iii1I1[13] - 207 * i11i1Iii1I1[14] + 46 * i11i1Iii1I1[15] + 6 * i11i1Iii1I1[16] + 7 * i11i1Iii1I1[17] - 18 * i11i1Iii1I1[18] == 12591,
5 * i11i1Iii1I1[0] + 26 * i11i1Iii1I1[1] + 8 * i11i1Iii1I1[2] + 160 * i11i1Iii1I1[3] + 9 * i11i1Iii1I1[4] - 4 * i11i1Iii1I1[5] + 36 * i11i1Iii1I1[6] + 6 * i11i1Iii1I1[7] - 15 * i11i1Iii1I1[8] - 20 * i11i1Iii1I1[9] + 66 * i11i1Iii1I1[10] + 16 * i11i1Iii1I1[11] - 1 * i11i1Iii1I1[12] + 690 * i11i1Iii1I1[13] - 20 * i11i1Iii1I1[14] + 46 * i11i1Iii1I1[15] + 6 * i11i1Iii1I1[16] + 7 * i11i1Iii1I1[17] - 18 * i11i1Iii1I1[18] + 19 * i11i1Iii1I1[19] == 52041,
29 * i11i1Iii1I1[0] - 26 * i11i1Iii1I1[1] + 0 * i11i1Iii1I1[2] + 60 * i11i1Iii1I1[3] + 90 * i11i1Iii1I1[4] - 4 * i11i1Iii1I1[5] + 6 * i11i1Iii1I1[6] + 6 * i11i1Iii1I1[7] - 16 * i11i1Iii1I1[8] - 21 * i11i1Iii1I1[9] + 69 * i11i1Iii1I1[10] + 6 * i11i1Iii1I1[11] - 12 * i11i1Iii1I1[12] + 69 * i11i1Iii1I1[13] - 20 * i11i1Iii1I1[14] - 46 * i11i1Iii1I1[15] + 65 * i11i1Iii1I1[16] + 0 * i11i1Iii1I1[17] - 1 * i11i1Iii1I1[18] + 39 * i11i1Iii1I1[19] - 20 * i11i1Iii1I1[20] == 20253,
45 * i11i1Iii1I1[0] - 56 * i11i1Iii1I1[1] + 10 * i11i1Iii1I1[2] + 650 * i11i1Iii1I1[3] - 900 * i11i1Iii1I1[4] + 44 * i11i1Iii1I1[5] + 66 * i11i1Iii1I1[6] - 6 * i11i1Iii1I1[7] - 6 * i11i1Iii1I1[8] - 21 * i11i1Iii1I1[9] + 9 * i11i1Iii1I1[10] - 6 * i11i1Iii1I1[11] - 12 * i11i1Iii1I1[12] + 69 * i11i1Iii1I1[13] - 2 * i11i1Iii1I1[14] - 406 * i11i1Iii1I1[15] + 651 * i11i1Iii1I1[16] + 2 * i11i1Iii1I1[17] - 10 * i11i1Iii1I1[18] + 69 * i11i1Iii1I1[19] - 0 * i11i1Iii1I1[20] + 21 * i11i1Iii1I1[21] == 18768,
555 * i11i1Iii1I1[0] - 6666 * i11i1Iii1I1[1] + 70 * i11i1Iii1I1[2] + 510 * i11i1Iii1I1[3] - 90 * i11i1Iii1I1[4] + 499 * i11i1Iii1I1[5] + 66 * i11i1Iii1I1[6] - 66 * i11i1Iii1I1[7] - 610 * i11i1Iii1I1[8] - 221 * i11i1Iii1I1[9] + 9 * i11i1Iii1I1[10] - 23 * i11i1Iii1I1[11] - 102 * i11i1Iii1I1[12] + 6 * i11i1Iii1I1[13] + 2050 * i11i1Iii1I1[14] - 406 * i11i1Iii1I1[15] + 665 * i11i1Iii1I1[16] + 333 * i11i1Iii1I1[17] + 100 * i11i1Iii1I1[18] + 609 * i11i1Iii1I1[19] + 777 * i11i1Iii1I1[20] + 201 * i11i1Iii1I1[21] - 22 * i11i1Iii1I1[22] == 111844,
1 * i11i1Iii1I1[0] - 22 * i11i1Iii1I1[1] + 333 * i11i1Iii1I1[2] + 4444 * i11i1Iii1I1[3] - 5555 * i11i1Iii1I1[4] + 6666 * i11i1Iii1I1[5] - 666 * i11i1Iii1I1[6] + 676 * i11i1Iii1I1[7] - 660 * i11i1Iii1I1[8] - 22 * i11i1Iii1I1[9] + 9 * i11i1Iii1I1[10] - 73 * i11i1Iii1I1[11] - 107 * i11i1Iii1I1[12] + 6 * i11i1Iii1I1[13] + 250 * i11i1Iii1I1[14] - 6 * i11i1Iii1I1[15] + 65 * i11i1Iii1I1[16] + 39 * i11i1Iii1I1[17] + 10 * i11i1Iii1I1[18] + 69 * i11i1Iii1I1[19] + 777 * i11i1Iii1I1[20] + 201 * i11i1Iii1I1[21] - 2 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] == 159029,
520 * i11i1Iii1I1[0] - 222 * i11i1Iii1I1[1] + 333 * i11i1Iii1I1[2] + 4 * i11i1Iii1I1[3] - 56655 * i11i1Iii1I1[4] + 6666 * i11i1Iii1I1[5] + 666 * i11i1Iii1I1[6] + 66 * i11i1Iii1I1[7] - 60 * i11i1Iii1I1[8] - 220 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 73 * i11i1Iii1I1[11] + 1007 * i11i1Iii1I1[12] + 7777 * i11i1Iii1I1[13] + 2500 * i11i1Iii1I1[14] + 6666 * i11i1Iii1I1[15] + 605 * i11i1Iii1I1[16] + 390 * i11i1Iii1I1[17] + 100 * i11i1Iii1I1[18] + 609 * i11i1Iii1I1[19] + 99999 * i11i1Iii1I1[20] + 210 * i11i1Iii1I1[21] + 232 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 24 * i11i1Iii1I1[24] == 2762025,
1323 * i11i1Iii1I1[0] - 22 * i11i1Iii1I1[1] + 333 * i11i1Iii1I1[2] + 4 * i11i1Iii1I1[3] - 55 * i11i1Iii1I1[4] + 666 * i11i1Iii1I1[5] + 666 * i11i1Iii1I1[6] + 66 * i11i1Iii1I1[7] - 660 * i11i1Iii1I1[8] - 220 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 3 * i11i1Iii1I1[11] + 100 * i11i1Iii1I1[12] + 777 * i11i1Iii1I1[13] + 2500 * i11i1Iii1I1[14] + 6666 * i11i1Iii1I1[15] + 605 * i11i1Iii1I1[16] + 390 * i11i1Iii1I1[17] + 100 * i11i1Iii1I1[18] + 609 * i11i1Iii1I1[19] + 9999 * i11i1Iii1I1[20] + 210 * i11i1Iii1I1[21] + 232 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 24 * i11i1Iii1I1[24] + 25 * i11i1Iii1I1[25] == 1551621,
777 * i11i1Iii1I1[0] - 22 * i11i1Iii1I1[1] + 6969 * i11i1Iii1I1[2] + 4 * i11i1Iii1I1[3] - 55 * i11i1Iii1I1[4] + 666 * i11i1Iii1I1[5] - 6 * i11i1Iii1I1[6] + 96 * i11i1Iii1I1[7] - 60 * i11i1Iii1I1[8] - 220 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 3 * i11i1Iii1I1[11] + 100 * i11i1Iii1I1[12] + 777 * i11i1Iii1I1[13] + 250 * i11i1Iii1I1[14] + 666 * i11i1Iii1I1[15] + 65 * i11i1Iii1I1[16] + 90 * i11i1Iii1I1[17] + 100 * i11i1Iii1I1[18] + 609 * i11i1Iii1I1[19] + 999 * i11i1Iii1I1[20] + 21 * i11i1Iii1I1[21] + 232 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 24 * i11i1Iii1I1[24] + 25 * i11i1Iii1I1[25] - 26 * i11i1Iii1I1[26] == 948348,
97 * i11i1Iii1I1[0] - 22 * i11i1Iii1I1[1] + 6969 * i11i1Iii1I1[2] + 4 * i11i1Iii1I1[3] - 56 * i11i1Iii1I1[4] + 96 * i11i1Iii1I1[5] - 6 * i11i1Iii1I1[6] + 96 * i11i1Iii1I1[7] - 60 * i11i1Iii1I1[8] - 20 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 3 * i11i1Iii1I1[11] + 10 * i11i1Iii1I1[12] + 707 * i11i1Iii1I1[13] + 250 * i11i1Iii1I1[14] + 666 * i11i1Iii1I1[15] + -9 * i11i1Iii1I1[16] + 90 * i11i1Iii1I1[17] + -2 * i11i1Iii1I1[18] + 609 * i11i1Iii1I1[19] + 0 * i11i1Iii1I1[20] + 21 * i11i1Iii1I1[21] + 2 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 24 * i11i1Iii1I1[24] + 25 * i11i1Iii1I1[25] - 26 * i11i1Iii1I1[26] + 27 * i11i1Iii1I1[27] == 777044,
177 * i11i1Iii1I1[0] - 22 * i11i1Iii1I1[1] + 699 * i11i1Iii1I1[2] + 64 * i11i1Iii1I1[3] - 56 * i11i1Iii1I1[4] - 96 * i11i1Iii1I1[5] - 66 * i11i1Iii1I1[6] + 96 * i11i1Iii1I1[7] - 60 * i11i1Iii1I1[8] - 20 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 3 * i11i1Iii1I1[11] + 10 * i11i1Iii1I1[12] + 707 * i11i1Iii1I1[13] + 250 * i11i1Iii1I1[14] + 666 * i11i1Iii1I1[15] + -9 * i11i1Iii1I1[16] + 0 * i11i1Iii1I1[17] + -2 * i11i1Iii1I1[18] + 69 * i11i1Iii1I1[19] + 0 * i11i1Iii1I1[20] + 21 * i11i1Iii1I1[21] + 222 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 224 * i11i1Iii1I1[24] + 25 * i11i1Iii1I1[25] - 26 * i11i1Iii1I1[26] + 27 * i11i1Iii1I1[27] - 28 * i11i1Iii1I1[28] == 185016,
77 * i11i1Iii1I1[0] - 2 * i11i1Iii1I1[1] + 6 * i11i1Iii1I1[2] + 6 * i11i1Iii1I1[3] - 96 * i11i1Iii1I1[4] - 9 * i11i1Iii1I1[5] - 6 * i11i1Iii1I1[6] + 96 * i11i1Iii1I1[7] - 0 * i11i1Iii1I1[8] - 20 * i11i1Iii1I1[9] + 99 * i11i1Iii1I1[10] + 3 * i11i1Iii1I1[11] + 10 * i11i1Iii1I1[12] + 707 * i11i1Iii1I1[13] + 250 * i11i1Iii1I1[14] + 666 * i11i1Iii1I1[15] + -9 * i11i1Iii1I1[16] + 0 * i11i1Iii1I1[17] + -2 * i11i1Iii1I1[18] + 9 * i11i1Iii1I1[19] + 0 * i11i1Iii1I1[20] + 21 * i11i1Iii1I1[21] + 222 * i11i1Iii1I1[22] + 23 * i11i1Iii1I1[23] - 224 * i11i1Iii1I1[24] + 26 * i11i1Iii1I1[25] - -58 * i11i1Iii1I1[26] + 27 * i11i1Iii1I1[27] - 2 * i11i1Iii1I1[28] + 29 * i11i1Iii1I1[29] == 130106]
if all(ii1iIi1i11i):
print("Congratulation!!!")
else:
print("wrong_wrong!!!")

是计下 flag 里面每个字符出现的次数检验是否符合那个字符串的格式化的对应次数,

将下面的 z3 解出可以得到一个字符串 H1Z1N1U1C1T1F1{1a6d275f7-463}

一个字符一个数字配对,代表该字符在原 flag 中出现的次数。

除去前面 HZNUCTF{,将括号内的字母和对应数字做映射,利用原代码中的**”111111116257645365477364777645752361”**去一一对应。

解密代码:

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
from z3 import *

def decrypt(_encrypted_):
mapping = "6257645365477364777645752361"

char_map = {}

remaining_map = {
'6': 'a',
'2': 'd',
'5': '7',
'7': 'f',
'4': '-',
'3': '6',
'1': '}'
}
char_map.update(remaining_map)

result = "HZNUCTF{"
for num in mapping:
result += char_map[num]

return result

s = Solver()

Enc = [Int(f'x{i}') for i in range(30)]

s.add(7 * Enc[0] == 504)
s.add(9 * Enc[0] - 5 * Enc[1] == 403)
s.add((2 * Enc[0] - 5 * Enc[1]) + 10 * Enc[2] == 799)
s.add(3 * Enc[0] + 8 * Enc[1] + 15 * Enc[2] + 20 * Enc[3] == 2938)
s.add((5 * Enc[0] + 15 * Enc[1] + 20 * Enc[2] - 19 * Enc[3]) + 1 * Enc[4] == 2042)
s.add((7 * Enc[0] + 1 * Enc[1] + 9 * Enc[2] - 11 * Enc[3]) + 2 * Enc[4] + 5 * Enc[5] == 1225)
s.add(11 * Enc[0] + 22 * Enc[1] + 33 * Enc[2] + 44 * Enc[3] + 55 * Enc[4] + 66 * Enc[5] - 77 * Enc[6] == 7975)
s.add(((21 * Enc[0] + 23 * Enc[1] + 3 * Enc[2] + 24 * Enc[3] - 55 * Enc[4]) + 6 * Enc[5] - 7 * Enc[6]) + 15 * Enc[7] == 229)
s.add((2 * Enc[0] + 26 * Enc[1] + 13 * Enc[2] + 0 * Enc[3] - 65 * Enc[4]) + 15 * Enc[5] + 29 * Enc[6] + 1 * Enc[7] + 20 * Enc[8] == 2107)
s.add((10 * Enc[0] + 7 * Enc[1] + -9 * Enc[2] + 6 * Enc[3] + 7 * Enc[4] + 1 * Enc[5] + 22 * Enc[6] + 21 * Enc[7] - 22 * Enc[8]) + 30 * Enc[9] == 4037)
s.add((15 * Enc[0] + 59 * Enc[1] + 56 * Enc[2] + 66 * Enc[3] + 7 * Enc[4] + 1 * Enc[5] - 122 * Enc[6]) + 21 * Enc[7] + 32 * Enc[8] + 3 * Enc[9] - 10 * Enc[10] == 4950)
s.add((((13 * Enc[0] + 66 * Enc[1] + 29 * Enc[2] + 39 * Enc[3] - 33 * Enc[4]) + 13 * Enc[5] - 2 * Enc[6]) + 42 * Enc[7] + 62 * Enc[8] + 1 * Enc[9] - 10 * Enc[10]) + 11 * Enc[11] == 12544)
s.add((((23 * Enc[0] + 6 * Enc[1] + 29 * Enc[2] + 3 * Enc[3] - 3 * Enc[4]) + 63 * Enc[5] - 25 * Enc[6]) + 2 * Enc[7] + 32 * Enc[8] + 1 * Enc[9] - 10 * Enc[10]) + 11 * Enc[11] - 12 * Enc[12] == 6585)
s.add(((((223 * Enc[0] + 6 * Enc[1] - 29 * Enc[2] - 53 * Enc[3] - 3 * Enc[4]) + 3 * Enc[5] - 65 * Enc[6]) + 0 * Enc[7] + 36 * Enc[8] + 1 * Enc[9] - 15 * Enc[10]) + 16 * Enc[11] - 18 * Enc[12]) + 13 * Enc[13] == 6893)
s.add(((((29 * Enc[0] + 13 * Enc[1] - 9 * Enc[2] - 93 * Enc[3]) + 33 * Enc[4] + 6 * Enc[5] + 65 * Enc[6] + 1 * Enc[7] - 36 * Enc[8]) + 0 * Enc[9] - 16 * Enc[10]) + 96 * Enc[11] - 68 * Enc[12]) + 33 * Enc[13] - 14 * Enc[14] == 1883)
s.add((((69 * Enc[0] + 77 * Enc[1] - 93 * Enc[2] - 12 * Enc[3]) + 0 * Enc[4] + 0 * Enc[5] + 1 * Enc[6] + 16 * Enc[7] + 36 * Enc[8] + 6 * Enc[9] + 19 * Enc[10] + 66 * Enc[11] - 8 * Enc[12]) + 38 * Enc[13] - 16 * Enc[14]) + 15 * Enc[15] == 8257)
s.add(((((23 * Enc[0] + 2 * Enc[1] - 3 * Enc[2] - 11 * Enc[3]) + 12 * Enc[4] + 24 * Enc[5] + 1 * Enc[6] + 6 * Enc[7] + 14 * Enc[8] - 0 * Enc[9]) + 1 * Enc[10] + 68 * Enc[11] - 18 * Enc[12]) + 68 * Enc[13] - 26 * Enc[14]) + 15 * Enc[15] - 16 * Enc[16] == 5847)
s.add((((((24 * Enc[0] + 0 * Enc[1] - 1 * Enc[2] - 15 * Enc[3]) + 13 * Enc[4] + 4 * Enc[5] + 16 * Enc[6] + 67 * Enc[7] + 146 * Enc[8] - 50 * Enc[9]) + 16 * Enc[10] + 6 * Enc[11] - 1 * Enc[12]) + 69 * Enc[13] - 27 * Enc[14]) + 45 * Enc[15] - 6 * Enc[16]) + 17 * Enc[17] == 18257)
s.add(((((25 * Enc[0] + 26 * Enc[1] - 89 * Enc[2]) + 16 * Enc[3] + 19 * Enc[4] + 44 * Enc[5] + 36 * Enc[6] + 66 * Enc[7] - 150 * Enc[8] - 250 * Enc[9]) + 166 * Enc[10] + 126 * Enc[11] - 11 * Enc[12]) + 690 * Enc[13] - 207 * Enc[14]) + 46 * Enc[15] + 6 * Enc[16] + 7 * Enc[17] - 18 * Enc[18] == 12591)
s.add((((((5 * Enc[0] + 26 * Enc[1] + 8 * Enc[2] + 160 * Enc[3] + 9 * Enc[4] - 4 * Enc[5]) + 36 * Enc[6] + 6 * Enc[7] - 15 * Enc[8] - 20 * Enc[9]) + 66 * Enc[10] + 16 * Enc[11] - 1 * Enc[12]) + 690 * Enc[13] - 20 * Enc[14]) + 46 * Enc[15] + 6 * Enc[16] + 7 * Enc[17] - 18 * Enc[18]) + 19 * Enc[19] == 52041)
s.add(((((((29 * Enc[0] - 26 * Enc[1]) + 0 * Enc[2] + 60 * Enc[3] + 90 * Enc[4] - 4 * Enc[5]) + 6 * Enc[6] + 6 * Enc[7] - 16 * Enc[8] - 21 * Enc[9]) + 69 * Enc[10] + 6 * Enc[11] - 12 * Enc[12]) + 69 * Enc[13] - 20 * Enc[14] - 46 * Enc[15]) + 65 * Enc[16] + 0 * Enc[17] - 1 * Enc[18]) + 39 * Enc[19] - 20 * Enc[20] == 20253)
s.add((((((((45 * Enc[0] - 56 * Enc[1]) + 10 * Enc[2] + 650 * Enc[3] - 900 * Enc[4]) + 44 * Enc[5] + 66 * Enc[6] - 6 * Enc[7] - 6 * Enc[8] - 21 * Enc[9]) + 9 * Enc[10] - 6 * Enc[11] - 12 * Enc[12]) + 69 * Enc[13] - 2 * Enc[14] - 406 * Enc[15]) + 651 * Enc[16] + 2 * Enc[17] - 10 * Enc[18]) + 69 * Enc[19] - 0 * Enc[20]) + 21 * Enc[21] == 18768)
s.add((((((555 * Enc[0] - 6666 * Enc[1]) + 70 * Enc[2] + 510 * Enc[3] - 90 * Enc[4]) + 499 * Enc[5] + 66 * Enc[6] - 66 * Enc[7] - 610 * Enc[8] - 221 * Enc[9]) + 9 * Enc[10] - 23 * Enc[11] - 102 * Enc[12]) + 6 * Enc[13] + 2050 * Enc[14] - 406 * Enc[15]) + 665 * Enc[16] + 333 * Enc[17] + 100 * Enc[18] + 609 * Enc[19] + 777 * Enc[20] + 201 * Enc[21] - 22 * Enc[22] == 111844)
s.add((((((((1 * Enc[0] - 22 * Enc[1]) + 333 * Enc[2] + 4444 * Enc[3] - 5555 * Enc[4]) + 6666 * Enc[5] - 666 * Enc[6]) + 676 * Enc[7] - 660 * Enc[8] - 22 * Enc[9]) + 9 * Enc[10] - 73 * Enc[11] - 107 * Enc[12]) + 6 * Enc[13] + 250 * Enc[14] - 6 * Enc[15]) + 65 * Enc[16] + 39 * Enc[17] + 10 * Enc[18] + 69 * Enc[19] + 777 * Enc[20] + 201 * Enc[21] - 2 * Enc[22]) + 23 * Enc[23] == 159029)
s.add((((520 * Enc[0] - 222 * Enc[1]) + 333 * Enc[2] + 4 * Enc[3] - 56655 * Enc[4]) + 6666 * Enc[5] + 666 * Enc[6] + 66 * Enc[7] - 60 * Enc[8] - 220 * Enc[9]) + 99 * Enc[10] + 73 * Enc[11] + 1007 * Enc[12] + 7777 * Enc[13] + 2500 * Enc[14] + 6666 * Enc[15] + 605 * Enc[16] + 390 * Enc[17] + 100 * Enc[18] + 609 * Enc[19] + 99999 * Enc[20] + 210 * Enc[21] + 232 * Enc[22] + 23 * Enc[23] - 24 * Enc[24] == 2762025)
s.add(((((1323 * Enc[0] - 22 * Enc[1]) + 333 * Enc[2] + 4 * Enc[3] - 55 * Enc[4]) + 666 * Enc[5] + 666 * Enc[6] + 66 * Enc[7] - 660 * Enc[8] - 220 * Enc[9]) + 99 * Enc[10] + 3 * Enc[11] + 100 * Enc[12] + 777 * Enc[13] + 2500 * Enc[14] + 6666 * Enc[15] + 605 * Enc[16] + 390 * Enc[17] + 100 * Enc[18] + 609 * Enc[19] + 9999 * Enc[20] + 210 * Enc[21] + 232 * Enc[22] + 23 * Enc[23] - 24 * Enc[24]) + 25 * Enc[25] == 1551621)
s.add((((((777 * Enc[0] - 22 * Enc[1]) + 6969 * Enc[2] + 4 * Enc[3] - 55 * Enc[4]) + 666 * Enc[5] - 6 * Enc[6]) + 96 * Enc[7] - 60 * Enc[8] - 220 * Enc[9]) + 99 * Enc[10] + 3 * Enc[11] + 100 * Enc[12] + 777 * Enc[13] + 250 * Enc[14] + 666 * Enc[15] + 65 * Enc[16] + 90 * Enc[17] + 100 * Enc[18] + 609 * Enc[19] + 999 * Enc[20] + 21 * Enc[21] + 232 * Enc[22] + 23 * Enc[23] - 24 * Enc[24]) + 25 * Enc[25] - 26 * Enc[26] == 948348)
s.add(((((((97 * Enc[0] - 22 * Enc[1]) + 6969 * Enc[2] + 4 * Enc[3] - 56 * Enc[4]) + 96 * Enc[5] - 6 * Enc[6]) + 96 * Enc[7] - 60 * Enc[8] - 20 * Enc[9]) + 99 * Enc[10] + 3 * Enc[11] + 10 * Enc[12] + 707 * Enc[13] + 250 * Enc[14] + 666 * Enc[15] + -9 * Enc[16] + 90 * Enc[17] + -2 * Enc[18] + 609 * Enc[19] + 0 * Enc[20] + 21 * Enc[21] + 2 * Enc[22] + 23 * Enc[23] - 24 * Enc[24]) + 25 * Enc[25] - 26 * Enc[26]) + 27 * Enc[27] == 777044)
s.add((((((177 * Enc[0] - 22 * Enc[1]) + 699 * Enc[2] + 64 * Enc[3] - 56 * Enc[4] - 96 * Enc[5] - 66 * Enc[6]) + 96 * Enc[7] - 60 * Enc[8] - 20 * Enc[9]) + 99 * Enc[10] + 3 * Enc[11] + 10 * Enc[12] + 707 * Enc[13] + 250 * Enc[14] + 666 * Enc[15] + -9 * Enc[16] + 0 * Enc[17] + -2 * Enc[18] + 69 * Enc[19] + 0 * Enc[20] + 21 * Enc[21] + 222 * Enc[22] + 23 * Enc[23] - 224 * Enc[24]) + 25 * Enc[25] - 26 * Enc[26]) + 27 * Enc[27] - 28 * Enc[28] == 185016)
s.add(((((((77 * Enc[0] - 2 * Enc[1]) + 6 * Enc[2] + 6 * Enc[3] - 96 * Enc[4] - 9 * Enc[5] - 6 * Enc[6]) + 96 * Enc[7] - 0 * Enc[8] - 20 * Enc[9]) + 99 * Enc[10] + 3 * Enc[11] + 10 * Enc[12] + 707 * Enc[13] + 250 * Enc[14] + 666 * Enc[15] + -9 * Enc[16] + 0 * Enc[17] + -2 * Enc[18] + 9 * Enc[19] + 0 * Enc[20] + 21 * Enc[21] + 222 * Enc[22] + 23 * Enc[23] - 224 * Enc[24]) + 26 * Enc[25] - -58 * Enc[26]) + 27 * Enc[27] - 2 * Enc[28]) + 29 * Enc[29] == 130106)

for x in Enc:
s.add(x >= 32)
s.add(x <= 126)

if s.check() == sat:
m = s.model()

solution = [m[x].as_long() if m[x] is not None else 0 for x in Enc]

decrypted = decrypt(solution)
print(decrypted)

else:
print("No solution found")

HZNUCTF{ad7fa-76a7-ff6a-fffa-7f7d6a}

XTEA

初始化置种子 srand 了一次,然后这边里面判断是否有调试,然后又 srand 了一遍,可以忽略,种子就是 0x7E8。

红框处是将输入字符串四个四个一组进行翻转。

InitKey 函数是用 rand 初始化了四个整数 Key。

XTea 是魔改的,Delta 是靠用户输入传进来的,那么这边 Delta 未知就需要爆破。

题目描述说有点 misc 味,发现附件中还有个 readme 里面的压缩包密码就是标准 Delta,2654435769 -> 0x9E3779B9

直接编写解密,使用该 Delta 就可以解出 flag。

解密代码:

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
#include <iostream>
#include <windows.h>
#include <string>
#include <time.h>

unsigned int *__fastcall dec(int _a1_, unsigned int *_a2_, unsigned int *_a3_, unsigned int _a4_)
{
unsigned int *result; // rax
unsigned int v5; // [rsp+24h] [rbp+4h]
unsigned int v6; // [rsp+44h] [rbp+24h]
unsigned int v7; // [rsp+64h] [rbp+44h]
int i; // [rsp+84h] [rbp+64h]

v5 = *_a2_;
v6 = *_a3_;
v7 = 0;
v7 = -_a1_ * 32;
for (i = 0; i < 32; ++i)
{
v6 -= (*(DWORD *)(_a4_ + 4LL * ((v7 >> 11) & 3)) + v7) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
v7 += _a1_;
v5 -= (*(DWORD *)(_a4_ + 4LL * (v7 & 3)) + v7) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
}
*_a2_ = v5;
result = _a3_;
*_a3_ = v6;
return result;
}

int main()
{
unsigned char buffer[] = {
0x24, 0x23, 0xCB, 0x8C, 0x1A, 0x74, 0xA7, 0x09,
0x8D, 0x67, 0x3C, 0xFB, 0x79, 0x3A, 0x08, 0xF6,
0x1B, 0x24, 0xCC, 0xF1, 0xF2, 0x59, 0xFA, 0x39,
0xCC, 0xE1, 0xAB, 0xF2, 0x72, 0x9F, 0x18, 0x17};
srand(0x7e8);
// 初始化Key
uint32_t key[4]{};
for (int i = 0; i < 4; i++)
key[i] = rand();

for (int j = 7; j > 0; j--)
dec(0x9E3779B9, (unsigned int *)(buffer + (j - 1) * 4), (unsigned int *)(buffer + j * 4), (uint32_t)key);

// 四个字节一组进行翻转
for (int j = 0; j < 32; j += 4)
{
auto tmp = *((char *)buffer + j + 3) | (*((char *)buffer + j + 2) << 8) | (*((char *)buffer + j + 1) << 16) | (*((char *)buffer + j) << 24);
*(int *)(buffer + j) = tmp;
}
printf("%.32s\n", buffer);

return 0;
}

HZNUCTF{ae6-9f57-4b74-b423-98eb}

randomsystem

第一部分是输入 64 字节大小的 0101 二进制数据,然后进行转换到 Hex(倒序),再倒序回来拆分半个字节转到 ascii 字符。

如:0101001001100101 第一次函数后是 0x65,0x52 然后再翻转拆分为 ascii 字符’5’,’2’,’6’,’5’。

根据判断判断出的字符可知要输入的是 52 65 56 65 52 65 53 65 的二进制数据。

0101001001100101010101100110010101010010011001010101001101100101

底下的一些加密函数里面有花指令,是基础花指令,这边不做多赘述。

第一部分用固定种子的随机数初始化了一个 v18 数值列表。

然后进行四次加密。

Enc1 是用随机数初始化的列表进行打乱输入字符串的顺序。

Enc2 是将输入字符串转存到另一个二维数组。

第三个函数是将之前输入转换后的 Key 存到”Str”中,实际值就是 ReVeReSe

第四个函数是用一个全局的矩阵乘上输入数据。

最后和 Key 进行循环异或加密。

所以解密流程就是这几步的翻转,需要先计算出全局矩阵数据的逆矩阵,这一步用在线网站就可以解得。

Enc1 由于是对称的可以直接用原函数,Enc3 也可以直接用原函数把矩阵数据改成逆矩阵就是解密。

解密代码:

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <windows.h>
#include <string>
#include <time.h>

void Enc1(char *_Str_, int *_RdList_)
{
char v3; // [esp+D3h] [ebp-1Dh]
size_t i; // [esp+DCh] [ebp-14h]
size_t v5; // [esp+E8h] [ebp-8h]

v5 = 64;
for (i = 0;; ++i)
{
auto result = v5 >> 1;
if (i >= v5 >> 1)
break;
if (_RdList_[i] >= 0 && _RdList_[i] < v5)
{
v3 = _Str_[i];
_Str_[i] = _Str_[v5 - _RdList_[i] - 1];
_Str_[v5 - _RdList_[i] - 1] = v3;
}
}
}

void Enc2(char *_a1_, char *_a2_)
{
int j; // [esp+D0h] [ebp-20h]
int i; // [esp+DCh] [ebp-14h]
int v4; // [esp+E8h] [ebp-8h]

v4 = 0;
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
*&_a1_[32 * i + 4 * j] = _a2_[v4++];
}
}

unsigned int dword_3FC368[] = {
0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001,
0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001};

int inv[] = {
1,-4,1,-2,0,5,-2,3,
0,3,-1,1,0,-3,1,-2,
0,-2,1,-1,0,2,-1,2,
0,0,0,1,0,-1,0,0,
0,-4,1,-1,1,4,-2,3,
0,1,0,0,0,0,0,-1,
0,1,0,0,0,-1,1,-1,
0,-1,0,0,0,1,0,1,
};

int Enc3(int *_a1_, char *_a2_, char *_a3_)
{
int result; // eax
int k; // [esp+D0h] [ebp-20h]
int j; // [esp+DCh] [ebp-14h]
int i; // [esp+E8h] [ebp-8h]

for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
{
_a3_[32 * i + 4 * j] = 0;
for (k = 0; k < 8; ++k)
_a3_[32 * i + 4 * j] += *&_a2_[32 * k + 4 * j] * _a1_[8 * i + k];
}
result = i + 1;
}
return result;
}

void Dec2(char *_a1_, char *_a2_)
{
int j;
int i;
int v4;

v4 = 0;
for (i = 0; i < 8; ++i)
{
for (j = 0; j < 8; ++j)
_a2_[v4++] = _a1_[32 * i + 4 * j];
}
}

unsigned char EncFlag[256] = {
0x78, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xF5, 0x01, 0x00, 0x00,
0x15, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00,
0x7C, 0x01, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
0x7D, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00, 0x5B, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00,
0x07, 0x01, 0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xE4, 0x01, 0x00, 0x00,
0x36, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, 0x5A, 0x01, 0x00, 0x00, 0x53, 0x01, 0x00, 0x00,
0x96, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
0x9E, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00,
0x9E, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7B, 0x01, 0x00, 0x00,
0x9E, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00,
0xC5, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
0xC6, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00,
0xCA, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00,
0xC1, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x9E, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
0x99, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00};

int main()
{
// First: 0101001001100101010101100110010101010010011001010101001101100101
srand(2025);
int RdList[0x80]{};
bool v16 = true;
int rd{};
for (int i = 0; i < 32; i++)
{
do
{
rd = rand() % 32;
rd &= 0x8000001F;
v16 = 1;
for (int j = 0; j < i; j++)
{
if (RdList[j] == rd)
{
v16 = 0;
break;
}
}
} while (!v16);
RdList[i] = rd;
}

char Key[] = "ReVeReSe";
int count = 0;
for (int i = 0; i < 256; i += 4)
{
*(DWORD *)(EncFlag + i) ^= Key[count % 8];
count++;
}
unsigned char Buffer_Dec[256]{};

Enc3((int *)inv, (char *)EncFlag, (char *)Buffer_Dec);
Dec2((char *)Buffer_Dec, (char *)Buffer_Dec);
Enc1((char *)Buffer_Dec, RdList);

printf("HZNUCTF{%.64s}\n", Buffer_Dec);
return 0;
}

HZNUCTF{3zfb899ac5c256d-7a8r59f0tccd-4fa6b8vfd111-a44ffy4r0-6dce5679da58}

conforand(非预期)

从 srand 查看交叉调用,发现是当前时间戳随机,并非伪随机。

查看 rand 交叉调用,发现是再 init_sbox 函数中调用,并且只获取了一次随机数,应该是利用 rand 的数值参与 sbox 生成。

那么这边的思路就是爆破随机数,但由于是 ollvm 编译的,代码混乱,使用 d810 去混淆后也是很混乱,这边就直接不分析加密代码,采取黑盒爆破手段。

接下来是先检验加密对称性,运行发现是会输出加密后的内容。

检验步骤:

  1. 随便输入一串字符串
  2. 断点 rand,修改 rand 返回值 rax 寄存器为 0。
  3. 得到输出加密内容。
  4. 再次输入字符串,断点在 main 的 rc4 调用处,将传参的字符串 patch 为刚刚程序输出的加密后字节数据。
  5. 断点 rand,修改 rand 返回值 rax 寄存器为 0。
  6. 观察输出加密内容是否为原字符串数据。

Patch 前:

Patch 后:

发现是对称的,同一个 rand 值,加密函数也可以用于解密。

开始 Patch 原程序流程,用于爆破,将 init 函数作为 hook 跳转函数。

将 rand 调用改成 jmp 到 init 函数。

init 函数头直接改成如下,将 0x4068D3 地址的数值存到 eax,然后再跳转回去,达到一个 hook 修改 rand 值结果的效果,所以我们直接加载 elf 通过修改 0x4068D3 数值,调用 rc4 加密来爆破解密密文。

这边使用这个库加载 elf 进行调用 call:https://github.com/IchildYu/load-elf (河豚鱼,神)

爆破代码(Key 是在原 init 函数中进行初始化的明文,可以直接找到):

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
#include <stdio.h>
#include <stdlib.h>
#include "include/load_elf.h"
#include "include/logger.h"
#include "include/breakpoint.h"

int main()
{
const char* path = "./conforand";
void* base = load_elf(path);

__uint64_t (*rc4)(unsigned char*, unsigned long long, unsigned char*, unsigned long long) = get_symbol_by_offset(base,0x413170);

unsigned char key[]="JustDoIt!";

for(int i=0; i<1000000; i++)
{
unsigned char EncData[]={0x83,0x1e,0x9c,0x48,0x7a,0xfa,0xe8,0x88,0x36,0xd5,0x0a,0x08,0xf6,0xa7,0x70,0x0f,0xfd,0x67,0xdd,0xd4,0x3c,0xa7,0xed,0x8d,0x51,0x10,0xce,0x6a,0x9e,0x56,0x57,0x83,0x56,0xe7,0x67,0x9a,0x67,0x22,0x24,0x6e,0xcd,0x2f};

*(unsigned int*)(0x4068D3) = i;

rc4(EncData,42,key,9);

if(EncData[0] == 'H'
&& EncData[1] == 'Z'
&& EncData[2] == 'N')
{
printf("Seed:%d\n",i);
printf("%.42s\n",EncData);
break;
}
}
return 0;
}

HZNUCTF{489b88-1305-411e-b1f4-88a3070a73}

exchange

输入的字符串经过 unhex、拆分字节,改变顺序。

如:11->0x31 0x31->‘3’ ‘1’ ‘3’ ‘1’->‘3’ ‘3’ ‘1’ ‘1’

是两个字节为一组进行变换的。

然后调用了加密函数,第一个参数传入变换后的输入,第二个参数是”HZNUCTF{“字串。

主加密函数,发现只走这上面的部分。

第一个函数是用”HZNUCTF{“字串生成的一串数据,64 个整数数据。

第二个函数是将输入数据 8 个字节为一组进行加密。

加密流程:

  1. 4 个字节为一组进行翻转
  2. 8 字节加密
  3. 4 个字节为一组进行翻转

加密可以看出是 DES 加密算法,是对称的,key 就是刚刚生成的 64 个整数数值的前 32 个,那么可以知道后 32 个就是解密用的 key,直接 copy 该函数,解密时用生成的后 32 个整数 key 即可解密。

解密代码:

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#include <iostream>
#include <windows.h>
#include <string>
#include <time.h>

unsigned int s1[64] = {
0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004};
unsigned int s2[64] = {
0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000};
unsigned int s3[64] = {
0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200};
unsigned int s4[64] = {
0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080};
unsigned int s5[64] = {
0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100};
unsigned int s6[64] = {
0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010};
unsigned int s7[64] = {
0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002};
unsigned int s8[64] = {
0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000};
unsigned short word_7FF65FC70900[8] = {
0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001};

unsigned int dword_7FF65FC70910[24] = {
0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100,
0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001};
unsigned char byte_7FF65FC70970[56] = {
0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00, 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,
0x3A, 0x32, 0x2A, 0x22, 0x1A, 0x12, 0x0A, 0x02, 0x3B, 0x33, 0x2B, 0x23, 0x3E, 0x36, 0x2E, 0x26,
0x1E, 0x16, 0x0E, 0x06, 0x3D, 0x35, 0x2D, 0x25, 0x1D, 0x15, 0x0D, 0x05, 0x3C, 0x34, 0x2C, 0x24,
0x1C, 0x14, 0x0C, 0x04, 0x1B, 0x13, 0x0B, 0x03};
unsigned char byte_7FF65FC709A8[16] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};

void __fastcall des_encrypt(unsigned int *_a1_, DWORD *_a2_)
{
unsigned int left = _a1_[1];
unsigned int right = _a1_[0];

unsigned int temp = (left ^ (right >> 4)) & 0xF0F0F0F;
left = temp ^ left;
right = (temp << 4) ^ right;

temp = (left ^ (right >> 16)) & 0x0000FFFF;
left = temp ^ left;
right = (temp << 16) ^ right;

temp = (right ^ (left >> 2)) & 0x33333333;
right = temp ^ right;
left = (temp << 2) ^ left;

temp = (right ^ (left >> 8)) & 0x00FF00FF;
right = temp ^ right;
left = (((temp << 8) ^ left) >> 31) | (2 * ((temp << 8) ^ left));

temp = (left ^ right) & 0xAAAAAAAA;
left = temp ^ left;
right = ((temp ^ right) >> 31) | (2 * (temp ^ right));

for (int i = 0; i < 8; i++)
{
temp = *_a2_++ ^ ((left >> 4) | (left << 28));
unsigned int result1 = s1[(temp >> 24) & 0x3F] |
s3[(temp >> 16) & 0x3F] |
s5[(temp >> 8) & 0x3F] |
s7[temp & 0x3F];
temp = *_a2_++ ^ left;

right ^= s2[(temp >> 24) & 0x3F] |
s4[(temp >> 16) & 0x3F] |
s6[(temp >> 8) & 0x3F] |
s8[temp & 0x3F] |
result1;

temp = *_a2_++ ^ ((right >> 4) | (right << 28));
result1 = s1[(temp >> 24) & 0x3F] |
s3[(temp >> 16) & 0x3F] |
s5[(temp >> 8) & 0x3F] |
s7[temp & 0x3F];

temp = *_a2_++ ^ right;
left ^= s2[(temp >> 24) & 0x3F] |
s4[(temp >> 16) & 0x3F] |
s6[(temp >> 8) & 0x3F] |
s8[temp & 0x3F] |
result1;
}
left = (left >> 1) | (left << 31);
temp = (left ^ right) & 0xAAAAAAAA;
left = temp ^ left;
right = ((temp ^ right) >> 1) | ((temp ^ right) << 31);

temp = (left ^ (right >> 8)) & 0xFF00FF;
left = temp ^ left;
right = (temp << 8) ^ right;

temp = (left ^ (right >> 2)) & 0x33333333;
left = temp ^ left;
right = (temp << 2) ^ right;

temp = (right ^ (left >> 16)) & 0xFFFF;
right = temp ^ right;
left = (temp << 16) ^ left;

temp = (right ^ (left >> 4)) & 0x0F0F0F0F;

_a1_[0] = (temp << 4) ^ left;
_a1_[1] = temp ^ right;
}

int main()
{
unsigned int key[64] = {
0x2C0B3C36, 0x09221A0A, 0x2829051D, 0x09123B0D, 0x2C091B18, 0x0512011F, 0x09292E17, 0x07122920,
0x090D1703, 0x0514372E, 0x0915123C, 0x27100E27, 0x01050927, 0x25150D29, 0x13151F32, 0x24112618,
0x03052031, 0x34312B37, 0x13043A05, 0x3C19151B, 0x23063B3E, 0x34293830, 0x03062108, 0x380B3F2A,
0x260E063D, 0x3009141B, 0x0E223D3D, 0x300B0124, 0x062A1700, 0x11093D14, 0x0E22262B, 0x1208083E,
0x0E22262B, 0x1208083E, 0x062A1700, 0x11093D14, 0x0E223D3D, 0x300B0124, 0x260E063D, 0x3009141B,
0x03062108, 0x380B3F2A, 0x23063B3E, 0x34293830, 0x13043A05, 0x3C19151B, 0x03052031, 0x34312B37,
0x13151F32, 0x24112618, 0x01050927, 0x25150D29, 0x0915123C, 0x27100E27, 0x090D1703, 0x0514372E,
0x09292E17, 0x07122920, 0x2C091B18, 0x0512011F, 0x2829051D, 0x09123B0D, 0x2C0B3C36, 0x09221A0A};

unsigned int data[64] = {
0x00000084, 0x0000008B, 0x00000003, 0x00000022, 0x00000014, 0x000000BE, 0x000000DF, 0x00000075,
0x000000B3, 0x000000D5, 0x00000076, 0x0000006F, 0x000000CD, 0x0000002A, 0x0000005D, 0x000000D7,
0x0000004D, 0x000000B2, 0x0000005F, 0x00000006, 0x00000098, 0x0000009D, 0x0000003E, 0x000000A8,
0x000000F7, 0x00000023, 0x000000F2, 0x0000008B, 0x000000F2, 0x00000054, 0x00000065, 0x0000007A,
0x00000020, 0x000000C0, 0x00000087, 0x00000055, 0x000000D6, 0x0000003B, 0x00000046, 0x0000003D,
0x000000F7, 0x000000B2, 0x0000007A, 0x0000009D, 0x000000C2, 0x000000CF, 0x0000001A, 0x000000AE,
0x00000016, 0x000000C7, 0x00000015, 0x00000030, 0x0000008E, 0x000000FD, 0x0000008F, 0x0000009E,
0x000000AA, 0x00000039, 0x000000AB, 0x000000FE, 0x00000095, 0x000000A7, 0x0000001F, 0x000000F1};

unsigned char Enc[64]{};
for (int i = 0; i < 64; i++)
Enc[i] = data[i];

// 四字节一组翻转
for (int i = 0; i < 64; i += 4)
{
auto a = Enc[i], b = Enc[i + 1], c = Enc[i + 2], d = Enc[i + 3];
Enc[i] = d;
Enc[i + 1] = c;
Enc[i + 2] = b;
Enc[i + 3] = a;
}

// DES解密(用后32个key)
for (int i = 0; i < 64; i += 8)
des_encrypt((unsigned int *)(Enc + i), (DWORD *)(key + 32));

// 四字节一组翻转
for (int i = 0; i < 64; i += 4)
{
auto a = Enc[i], b = Enc[i + 1], c = Enc[i + 2], d = Enc[i + 3];
Enc[i] = d;
Enc[i + 1] = c;
Enc[i + 2] = b;
Enc[i + 3] = a;
}

printf("HZNUCTF{");
// 逆向初始字符串变换
for (int i = 0; i < 64; i += 4)
{
std::string tmp1;
tmp1 += Enc[i];
tmp1 += Enc[i + 2];

std::string tmp2;
tmp2 += Enc[i + 1];
tmp2 += Enc[i + 3];

printf("%c", char(std::stoi(tmp1, 0, 16)));
printf("%c", char(std::stoi(tmp2, 0, 16)));
}

printf("}\n");

return 0;
}

HZNUCTF{391ds2b9-9e31-45f8-ba4a-4904a2d8}

Index

下载附件发现 wasm 文件开头字节和正常 wasm 文件不一样,复制修复即可。

左题目附件,右正常 wasm 文件。

使用 ghidra 进行分析,因为有专门的 wasm 反编译插件。

通过 Exports 定位到 main 函数,以下是经过我重命名后的结果。

首先是输入 key,然后判断和该处明文是否相等。

然后将 Key xor 上 0x51。

第一步加密,置了随机数种子 0x194,然后用随机数打乱输入的字符串,再转存到另一个 Out 数组。

第二步加密(四个字节一组加密):

  1. 用 key 获取到两个值,然后全局数值 iRam0001120++,每次加密都 +1,初始值是 0。
  2. 调用一个函数将 0x10ea0 处数据异或上 0x10da0 取下标的对应值。
  3. 再将输入字符串异或上 0x10ea0 对应下标数据以及 0x11020 对应下标数据,0x11020 处数据就是原 Key 字符串**”TGCTF404”**。

最后再与 0x10fa0 处数据进行比对,所以 0x10fa0 处就是加密后的 flag。

导出 0x10ea0 和 0x10da0 数据,编写以上代码的逆向解密代码即可。

解密代码:

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <Windows.h>

// 0x10da0处数据
unsigned char box[] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};

// 0x10ea0处数据
unsigned char box_ori[] = {
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48};

void unnamed_function_10(byte *_param1_, int _param2_)
{
for (int i = 0; i < 0x100; i = i + 1)
{
_param1_[i] = _param1_[i] ^ (byte)_param2_;
}
return;
}

unsigned char Enc[] = {
0x84, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00,
0x6b, 0x00, 0x00, 0x00,
0xf7, 0x00, 0x00, 0x00,
0x49, 0x00, 0x00, 0x00,
0x22, 0x00, 0x00, 0x00,
0xd6, 0x00, 0x00, 0x00,
0x42, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00,
0x7b, 0x00, 0x00, 0x00,
0x42, 0x00, 0x00, 0x00,
0xf4, 0x00, 0x00, 0x00,
0x46, 0x00, 0x00, 0x00,
0xa9, 0x00, 0x00, 0x00,
0x83, 0x00, 0x00, 0x00,
0x62, 0x00, 0x00, 0x00,
0xd1, 0x00, 0x00, 0x00,
0x32, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
0x42, 0x00, 0x00, 0x00,
0x6a, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0xa3, 0x00, 0x00, 0x00,
0xf2, 0x00, 0x00, 0x00,
0xe2, 0x00, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x00, 0x00,
0x76, 0x00, 0x00, 0x00,
0xb0, 0x00, 0x00, 0x00,
0xdc, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x51, 0x00, 0x00, 0x00};

void Dec_2(unsigned char *_Input_, unsigned char *_Key_)
{
static int c = 0;
int iVar1 = (int)_Key_[c] >> 4;
DWORD uVar2 = (int)_Key_[c] & 0xf;
c++;
unnamed_function_10(box_ori, (int)*(char *)(iVar1 * 0x10 + (unsigned char *)box + uVar2));
unsigned char key_o[] = "TGCTF404";
for (int i = 0; i < 4; i++)
{
_Input_[i] = _Input_[i] ^ box_ori2[iVar1 * 0x10 + i * 0x11 + uVar2];
_Input_[i] = _Input_[i] ^ key_o[i];
}
}

void decrypt(unsigned char *_Input_, int _length_)
{
unsigned char Key[] = "TGCTF404";

for (int i = 0; i < 8; i++)
Key[i] ^= 0x51;

for (int i = 0; i < _length_; i += 4)
{
Dec_2((unsigned char *)(_Input_ + i), Key);
}

srand(0x194);

int swaps[32][2];
for (int i = 0; i < 32; i++)
{
auto Value = rand();
Value = i + Value / (0x7fff / (32 - i) + 1);
swaps[i][0] = i;
swaps[i][1] = Value;
}

for (int i = 31; i >= 0; i--)
{
unsigned char temp = _Input_[swaps[i][0]];
_Input_[swaps[i][0]] = _Input_[swaps[i][1]];
_Input_[swaps[i][1]] = temp;
}
}

int main()
{
unsigned char Key[] = "TGCTF404";
unsigned char Enc_flag[32]{};

for (int i = 0; i < 32; i++)
Enc_flag[i] = *(int *)((byte *)Enc + i * 4);

decrypt(Enc_flag, 32);

printf("%.32s\n", Enc_flag);
return 0;
}

HZNUCTF{f898-de85-46e-9e43-b9c8}