SCTF2019 babyre

babyre

附件

  • babygame

分析

IDA打开,定位到main函数:

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
void __fastcall main(int a1, char **a2, char **a3)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

v17 = __readfsqword(0x28u);
v4 = 0;
memset(str2, 0, sizeof(str2));
v11 = 0;
memset(v12, 0, sizeof(v12));
v13 = 0;
memset(v14, 0, sizeof(v14));
v15 = 0;
strcpy(
v16,
"**************.****.**s..*..******.****.***********..***..**..#*..***..***.********************.**..*******..**...*..*.*.**.*");
*(_QWORD *)&v7[5] = 0LL;
v8 = 0LL;
v9 = 0;
v6 = &v16[22];
strcpy((char *)v7, "sctf_9102");
puts("plz tell me the shortest password1:");
scanf("%s", v14);
v5 = 1;
while ( v5 )
{
v3 = *((_BYTE *)v14 + v4);
switch ( v3 )
{
case 'w':
v6 -= 5;
break;
case 's':
v6 += 5;
break;
case 'd':
++v6;
break;
case 'a':
--v6;
break;
case 'x':
v6 += 25;
break;
case 'y':
v6 -= 25;
break;
default:
v5 = 0;
break;
}
++v4;
if ( *v6 != '.' && *v6 != '#' )
v5 = 0;
if ( *v6 == '#' )
{
puts("good!you find the right way!\nBut there is another challenge!");
break;
}
}
if ( v5 )
{
puts("plz tell me the password2:");
scanf("%s", str2);
sub_561F47600C22((const char *)str2, (__int64)v12);
if ( (unsigned int)sub_561F47600F67((const char *)v12, (const char *)v7) == 1 )
{
puts("Congratulation!");
puts("Now,this is the last!");
puts("plz tell me the password3:");
scanf("%s", &v7[5]);
if ( (unsigned int)sub_561F47600FFA((char *)&v7[5]) == 1 )
{
puts("Congratulation!Here is your flag!:");
printf("sctf{%s-%s(%s)}", (const char *)v14, (const char *)str2, (const char *)&v7[5]);
}
else
{
printf("something srong...");
}
}
else
{
printf("sorry,somthing wrong...");
}
}
else
{
printf("sorry,is't not a right way...");
}
}

可以看到password1是走迷宫之类的一关, 根据switch里面的操作确定出了迷宫的长宽, 最开始以为就是一个平面的走迷宫, 最后发现flag提交不上去(password2、3都正确)才知道是一个立体的5x5x6迷宫.

那么迷宫部分就不再多说了, 接着看password2. 其中 sub_561F47600C22 是加密过程, sub_561F47600F67 用于检测, 密文是字符串 sctf_9102 .

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
void __fastcall sub_561F47600C22(const char *a1, __int64 a2)
{
int v2; // eax
int v3; // eax
int v4; // eax
int v5; // [rsp+14h] [rbp-24Ch]
int v6; // [rsp+18h] [rbp-248h]
int v7; // [rsp+1Ch] [rbp-244h]
int v8; // [rsp+20h] [rbp-240h]
int v9; // [rsp+24h] [rbp-23Ch]
int str2len; // [rsp+28h] [rbp-238h]
int v11; // [rsp+2Ch] [rbp-234h]
const char *v12; // [rsp+48h] [rbp-218h]
int v13[130]; // [rsp+50h] [rbp-210h] BYREF
unsigned __int64 v14; // [rsp+258h] [rbp-8h]

v14 = __readfsqword(0x28u);
qmemcpy(v13, dword_561F47601740, 512uLL);
v6 = 3;
v5 = 0;
v8 = 0;
v9 = 0;
str2len = strlen(a1);
v12 = a1;
while ( 1 )
{
v11 = 0;
if ( v8 < str2len )
break;
LABEL_7:
if ( v8 >= str2len )
goto LABEL_8;
}
do
{
if ( a1[v8] != 25 )
break;
++v8;
++v11;
}
while ( v8 < str2len );
if ( v8 != str2len )
{
++v8;
goto LABEL_7;
}
LABEL_8:
v7 = 0;
while ( str2len > 0 )
{
v6 -= v13[*v12] == '@';
v5 = v13[*v12] & 0x3F | (v5 << 6);
if ( ++v7 == 4 )
{
v7 = 0;
if ( v6 )
{
v2 = v9++;
*(_BYTE *)(v2 + a2) = BYTE2(v5);
}
if ( v6 > 1 )
{
v3 = v9++;
*(_BYTE *)(v3 + a2) = BYTE1(v5);
}
if ( v6 > 2 )
{
v4 = v9++;
*(_BYTE *)(v4 + a2) = v5;
}
}
++v12;
--str2len;
}
}

其中的明文左移6位进行或运算、AND 0x3F取后六位、四字节为一组与base64算法有很多相似之处, 另外, dword_561F47601740 存放着加密使用到的Table.

懒得写脚本了, 直接在py命令行找出 sctf_9102 对应的Table值了.

1
2
3
4
5
6
7
>>> import libnum
>>> s = libnum.s2b('sctf_9102')
'011100110110001101110100011001100101111100111001001100010011000000110010'
>>> for i in range(0, len(s), 6):
... print(int(s[i:i+6], 2), end=', ')
28, 54, 13, 52, 25, 37, 60, 57, 12, 19, 0, 50,
>>>

接下来通过上面的值 [28, 54, 13, 52, 25, 37, 60, 57, 12, 19, 0, 50,] 找出其在Table中的索引值组合成字符串就可以了(见解密代码中的decrypt2函数).

最后看password3, 核心代码就在一个 sub_561F47600FFA 函数里面, v8是比较用的密文, 该函数首先使用 sub_561F4760078A 将 a1 每四个字节为一组并使用 BYTE_SWAP 在组内进行逆序存储到v10的0至3号索引处.

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
__int64 __fastcall sub_561F47600FFA(char *a1)
{
int v2; // [rsp+18h] [rbp-158h]
int i; // [rsp+18h] [rbp-158h]
int v4; // [rsp+1Ch] [rbp-154h]
int v5; // [rsp+24h] [rbp-14Ch]
int v6; // [rsp+28h] [rbp-148h]
int v7; // [rsp+2Ch] [rbp-144h]
int v8[16]; // [rsp+30h] [rbp-140h]
int v9[16]; // [rsp+70h] [rbp-100h]
int v10[30]; // [rsp+B0h] [rbp-C0h]
unsigned __int64 v11; // [rsp+168h] [rbp-8h]

v11 = __readfsqword(0x28u);
v8[0] = 0xBE;
v8[1] = 4;
v8[2] = 6;
v8[3] = 0x80;
v8[4] = 0xC5;
v8[5] = 0xAF;
v8[6] = 0x76;
v8[7] = 0x47;
v8[8] = 0x9F;
v8[9] = 0xCC;
v8[10] = 0x40;
v8[11] = 0x1F;
v8[12] = 0xD8;
v8[13] = 0xBF;
v8[14] = 0x92;
v8[15] = 0xEF;
v5 = (a1[6] << 8) | (a1[5] << 16) | (a1[4] << 24) | a1[7];
v6 = (a1[10] << 8) | (a1[9] << 16) | (a1[8] << 24) | a1[11];
v7 = (a1[14] << 8) | (a1[13] << 16) | (a1[12] << 24) | a1[15];
v4 = 0;
v2 = 4;
v10[0] = sub_561F4760078A((a1[2] << 8) | (a1[1] << 16) | (*a1 << 24) | (unsigned int)a1[3]);
v10[1] = sub_561F4760078A(v5);
v10[2] = sub_561F4760078A(v6);
v10[3] = sub_561F4760078A(v7);
do
{
v10[v2] = sub_561F4760143B(v10[v4], v10[v4 + 1], v10[v4 + 2], v10[v4 + 3]);
++v4;
++v2;
}
while ( v2 <= 29 );
v9[0] = HIBYTE(v10[26]);
v9[1] = BYTE2(v10[26]);
v9[2] = BYTE1(v10[26]);
v9[3] = LOBYTE(v10[26]);
v9[4] = HIBYTE(v10[27]);
v9[5] = BYTE2(v10[27]);
v9[6] = BYTE1(v10[27]);
v9[7] = LOBYTE(v10[27]);
v9[8] = HIBYTE(v10[28]);
v9[9] = BYTE2(v10[28]);
v9[10] = BYTE1(v10[28]);
v9[11] = LOBYTE(v10[28]);
v9[12] = HIBYTE(v10[29]);
v9[13] = BYTE2(v10[29]);
v9[14] = BYTE1(v10[29]);
v9[15] = LOBYTE(v10[29]);
for ( i = 0; i <= 15; ++i )
{
if ( v9[i] != v8[i] )
return 0xFFFFFFFFLL;
}
return 1LL;
}

随后, 循环加密v10并将其进行拓展, 从4号索引到29号索引就是拓展出的. 拓展的规律是v10[i] = sub_561F4760143B(v10[i - 4], v10[i - 3], v10[i - 2], v10[i - 1]). 最后再次将v10的26至29号索引对应的值打乱到v9中, 随即将v8、v9进行比较.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall sub_55555540143B(int a1, int a2, int a3, unsigned int a4)
{
return a1 ^ (unsigned int)sub_561F47601464(a2 ^ a3 ^ a4);
}

__int64 __fastcall sub_561F47601464(unsigned int a1)
{
int v2; // [rsp+18h] [rbp-498h]
int v3[290]; // [rsp+20h] [rbp-490h] BYREF
unsigned __int64 v4; // [rsp+4A8h] [rbp-8h]

v4 = __readfsqword(0x28u);
qmemcpy(v3, &byte_561F47601940, 0x480uLL);
v2 = (v3[BYTE2(a1)] << 16) | v3[(unsigned __int8)a1] | (v3[BYTE1(a1)] << 8) | (v3[HIBYTE(a1)] << 24);
return __ROL4__(v2, 12) ^ (unsigned int)(__ROL4__(v2, 8) ^ __ROR4__(v2, 2)) ^ __ROR4__(v2, 6);
}

对于v10的索引为4到29元素, 每个值只与它前面四个值有关, 比如 v10[29] = v10[25] ^ sub_561F47601464(v10[24], v10[23], v10[22])v10[4] = v10[3] ^ sub_561F47601464(v10[2], v10[1], v10[0]). sub_561F47601464 只负责计算出最外层xor所使用的key无需逆向. 所以只需模拟 sub_55555540143Bsub_561F47601464 即可. 另外不难看出, v10[25] = v10[29] ^ sub_561F47601464(v10[24], v10[23], v10[22])v10[3] = v10[4] ^ sub_561F47601464(v10[2], v10[1], v10[0]).

解密代码

因为是C++代码, 而且用到了IDA提供的头文件defs.h, 所以需要将头文件复制到C++代码同一目录下或自己设置C++编译器寻找头文件的规则.

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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*

stage 1
*****
*****
****.
****.
**s..
*..**
****.
****.
*****
*****
*..**
*..**
..#*.
.***.
.***.
*****
*****
*****
*****
.**..
*****
**..*
*...*
..*.*
.**.*

answer: sxss (错的)
ddwwxxssxaxwwaasasyywwdd (正确)
*/

#include <iostream>
#include <cstdint>
#include "defs.h"

unsigned char ida_chars[] =
{
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x00,
0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00,
0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00,
0x3B, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3D, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00,
0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00,
0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00,
0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x1A, 0x00,
0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00,
0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00,
0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2E, 0x00,
0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x00};

unsigned char ida_chars2[] =
{
0xD6, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xE9, 0x00,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00,
0xE1, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0xB7, 0x00,
0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x67, 0x00,
0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00,
0x44, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x26, 0x00,
0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9C, 0x00,
0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
0xF4, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xEF, 0x00,
0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00,
0x33, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0B, 0x00,
0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00,
0xCF, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0x62, 0x00,
0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00,
0x1C, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xC9, 0x00,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00,
0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xDF, 0x00,
0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00,
0x75, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x3F, 0x00,
0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xFC, 0x00,
0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0x83, 0x00,
0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x85, 0x00,
0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00,
0x68, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x81, 0x00,
0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x8B, 0x00,
0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x70, 0x00,
0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00,
0x35, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x24, 0x00,
0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00,
0x63, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xD1, 0x00,
0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x22, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x3B, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0xD4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
0x57, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xD3, 0x00,
0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
0x4C, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00,
0xC4, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x9E, 0x00,
0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
0xB5, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0xF7, 0x00,
0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00,
0xF9, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x15, 0x00,
0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00,
0xAE, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0xA4, 0x00,
0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xAD, 0x00,
0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0x8C, 0x00,
0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00,
0x1D, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0xE2, 0x00,
0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
0x66, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x60, 0x00,
0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x0D, 0x00,
0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00,
0x6F, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0xDB, 0x00,
0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
0xDE, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x8E, 0x00,
0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x72, 0x00,
0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x5B, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x8D, 0x00,
0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00,
0x92, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xDD, 0x00,
0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0x5C, 0x00,
0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0xD8, 0x00,
0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00,
0x31, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xA5, 0x00,
0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00,
0xBD, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x74, 0x00,
0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
0xB8, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xB4, 0x00,
0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00,
0x69, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x4A, 0x00,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
0x77, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x65, 0x00,
0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0x6E, 0x00,
0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x7D, 0x00,
0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00,
0xDC, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00,
0x5F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xD7, 0x00,
0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
0x48, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xBA, 0x00,
0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xAA, 0x00,
0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00,
0x91, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x67, 0x00,
0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x70, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00};

void decrypt2()
{
// stage 2
uint8_t s[] = {
28, 54, 13, 52, 25, 37, 60, 57, 12, 19, 0, 50};
uint32_t *key = (uint32_t *)ida_chars;

for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 128; j++)
{
if (key[j] == s[i])
{
std::cout << char(j);
}
}
}

std::cout << std::endl;
}

uint64_t sub_561F47601464(unsigned int a1)
{
int v2; // [rsp+18h] [rbp-498h]
int *v3; // [rsp+20h] [rbp-490h] BYREF
unsigned __int64 v4; // [rsp+4A8h] [rbp-8h]
v3 = (int *)ida_chars2;
v2 = (v3[(uint8_t)BYTEn(a1, 2)] << 16) | v3[(uint8_t)a1] | (v3[BYTEn(a1, 1)] << 8) | (v3[BYTEn(a1, 3)] << 24);
return __ROL4__(v2, 12) ^ (unsigned int)(__ROL4__(v2, 8) ^ __ROR4__(v2, 2)) ^ __ROR4__(v2, 6);
}

uint64_t sub_55555540143B(int a1, int a2, int a3, unsigned int a4)
{
return a1 ^ (unsigned int)sub_561F47601464(a2 ^ a3 ^ a4);
}

uint64_t sub_55555540078A(unsigned int a1)
{
uint8_t *tmp = (uint8_t *)&a1;
uint32_t res = 0;
uint8_t *p_res = (uint8_t *)&res;
p_res[0] = tmp[3];
p_res[1] = tmp[2];
p_res[2] = tmp[1];
p_res[3] = tmp[0];
return res;
}

void decrypt3()
{
uint32_t v8[] = {
0xBE, 4, 6, 0x80, 0xC5, 0xAF, 0x76, 0x47, 0x9F, 0xCC, 0x40, 0x1F, 0xD8, 0xBF, 0x92, 0xEF};
uint32_t v10[30];
uint8_t *tmp = (uint8_t *)(v10 + 26);

tmp[0] = v8[3];
tmp[1] = v8[2];
tmp[2] = v8[1];
tmp[3] = v8[0];
tmp[4] = v8[7];
tmp[5] = v8[6];
tmp[6] = v8[5];
tmp[7] = v8[4];
tmp[8] = v8[11];
tmp[9] = v8[10];
tmp[10] = v8[9];
tmp[11] = v8[8];
tmp[12] = v8[15];
tmp[13] = v8[14];
tmp[14] = v8[13];
tmp[15] = v8[12];

for (int i = 29; i >= 4; i--)
{
v10[i - 4] = sub_55555540143B(v10[i], v10[i - 3], v10[i - 2], v10[i - 1]);
}

v10[0] = sub_55555540078A(v10[0]);
v10[1] = sub_55555540078A(v10[1]);
v10[2] = sub_55555540078A(v10[2]);
v10[3] = sub_55555540078A(v10[3]);

printf("%x%x%x%x\n", v10[0], v10[1], v10[2], v10[3]);

}

int main(int argc, const char *argv[])
{
decrypt2();
decrypt3();
/*
decrypt3 结果: 666c34675f69735f73305f7567317921

>>> libnum.n2s(0x666c34675f69735f73305f7567317921)
b'fl4g_is_s0_ug1y!'
*/
return 0;
}