这道题的前面一部分我分析不是很清楚,参考了其他大佬的博客才能理解

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rbx
__int64 v4; // rax
__int128 *v5; // rax
__int64 v6; // r11
__int128 *v7; // r14
int v8; // edi
__int128 *v9; // rsi
char v10; // r10
int v11; // edx
__int64 v12; // r8
unsigned __int64 v13; // rcx
__int64 v14; // rcx
unsigned __int64 v15; // rax
unsigned __int64 i; // rax
__int64 v17; // rax
size_t v18; // rsi
_BYTE *v19; // rbx
_BYTE *v20; // r9
int v21; // er11
char *v22; // r8
__int64 v23; // rcx
char v24; // al
__int64 v25; // r9
__int64 v26; // rdx
__int64 v27; // rax
size_t Size; // [rsp+20h] [rbp-48h] BYREF
__int128 v30; // [rsp+28h] [rbp-40h] BYREF
int v31; // [rsp+38h] [rbp-30h]
int v32; // [rsp+3Ch] [rbp-2Ch]
int Code[4]; // [rsp+40h] [rbp-28h] BYREF
int v34; // [rsp+50h] [rbp-18h]

*Code = 0i64;
v34 = 0;
sub_1400018C0(std::cin, argv, Code);
v3 = -1i64;
v4 = -1i64;
do
++v4;
while ( *(Code + v4) );
if ( v4 != 19 )
{
sub_140001620(std::cout, "error\n");
_exit(Code);
}
v5 = operator new(5ui64);
v6 = *&::Code;
v7 = v5;
v8 = 0;
v9 = v5;
do
{
v10 = *(v9 + Code - v5);
v11 = 0;
*v9 = v10;
v12 = 0i64;
v13 = -1i64;
do
++v13;
while ( *(v6 + v13) );
if ( v13 )
{
do
{
if ( v10 == *(v6 + v12) )
break;
++v11;
++v12;
}
while ( v11 < v13 );
}
v14 = -1i64;
do
++v14;
while ( *(v6 + v14) );
if ( v11 == v14 )
_exit(v6);
v9 = (v9 + 1);
}
while ( v9 - v5 < 4 );
*(v5 + 4) = 0;
do
++v3;
while ( *(Code + v3) );
v15 = 0i64;
v30 = *v7;
while ( *(&v30 + v15) )
{
if ( !*(&v30 + v15 + 1) )
{
++v15;
break;
}
if ( !*(&v30 + v15 + 2) )
{
v15 += 2i64;
break;
}
if ( !*(&v30 + v15 + 3) )
{
v15 += 3i64;
break;
}
v15 += 4i64;
if ( v15 >= 16 )
break;
}
for ( i = v15 + 1; i < 0x10; ++i )
*(&v30 + i) = 0;
v17 = sub_140001AB0(Code, v3, &v30, &Size);
v18 = Size;
v19 = v17;
v20 = operator new(Size);
v21 = 1;
*v20 = v19[2];
v22 = v20 + 1;
v20[1] = *v19;
v20[2] = v19[3];
v20[3] = v19[1];
v20[4] = v19[6];
v20[5] = v19[4];
v20[6] = v19[7];
v20[7] = v19[5];
v20[8] = v19[10];
v20[9] = v19[8];
v20[10] = v19[11];
v20[11] = v19[9];
v20[12] = v19[14];
v20[13] = v19[12];
v20[14] = v19[15];
v20[15] = v19[13];
v20[16] = v19[18];
v20[17] = v19[16];
v20[18] = v19[19];
v20[19] = v19[17];
v20[20] = v19[22];
v20[21] = v19[20];
v20[22] = v19[23];
for ( v20[23] = v19[21]; v21 < v18; ++v22 )
{
v23 = 0i64;
if ( v21 / 3 > 0 )
{
v24 = *v22;
do
{
v24 ^= v20[v23++];
*v22 = v24;
}
while ( v23 < v21 / 3 );
}
++v21;
}
*&v30 = 0xC0953A7C6B40BCCEui64;
v25 = v20 - &v30;
*(&v30 + 1) = 0x3502F79120209BEFi64;
v26 = 0i64;
v31 = 0xC8021823;
v32 = 0xFA5656E7;
do
{
if ( *(&v30 + v26) != *(&v30 + v26 + v25) )
_exit(v8 * v8);
++v8;
++v26;
}
while ( v26 < 24 );
v27 = sub_140001620(std::cout, "You win!");
std::ostream::operator<<(v27, sub_1400017F0);
return 0;
}

用 findcrypt 看了一下,sub_140001AB0 这个函数是 xxtea 加密,然后在加密之后,后面对加密后的 flag 乱了一下顺序,再每 3 个数据位一组,进行了一些异或操作

至于前面一部分的操作,大佬的博客是这样说的

  1. 判断输入的字符串的每个字符是否包含在 "qwertyuiopasdfghjklzxcvbnm1234567890" 中
  2. 取输入字符串的前 4 位字符,即 "flag",扩展为 16 位,作为 xxtea 加密的秘钥 key

其中的 flag 扩展为 16 位,就只要在右端补 0 就可以了

由最后的 if 条件可知,v30,v30+1,v31,v32 就是最后的结果,这里要注意一下小端序的问题,要反过来写

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
import xxtea

result = 'CE BC 40 6B 7C 3A 95 C0 EF 9B 20 20 91 F7 02 35 23 18 02 C8 E7 56 56 FA'.split(" ")
res = [int(i,16) for i in result]

for i in range(7,-1,-1):
t = 0
for n in range(0,i):
if t == 0:
t = res[0]
else:
t ^= res[n]
for j in range(3):
res[i*3+j] ^= t

box = [1,3,0,2,5,7,4,6,9,11,8,10,13,15,12,14,17,19,16,18,21,23,20,22]
m = []


for i in range(len(box)):
m.append(res[box[i]])
print(m)

key = 'flag'+'\x00'*12

print(xxtea.decrypt(bytes(m),key,padding=False))

得到 flag:flag