0%

re2

re2

国赛分赛区re

puzzle

是个upx壳,自动脱壳没脱掉,原来是upx的特征被改了,下面UPX全部被改成了vmp,全部恢复成UPX再脱壳就行,但不能调试,应该是文件到内存的偏移存在问题。

image-20220705231608958

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
 *(_QWORD *)v20 = fmt_Fprintf((__int64)&off_505F00, qword_588528, "Input: ", 7LL, v2, 0LL, 0LL, v16, v17, v18);
v38[0] = "\b";
v38[1] = v35;
v11 = &off_505EE0;
v12 = (__int64 *)qword_588520;
*(_QWORD *)v13 = "%s";
*(_QWORD *)&v13[8] = 2LL;
*(_QWORD *)&v13[16] = v38;
v14 = 1LL;
v15 = 1LL;
fmt_Fscanf((__int64)v1, v0, (const char *)&off_505EE0);
if ( !v17 )
{
v3 = v35;
v4 = 0LL;
v5 = 0LL;
while ( v4 < 9 )//主要加密
{
for ( i = 0LL; i < 9; ++i )
{
v1 = (__int64 *)v40[3 * v4 - 1];
if ( v40[3 * v4] <= (unsigned __int64)i )
sub_466740((__int64)v11, (__int64)v12);
v0 = *((unsigned __int8 *)v1 + i);
if ( !(_BYTE)v0 )
{
v7 = v3[1];
if ( v7 <= v5 )
goto LABEL_13;
if ( v7 <= (unsigned __int64)v5 )
sub_466740((__int64)v11, (__int64)v12);
v8 = *(unsigned __int8 *)(v5 + *v3);
if ( (unsigned __int8)v8 < '0' || (unsigned __int8)v8 > '9' )
goto LABEL_13;
v0 = (unsigned int)(v8 - 48);
*((_BYTE *)v1 + i) = v0;
++v5;
}
}
++v4;
}
if ( v3[1] == v5 && (v15 = sub_4B8720((__int64)&v39, 9LL, 9, v13[8]), v13[8]) )
{
v17 = runtime_stringtoslicebyte((__int64)v34, *v35, v35[1], *(__int64 *)&v13[8], *(__int64 *)&v13[16], v14);
v16 = sub_4938A0(*(__int64 *)&v13[8], *(__int64 *)&v13[16], v14, *(__int128 *)&v13[8]);
v32 = *(_OWORD *)&v13[8];
v33 = *(_OWORD *)&v13[8];
runtime_convT2Enoptr((__int64)&unk_4C6160, (__int64)&v33, *(__int64 *)v13, *(__int64 *)&v13[8]);
v37 = *(_OWORD *)v13;
v11 = &off_505F00;
v12 = (__int64 *)qword_588528;
*(_QWORD *)v13 = "Your flag is flag{%x}async stack too l";
*(_QWORD *)&v13[8] = 21LL;
*(_QWORD *)&v13[16] = &v37;
v14 = 1LL;
v15 = 1LL;
fmt_Fprintf((__int64)v1, v0, v9);
}
else
{
LABEL_13:
v36[0] = &unk_4C5940;
v36[1] = &off_504828; // Wrong!
*(_QWORD *)&v19 = fmt_Fprintln((__int64)&off_505F00, qword_588528, (__int64)v36, 1LL, 1LL, v14, v15, v16);
}
}
}

这是个go程序,直接找到main_main发现符号表并没有损坏,直接看,发现应该是个数独,毕竟这一周做了两道数独了。

但是从静态是看不到数独的图的,所以只能动态,用程序脱壳后的程序并不能动调,所以得手动跟,比较不好跟。

直接找到rsp的地址后,步入sub_5AB660

image-20220803151134283

sub_5AB700

image-20220803151228497

sub_5AF500

image-20220803151237196

sub_5ADBA0

image-20220803151245375

sub_5D4300

image-20220803151255502

到sub_628C40

image-20220803151322255

发现call rax ; sub_628C40进去就是main_main,发现了加载地图的地方

image-20220803151527692

查看v48

image-20220803151556289

就是地图

image-20220803151843891

得到flag

havetea

动调可以发现就是一个tea加密和xtea加密

image-20220706163158211

发现输入16字节,8字节传入,进行两次tea加密

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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0x9E3779B9 * 32, i; /* set up */
uint32_t delta = 0x9E3779B9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}

int main()
{
uint32_t v[] = { 0xE66F0E9E, 0x42A17CD6 }, k[4] = { 0x9e,0x37,0x79,0xb9 }, v1[] = { 0x5BDDE878, 0xD236F4AD };
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
decrypt(v, k);
printf("decode:%x %x\n", v[0], v[1]);
decrypt(v1, k);
printf("decode:%x %x\n", v1[0], v1[1]);
return 0;
}
倒序就是密码:please_drink_tea

然后就是一个xtea加密

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
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}

int main()
{
uint32_t v[] = { 0x7D758E0A, 0xEDAFF6AD }, v1[] = { 0x9DDE7E86, 0xE3D36CD5 }, v2[] = { 0xABD3C82E, 0x6B7B2CFE }, v3[] = { 0x2C6608C2, 0x0686A1DA };
uint32_t const k[4] = { 0x61656C70, 0x645F6573, 0x6B6E6972, 0x6165745F };
unsigned int r = 32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
decipher(r, v, k);
decipher(r, v1, k);
decipher(r, v2, k);
decipher(r, v3, k);
printf("decode:%x %x\n", v[0], v[1]);
printf("decode:%x %x\n", v1[0], v1[1]);
printf("decode:%x %x\n", v2[0], v2[1]);
printf("decode:%x %x\n", v3[0], v3[1]);
return 0;
}

倒序转换成字符就行了

_rdtsc

creak3

用jadx打开发现很简单加密,就是把flag{xxxxxxxxx}中间的密文传进check函数,直接去so文件找jni发现关键check函数

image-20220707202353900

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
__int64 __fastcall sub_4700(__int64 *a1, __int64 a2, __int64 a3)
{
__int64 v3; // rbx
_DWORD *v4; // r14
__int64 v5; // rax
const char *v6; // rsi
int v8; // [rsp+4h] [rbp-34h] BYREF
int v9; // [rsp+8h] [rbp-30h] BYREF
int v10; // [rsp+Ch] [rbp-2Ch] BYREF
int v11; // [rsp+10h] [rbp-28h] BYREF
int v12; // [rsp+14h] [rbp-24h]
unsigned __int64 v13; // [rsp+18h] [rbp-20h]

v13 = __readfsqword(0x28u);
v3 = (*(__int64 (__fastcall **)(__int64 *, __int64, _QWORD))(*a1 + 1352))(a1, a3, 0LL);
if ( (unsigned int)sub_3D70(v3) == 32 )
{
v10 = 16;
v4 = malloc(0x80uLL);
if ( (unsigned int)sub_4330(v3, v4, &v10) )
{
v5 = *a1;
v6 = "Bad format";
}
else
{
v9 = *v4 ^ 0x39DEB332;
v11 = v4[1] ^ v9;
v12 = v4[2] ^ v11;
v8 = v4[3] ^ v12;
if ( sub_43F0((__int64)&v9) && (unsigned __int8)sub_44E0(&v11) && (unsigned __int8)sub_4630(&v8) )
{
v5 = *a1;
v6 = "right flag!!!";
}
else
{
v5 = *a1;
v6 = "sorry,wrong flag.";
}
}
}
else
{
v5 = *a1;
v6 = "length of input is not enough!!!";
}
return (*(__int64 (__fastcall **)(__int64 *, const char *))(v5 + 1336))(a1, v6);
}

程序的意思就是要输入一个32位的flag,然后每两个一组变成16进制,变成16位,4个4个一组,先进行异或,然后进入三个函数验证

第一个函数是sha1加密,4字节还知道一个字节

1
2
3
4
5
6
7
8
import hashlib
for i1 in range(0xff):
for i2 in range(0xff):
for i4 in range(0xff):
arr = [i1, i2, 0xe9,i4]
if(hashlib.sha1(bytes(arr)).hexdigest().lower() == "2e60865e94119223c4657eac98d744ee909e66b8"):
print(hex(i1),hex(i2),0xe9,hex(i4))
break

第二个函数刚开始没看出来,后面发现是sm4加密

image-20220707105839618

不难发现是sm4的cbc模式,那么需要找到key和iv,发现是0-0xf,直接写脚本

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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
#include <string.h>
#include <stdio.h>
#include <time.h>
/*--------------------------------------------------------------------------------------------------------------*/
#define SM4_ENCRYPT 1
#define SM4_DECRYPT 0
/*--------------------------------------------------------------------------------------------------------------*/
/**
* \brief SM4 context structure
*/
typedef struct
{
int mode; /*!< encrypt/decrypt */
unsigned long sk[32]; /*!< SM4 subkeys */
}
sm4_context;
/*--------------------------------------------------------------------------------------------------------------*/
/**
* \brief SM4 key schedule (128-bit, encryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_enc(sm4_context *ctx, unsigned char key[16]);
/*--------------------------------------------------------------------------------------------------------------*/
/**
* \brief SM4 key schedule (128-bit, decryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_dec(sm4_context *ctx, unsigned char key[16]);
/*--------------------------------------------------------------------------------------------------------------*/
/**
* \brief SM4-ECB block encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param input input block
* \param output output block
*/
void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
unsigned char *input,
unsigned char *output);
/*--------------------------------------------------------------------------------------------------------------*/
/**
* \brief SM4-CBC buffer encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
unsigned char iv[16],
unsigned char *input,
unsigned char *output);
/*--------------------------------------------------------------------------------------------------------------*/
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
/*--------------------------------------------------------------------------------------------------------------*/
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*--------------------------------------------------------------------------------------------------------------*/
/*
*rotate shift left marco definition
*
*/
#define SHL(x,n) (((x) & 0xFFFFFFFF) << n)
#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
/*--------------------------------------------------------------------------------------------------------------*/
/*
* Expanded SM4 S-boxes
/* Sbox table: 8bits input convert to 8 bits output*/
static const unsigned char SboxTable[16][16] =
{
{ 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 }
};
/*--------------------------------------------------------------------------------------------------------------*/
/* System parameter */
static const unsigned long FK[4] =
{ 0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc };
/*--------------------------------------------------------------------------------------------------------------*/
/* fixed parameter */
static const unsigned long CK[32] =
{
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
};
/*--------------------------------------------------------------------------------------------------------------*/
/*
* private function:
* look up in SboxTable and get the related value.
* args: [in] inch: 0x00~0xFF (8 bits unsigned value).
*/
static unsigned char sm4Sbox(unsigned char inch)
{
unsigned char *pTable = (unsigned char *)SboxTable;
unsigned char retVal = (unsigned char)(pTable[inch]);
return retVal;
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* private F(Lt) function:
* "T algorithm" == "L algorithm" + "t algorithm".
* args: [in] a: a is a 32 bits unsigned value;
* return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
*/
static unsigned long sm4Lt(unsigned long ka)
{
unsigned long bb = 0;
unsigned long c = 0;
unsigned char a[4];
unsigned char b[4];
PUT_ULONG_BE(ka, a, 0)
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
GET_ULONG_BE(bb, b, 0)
c = bb ^ (ROTL(bb, 2)) ^ (ROTL(bb, 10)) ^ (ROTL(bb, 18)) ^ (ROTL(bb, 24));
return c;
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* private F function:
* Calculating and getting encryption/decryption contents.
* args: [in] x0: original contents;
* args: [in] x1: original contents;
* args: [in] x2: original contents;
* args: [in] x3: original contents;
* args: [in] rk: encryption/decryption key;
* return the contents of encryption/decryption contents.
*/
static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
{
return (x0^sm4Lt(x1^x2^x3^rk));
}
/*--------------------------------------------------------------------------------------------------------------*/
/* private function:
* Calculating round encryption key.
* args: [in] a: a is a 32 bits unsigned value;
* return: sk[i]: i{0,1,2,3,...31}.
*/
static unsigned long sm4CalciRK(unsigned long ka)
{
unsigned long bb = 0;
unsigned long rk = 0;
unsigned char a[4];
unsigned char b[4];
PUT_ULONG_BE(ka, a, 0)
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
GET_ULONG_BE(bb, b, 0)
rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));
return rk;
}
/*--------------------------------------------------------------------------------------------------------------*/
static void sm4_setkey(unsigned long SK[32], unsigned char key[16])
{
unsigned long MK[4];
unsigned long k[36];
unsigned long i = 0;

GET_ULONG_BE(MK[0], key, 0);
GET_ULONG_BE(MK[1], key, 4);
GET_ULONG_BE(MK[2], key, 8);
GET_ULONG_BE(MK[3], key, 12);
k[0] = MK[0] ^ FK[0];
k[1] = MK[1] ^ FK[1];
k[2] = MK[2] ^ FK[2];
k[3] = MK[3] ^ FK[3];
for (; i<32; i++)
{
k[i + 4] = k[i] ^ (sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
SK[i] = k[i + 4];
}

}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* SM4 standard one round processing
*
*/
static void sm4_one_round(unsigned long sk[32],
unsigned char input[16],
unsigned char output[16])
{
unsigned long i = 0;
unsigned long ulbuf[36];

memset(ulbuf, 0, sizeof(ulbuf));
GET_ULONG_BE(ulbuf[0], input, 0)
GET_ULONG_BE(ulbuf[1], input, 4)
GET_ULONG_BE(ulbuf[2], input, 8)
GET_ULONG_BE(ulbuf[3], input, 12)
while (i<32)
{
ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i]);
i++;
}
PUT_ULONG_BE(ulbuf[35], output, 0);
PUT_ULONG_BE(ulbuf[34], output, 4);
PUT_ULONG_BE(ulbuf[33], output, 8);
PUT_ULONG_BE(ulbuf[32], output, 12);
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* SM4 key schedule (128-bit, encryption)
*/
void sm4_setkey_enc(sm4_context *ctx, unsigned char key[16])
{
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* SM4 key schedule (128-bit, decryption)
*/
void sm4_setkey_dec(sm4_context *ctx, unsigned char key[16])
{
int i;
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
for (i = 0; i < 16; i++)
{
SWAP(ctx->sk[i], ctx->sk[31 - i]);
}
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* SM4-ECB block encryption/decryption
*/
void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
unsigned char *input,
unsigned char *output)
{
while (length > 0)
{
sm4_one_round(ctx->sk, input, output);
input += 16;
output += 16;
length -= 16;
}
}
/*--------------------------------------------------------------------------------------------------------------*/
/*
* SM4-CBC buffer encryption/decryption
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
unsigned char iv[16],
unsigned char *input,
unsigned char *output)
{
int i;
unsigned char temp[16];

if (mode == SM4_ENCRYPT)
{
while (length > 0)
{
for (i = 0; i < 16; i++)
output[i] = (unsigned char)(input[i] ^ iv[i]);

sm4_one_round(ctx->sk, output, output);
memcpy(iv, output, 16);

input += 16;
output += 16;
length -= 16;
}
}
else /* SM4_DECRYPT */
{
while (length > 0)
{
memcpy(temp, input, 16);
sm4_one_round(ctx->sk, input, output);

for (i = 0; i < 16; i++)
output[i] = (unsigned char)(output[i] ^ iv[i]);

memcpy(iv, temp, 16);

input += 16;
output += 16;
length -= 16;
}
}
}
/*--------------------------------------------------------------------------------------------------------------*/
int main()
{
unsigned char key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
unsigned char input[16] = { 0xD4, 0xD9, 0x76, 0xED, 0x8C, 0xFD, 0x9E, 0x36, 0x75, 0xCF, 0x39, 0x20, 0x56, 0x3A, 0xE6, 0xBF };
unsigned char output[16];
unsigned char iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
sm4_context ctx;
unsigned long i;

/*
//encrypt testing
sm4_setkey_enc(&ctx,key);
sm4_crypt_ecb(&ctx,1,16,input,output);
for(i=0;i<16;i++)
printf("%02x ", output[i]);
printf("\n");
*/

//decrypt testing
sm4_setkey_dec(&ctx, key);
sm4_crypt_cbc(&ctx, 0, 16, iv, input, output);
for (i = 0; i<16; i++)
printf("%02x\n", output[i]);
printf("\n");
return 0;
}

第三个函数就是个base64直接搞

1
2
3
4
5
6
7
8
9
10
11
12
#输出数组
import base64
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
diy_base = 'abcdefghijklmnpoqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'
s = 'cpVVnW'
ss = ''
for i in range(len(s)-2):
ss += base[diy_base.find(s[i])]
ss += '=='
a = base64.b64decode(ss)
print(list(map(hex,a)))

然后再进行异或,转换两次小端序就行

1
2
3
4
5
6
7
8
9
10
11
12
13
v8 =  0x37efeb08
v11 = 0x8275e5d1
v12 = 0xff540b2d
v9 = 0x09e948b0
flag =[0] * 4
flag[0] = v9 ^ 0x39DEB332
flag[1] = v9 ^ v11
flag[2] = v11 ^v12
flag[3] = v12 ^ v8
print(hex(flag[0]))
print(hex(flag[1]))
print(hex(flag[2]))
print(hex(flag[3]))

creakme4

image-20220707204945097

还是直接看so文件

image-20220708200200022

findcript直接找到是blowfish加密,之前做过这个加密:

image-20220708200238598

然后下面发现还有个加密

image-20220708200306368

findcrypt并没有检测出,

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
__int64 __fastcall sub_142B8(__int64 a1, __int64 a2, __int64 a3)
{
int v5; // w23
int v6; // w0
int v7; // w3
int v8; // w4
int v9; // w5
int v10; // w6
void *v11; // x7
__int64 v12; // x21
__int64 v13; // x0
__int64 v14; // x19
__int64 v16; // [xsp+0h] [xbp-E0h] BYREF
__int64 v17[2]; // [xsp+8h] [xbp-D8h] BYREF
void *ptr; // [xsp+18h] [xbp-C8h]
char v19[8]; // [xsp+20h] [xbp-C0h] BYREF
char v20[96]; // [xsp+28h] [xbp-B8h] BYREF
char v21[8]; // [xsp+88h] [xbp-58h] BYREF
_QWORD v22[2]; // [xsp+90h] [xbp-50h] BYREF

v5 = 1945572552;
v22[1] = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v17[1] = 0LL;
ptr = 0LL;
v17[0] = 0LL;
v6 = strlen(a5);
sub_14FE0((int)v17, (int)a5, v6, v7, v8, v9, v10, v11);
v12 = (*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
sub_13FC8(v12, v21);
v16 = 0xE7CDAB8967452301LL;
sub_1054C(&v16, v20, 0LL);
sub_10C84(v22, v19, v20);
if ( (unsigned __int8)v19[0] == 228
&& (unsigned __int8)v19[1] == 234
&& (unsigned __int8)v19[2] == 196
&& (unsigned __int8)v19[3] == 129
&& (unsigned __int8)v19[4] == 185
&& (unsigned __int8)v19[5] == 254
&& v19[6] == 38
&& (unsigned __int8)v19[7] == 188 )
{
v13 = (*(__int64 (__fastcall **)(__int64, void *))(*(_QWORD *)a1 + 1336LL))(a1, &unk_3C090);
}
else
{
(*(void (__fastcall **)(__int64, __int64, __int64))(*(_QWORD *)a1 + 1360LL))(a1, a3, v12);
v13 = (*(__int64 (__fastcall **)(__int64, void *))(*(_QWORD *)a1 + 1336LL))(a1, &unk_3C050);
}
v14 = v13;
while ( v5 != 847613141 )
{
if ( (v17[0] & 1) != 0 )
v5 = 847613141;
else
v5 = -519487832;
if ( v5 == -519487832 )
return v14;
}
operator delete(ptr);
return v14;
}

image-20220708200509986

学了des加密后,发现这有8个s盒,应该是个des,并没有魔改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Cipher import Blowfish
key = b'\x12\x34\x56\x78\x9a\xbc\xde\xff'
enc_data = bytes([0x92, 0xB1, 0xC0, 0x8D, 0x7D, 0x4D, 0x02, 0XB6])
cipher = Blowfish.new(key, Blowfish.MODE_ECB)
dec = cipher.decrypt(enc_data)
for i in dec:
print("{:02x}".format(i), end='')
from Crypto.Cipher import DES
key = bytes([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7])
enc_data = bytes([0xE4, 0XEA, 0XC4, 0X81, 0xB9, 0xFE, 0x26, 0xBC])
cipher = DES.new(key, DES.MODE_ECB)
dec = cipher.decrypt(enc_data)
for i in dec:
print("{:02x}".format(i), end='')

得到flag

analgo

又是go语言,发现有一段brainfuck

直接在对比处下断点来查看输入后经过加密会怎么变化。

image-20220708092459410

image-20220708165947660

在比较处patch一下

1
2
3
4
5
6
输入:111111111111111111111111111111111111111111
输出:0F 5291D4135695D8175A99DC1B5E9DE01F62A1E42366A5E8276AA9EC2B6EADB0EF3271B4F33675B8F70F
输入:211111111111111111111111111111111111111111
输出:C2 5291D4135695D8175A99DC1B5E9DE01F62A1E42366A5E8276AA9EC2B6EADB0EF3271B4F33675B8F70F
输入:112111111111111111111111111111111111111111
输出:0F 7F 40D4135695D8175A99DC1B5E9DE01F62A1E42366A5E8276AA9EC2B6EADB0EF3271B4F33675B8F70F

很明显字节与字节之间并无明显关联,对程序进行单字节爆破处理,这是我第二次见这样的脚本,上次还是在hgame。。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import subprocess
import string

data = list('fl1111111111111111111111111111111111111111\n')#确定前两个字符从而递归推出下面字符
for i in range(2,0x2a):
bin = bytearray(open("analgo.exe","rb").read())
bin[0xb3045] = i
open("analgo.exe","wb").write(bin)#将之后的值写入文件
for j in string.printable:#爆破
data[i] = j
pipe = subprocess.Popen("./analgo.exe",bufsize=2,stdout=subprocess.PIPE,stdin=subprocess.PIPE)#创建管道
pipe.stdin.write(bytes("".join(data).encode("utf-8"))) #将该字符写入文件进行验证
if b'right!\n' == pipe.stdout.read():#如果子进程输出right
break
print("".join(data))#输出结果

flag{568a3cdd-77e1-4c42-9fee-127e27a5744e}

1
2
3
4
5
6
7
8
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)

args:表示要执行的命令。必须是一个字符串,字符串参数列表。
stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常。
encoding: 如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令

rota

这题还是比较简单的

image-20220711181535411

显然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
if ( v13 )
{
for ( i = 0i64; i < 64; ++i )
*((_BYTE *)&unk_7FF75F6B6040 + i) = (*((_BYTE *)&unk_7FF75F6B6040 + i) + 1) & 0x3F;
}
else
{
si128 = _mm_load_si128((const __m128i *)&xmmword_7FF75F6B4340);
v15 = _mm_load_si128((const __m128i *)&xmmword_7FF75F6B4350);
v16 = 0i64;
v17 = _mm_cvtsi32_si128(6u);
do
{
v18 = _mm_add_epi32(_mm_cvtepu8_epi32(*(_DWORD *)((char *)&unk_7FF75F6B6040 + v16)), si128);
v19 = _mm_and_si128(
_mm_shuffle_epi32(
_mm_shufflehi_epi16(
_mm_shufflelo_epi16(
_mm_sub_epi32(
v18,
_mm_sll_epi32(
_mm_sra_epi32(_mm_add_epi32(_mm_and_si128(_mm_cmpgt_epi32((__m128i)0i64, v18), v15), v18), v17),
v17)),
216),
216),
216),
(__m128i)xmmword_7FF75F6B4360);
*(_DWORD *)((char *)&unk_7FF75F6B6040 + v16) = _mm_cvtsi128_si32(_mm_packus_epi16(v19, v19));
v20 = _mm_add_epi32(_mm_cvtepu8_epi32(*(_DWORD *)((char *)&unk_7FF75F6B6044 + v16)), si128);
v21 = _mm_and_si128(
_mm_shuffle_epi32(
_mm_shufflehi_epi16(
_mm_shufflelo_epi16(
_mm_sub_epi32(
v20,
_mm_sll_epi32(
_mm_sra_epi32(_mm_add_epi32(_mm_and_si128(_mm_cmpgt_epi32((__m128i)0i64, v20), v15), v20), v17),
v17)),
216),
216),
216),
(__m128i)xmmword_7FF75F6B4360);
*(_DWORD *)((char *)&unk_7FF75F6B6044 + v16) = _mm_cvtsi128_si32(_mm_packus_epi16(v21, v21));
v16 += 8i64;
}
while ( v16 < 64 );
}
sub_7FF75F6B10E0((__int64)v24);
sub_7FF75F6B1E10(v24, (__int64)v32, (__int64)encode2);

下面这其实都没啥,最主要的是sub_7FF75F6B1E10函数v32是传进来的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
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
char __fastcall sub_7FF75F6B1E10(_BYTE *a1, __int64 a2, __int64 a3)
{
char v3; // bl
_BYTE *v4; // rdi
char v5; // r9
char result; // al
__int64 v7; // rbp
__int64 v9; // rsi
int v10; // edx
char v11; // r8
__int64 v12; // rdx
char v13; // bl
__int64 v14; // rcx
int v15; // edx
char v16; // r8
__int64 v17; // rdx
char v18; // bl
__int64 v19; // rcx
int v20; // edx
char v21; // r8
__int64 v22; // rdx
char v23; // bl
__int64 v24; // rcx
int v25; // edx
char v26; // r8
__int64 v27; // rdx
char v28; // bl
__int64 v29; // rcx
int v30; // edx
char v31; // r8
__int64 v32; // rdx
__int64 v33; // rcx

v3 = a1[192];
v4 = (_BYTE *)(a3 + 1);
v5 = a1[193];
result = a1[194];
v7 = a2 - a3;
v9 = 9i64;
do
{
v10 = 0;
while ( (unsigned __int8)v4[v7 - 1] != aXiizduaoglak6j[v10] )
{
if ( ++v10 >= 64 )
{
LOBYTE(v10) = 0;
break;
}
}
v11 = v5;
v12 = (v5 + a1[(v3 + (_BYTE)v10) & 0x3F]) & 0x3F;
v13 = (v3 + 1) & 0x3F;
v14 = (unsigned __int8)a1[((result + a1[v12 + 64]) & 0x3F) + 128];
a1[192] = v13;
*(v4 - 1) = aXiizduaoglak6j[v14];
if ( !v13 )
{
v5 = (v5 + 1) & 0x3F;
a1[193] = v5;
if ( ((v11 + 1) & 0x3F) == 0 )
{
result = (result + 1) & 0x3F;
a1[194] = result;
}
}
v15 = 0;
while ( (unsigned __int8)v4[v7] != aXiizduaoglak6j[v15] )
{
if ( ++v15 >= 64 )
{
LOBYTE(v15) = 0;
break;
}
}
v16 = v5;
v17 = (v5 + a1[(v13 + (_BYTE)v15) & 0x3F]) & 0x3F;
v18 = (v13 + 1) & 0x3F;
v19 = (unsigned __int8)a1[((result + a1[v17 + 64]) & 0x3F) + 128];
a1[192] = v18;
*v4 = aXiizduaoglak6j[v19];
if ( !v18 )
{
v5 = (v5 + 1) & 0x3F;
a1[193] = v5;
if ( ((v16 + 1) & 0x3F) == 0 )
{
result = (result + 1) & 0x3F;
a1[194] = result;
}
}
v20 = 0;
while ( (unsigned __int8)v4[v7 + 1] != aXiizduaoglak6j[v20] )
{
if ( ++v20 >= 64 )
{
LOBYTE(v20) = 0;
break;
}
}
v21 = v5;
v22 = (v5 + a1[(v18 + (_BYTE)v20) & 0x3F]) & 0x3F;
v23 = (v18 + 1) & 0x3F;
v24 = (unsigned __int8)a1[((result + a1[v22 + 64]) & 0x3F) + 128];
a1[192] = v23;
v4[1] = aXiizduaoglak6j[v24];
if ( !v23 )
{
v5 = (v5 + 1) & 0x3F;
a1[193] = v5;
if ( ((v21 + 1) & 0x3F) == 0 )
{
result = (result + 1) & 0x3F;
a1[194] = result;
}
}
v25 = 0;
while ( (unsigned __int8)v4[v7 + 2] != aXiizduaoglak6j[v25] )
{
if ( ++v25 >= 64 )
{
LOBYTE(v25) = 0;
break;
}
}
v26 = v5;
v27 = (v5 + a1[(v23 + (_BYTE)v25) & 0x3F]) & 0x3F;
v28 = (v23 + 1) & 0x3F;
v29 = (unsigned __int8)a1[((result + a1[v27 + 64]) & 0x3F) + 128];
a1[192] = v28;
v4[2] = aXiizduaoglak6j[v29];
if ( !v28 )
{
v5 = (v5 + 1) & 0x3F;
a1[193] = v5;
if ( ((v26 + 1) & 0x3F) == 0 )
{
result = (result + 1) & 0x3F;
a1[194] = result;
}
}
v30 = 0;
while ( (unsigned __int8)v4[v7 + 3] != aXiizduaoglak6j[v30] )
{
if ( ++v30 >= 64 )
{
LOBYTE(v30) = 0;
break;
}
}
v31 = v5;
v32 = (v5 + a1[(v28 + (_BYTE)v30) & 0x3F]) & 0x3F;
v3 = (v28 + 1) & 0x3F;
v33 = (unsigned __int8)a1[((result + a1[v32 + 64]) & 0x3F) + 128];
a1[192] = v3;
v4[3] = aXiizduaoglak6j[v33];
if ( !v3 )
{
v5 = (v5 + 1) & 0x3F;
a1[193] = v5;
if ( ((v31 + 1) & 0x3F) == 0 )
{
result = (result + 1) & 0x3F;
a1[194] = result;
}
}
v4 += 5;
--v9;
}
while ( v9 );
return result;
}

5个地方结构相似,发现其实只用看懂一个就行,原数据在v4,我们可以直接爆破,然后直接对比就行,其实不难。每个结构其实是对一个字符进行的加密,那么每一次do while就是加密5个,但我们可以直接单个爆破。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import base64
cmp = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm"
base_change = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb"
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
a1 = [0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07, 0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E, 0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18, 0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14]
flag1 = ''
flag = ""
for i in range(45):
for j in base_change:
x = base_change.find(j)
v17 = a1[(i + x) & 0x3f] & 0x3f
v14 = a1[(a1[v17 + 64] ) + 128]
if base_change[v14] == cmp[i]:
flag1 += j

print(flag1)
for i in range(len(flag1)-1):
flag += base[base_change.find(flag1[i])]
print(base64.b64decode(flag))

gocode

这个题字节码逆向,还是go的,不过这个go比之前做的友善多了

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
310
311
312
313
314
315
316
317
318
319
void __cdecl main_main()
{
unsigned __int64 v0; // rdi
__int64 count; // rax
unsigned __int64 v2; // rcx
__int64 v3; // rdx
unsigned __int64 v4; // rbx
unsigned __int64 opcode; // rsi
unsigned __int64 v6; // rsi
unsigned __int64 v7; // r8
unsigned __int64 v8; // rsi
unsigned __int64 i; // rsi
_QWORD *v10; // rax
__int64 v11; // rbx
__int64 v12; // rsi
unsigned __int64 v13; // rdi
__int64 v14; // rcx
unsigned __int64 v15; // rsi
unsigned __int64 v16; // r8
const char *v17; // rdx
unsigned __int64 v18; // rsi
unsigned __int64 v19; // r8
unsigned __int64 v20; // rsi
unsigned __int64 v21; // r8
unsigned __int64 v22; // rsi
unsigned __int64 v23; // r8
unsigned __int64 v24; // r8
unsigned __int64 v25; // rsi
__int64 v26; // rsi
unsigned __int64 v27; // rdi
unsigned __int64 v28; // rsi
__int64 v29; // rsi
void **v30; // [rsp+0h] [rbp-CD0h]
__int64 v31; // [rsp+8h] [rbp-CC8h]
_QWORD *v32; // [rsp+20h] [rbp-CB0h]
__int128 v33; // [rsp+28h] [rbp-CA8h]
__int64 v34; // [rsp+38h] [rbp-C98h]
__int64 v35; // [rsp+40h] [rbp-C90h]
_QWORD *v36; // [rsp+50h] [rbp-C80h]
unsigned __int64 v37; // [rsp+58h] [rbp-C78h]
__int64 v38; // [rsp+68h] [rbp-C68h]
__int64 v39; // [rsp+70h] [rbp-C60h]
unsigned __int64 v40; // [rsp+78h] [rbp-C58h]
unsigned __int64 v41; // [rsp+80h] [rbp-C50h] BYREF
__int128 v42[2]; // [rsp+88h] [rbp-C48h] BYREF
__int64 v43[374]; // [rsp+A8h] [rbp-C28h] BYREF
__int64 v44; // [rsp+C58h] [rbp-78h] BYREF
__int64 v45; // [rsp+C60h] [rbp-70h]
_QWORD v46[2]; // [rsp+C68h] [rbp-68h] BYREF
_QWORD v47[2]; // [rsp+C78h] [rbp-58h] BYREF
_QWORD v48[2]; // [rsp+C88h] [rbp-48h] BYREF
_QWORD v49[2]; // [rsp+C98h] [rbp-38h] BYREF
_QWORD v50[2]; // [rsp+CA8h] [rbp-28h] BYREF
_QWORD v51[2]; // [rsp+CB8h] [rbp-18h] BYREF

while ( (unsigned __int64)&v41 <= *(_QWORD *)(*(_QWORD *)NtCurrentTeb()->NtTib.ArbitraryUserPointer + 16LL) )
runtime_morestack_noctxt();
qmemcpy(v43, "\n", sizeof(v43));
v0 = (unsigned __int64)&v44;
memset(v42, 0, sizeof(v42));
count = 0LL;
v2 = 0LL;
v3 = 0LL;
v4 = 0LL;
while ( 1 )
{
if ( (unsigned __int64)count >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v37 = v2;
v44 = v3;
v38 = count;
opcode = v43[count];
if ( opcode <= 0xC )
break;
if ( opcode > 0xE )
{
switch ( opcode )
{
case 0xFuLL:
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v22 = v43[count + 1];
if ( v22 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v23 = v43[count + 2];
if ( v23 >= 4 )
goto LABEL_97;
v24 = *((_QWORD *)v42 + v23);
if ( !v24 )
{
v31 = runtime_panicdivide(v30);
LABEL_97:
runtime_panicIndexU((__int64)v30, v31);
}
v0 = v3;
*((_QWORD *)v42 + v22) /= v24;
count += 3LL;
break;
case 0xAAuLL:
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v25 = v43[count + 1];
if ( v25 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v26 = *((_QWORD *)v42 + v25);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v27 = v43[count + 2];
if ( v27 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v27);
if ( v0 != v26 )
{
v47[0] = &unk_D62740;
v47[1] = &off_DA0B58;
fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v47, 1LL, 1LL, v33, *((__int64 *)&v33 + 1), v34);
v31 = os_Exit(0LL);
count = v38;
v2 = v37;
v3 = v44;
}
count += 3LL;
break;
case 0xBBuLL:
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v28 = v43[count + 2];
if ( v28 >= v2 )
runtime_panicIndexU((__int64)v30, v31);
v29 = *(_QWORD *)(v3 + 8 * v28);
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v0 = v43[count + 1];
if ( v0 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
*((_QWORD *)v42 + v0) = v29;
count += 3LL;
break;
}
}
else if ( opcode == 13 )
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v18 = v43[count + 1];
if ( v18 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v19 = v43[count + 2];
if ( v19 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v18) - *((_QWORD *)v42 + v19);
*((_QWORD *)v42 + v18) = v0;
count += 3LL;
}
else
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v20 = v43[count + 1];
if ( v20 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v21 = v43[count + 2];
if ( v21 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v21) * *((_QWORD *)v42 + v20);
*((_QWORD *)v42 + v20) = v0;
count += 3LL;
}
LABEL_12:
if ( count >= 374 )
{
v46[0] = &unk_D62740;
v46[1] = &off_DA0B78;
fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v46, 1LL, 1LL, v33, *((__int64 *)&v33 + 1), v34);
return;
}
}
if ( opcode <= 2 )
{
if ( opcode == 1 )
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v6 = v43[count + 1];
if ( v6 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v7 = v43[count + 2];
if ( v7 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v7) ^ *((_QWORD *)v42 + v6);
*((_QWORD *)v42 + v6) = v0;
count += 3LL;
}
else if ( opcode == 2 )
{
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v0 = v43[count + 2];
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v8 = v43[count + 1];
if ( v8 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
*((_QWORD *)v42 + v8) = v0;
count += 3LL;
}
goto LABEL_12;
}
if ( opcode != 10 )
{
if ( opcode == 11 )
{
for ( i = 0LL; ; i = v41 )
{
v0 = qword_E23C38;
if ( (__int64)i >= qword_E23C38 )
break;
if ( i + 2 > qword_E23C38 )
runtime_panicSliceAlen((__int64)v30, v31);
if ( i > i + 2 )
runtime_panicSliceB((__int64)v30, v31);
v41 = i + 2;
v45 = v3;
v40 = v4;
v39 = v2;
v34 = strconv_ParseUint(qword_E23C30 + i, 2LL, 16LL, 32LL, (__int64)v32, v33);
v10 = v32;
if ( (_QWORD)v33 )
{
v48[0] = &unk_D62740;
v48[1] = &off_DA0B68;
fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v48, 1LL, 1LL, v33, *((__int64 *)&v33 + 1), v34);
return;
}
v11 = v39;
v12 = v39 + 1;
v13 = v40;
if ( v40 < v39 + 1 )
{
v36 = v32;
runtime_growslice((__int64)"\b", v45, v39, v40, v39 + 1, 0LL, *((__int64 *)&v33 + 1), v34);
v14 = v33;
v13 = v34;
v12 = *((_QWORD *)&v33 + 1) + 1LL;
v10 = v36;
v11 = v39;
}
else
{
v14 = v45;
}
*(_QWORD *)(v14 + 8 * v11) = v10;
count = v38;
v4 = v13;
v3 = v14;
v2 = v12;
}
++count;
}
else if ( opcode == 12 )
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v15 = v43[count + 1];
if ( v15 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v16 = v43[count + 2];
if ( v16 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v16) + *((_QWORD *)v42 + v15);
*((_QWORD *)v42 + v15) = v0;
count += 3LL;
}
goto LABEL_12;
}
v51[0] = &unk_D62740;
v51[1] = &off_DA0B48;
v35 = fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v51, 1LL, 1LL, v33, *((__int64 *)&v33 + 1), v34);
v50[0] = "\b";
v50[1] = &qword_E23C30;
v30 = &off_DA21F8;
v31 = qword_E23420;
v32 = v50;
*(_QWORD *)&v33 = 1LL;
*((_QWORD *)&v33 + 1) = 1LL;
fmt_Fscanf(v0, (__int64)v50, "%37s", &qword_E23C30);
if ( v35 )
return;
if ( qword_E23C38 == 37 && *(_DWORD *)qword_E23C30 == '{LCP' && *(_BYTE *)(qword_E23C30 + 36) == 125 )// 检测长度和PCL{}
{
qword_E23C38 = 32LL;
if ( dword_E66C60 )
{
v0 = (unsigned __int64)&qword_E23C30;
runtime_gcWriteBarrierBX(&qword_E23C30, v50, v17);
}
else
{
qword_E23C30 += 4LL;
}
count = v38 + 1;
v2 = v37;
v3 = v44;
goto LABEL_12;
}
v49[0] = &unk_D62740;
v49[1] = &off_DA0B58;
fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v49, 1LL, 1LL, 1LL, 1LL, v34);
}

指令集都在v43里,我们可以dump出来的,发现也就是几种指令,三个一组。前两个0xa和0xb是为了验证输入格式是否正确

1
[0x0A, 0x0B, 0xBB, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xBB, 0x02, 0x02, 0xBB, 0x03, 0x03, 0x0C, 0x01, 0x02, 0x02, 0x02, 0x11B, 0xAA, 0x01, 0x02, 0xBB, 0x01, 0x01, 0xBB, 0x02, 0x02, 0x0C, 0x00, 0x01, 0x0E, 0x00, 0x02, 0x0D, 0x00, 0x03, 0x02, 0x02, 0x7901, 0xAA, 0x00, 0x02, 0xBB, 0x02, 0x02, 0x02, 0x00, 0x63, 0x01, 0x02, 0x00, 0xBB, 0x00, 0x00, 0x0E, 0x00, 0x02, 0x0D, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x02, 0x01, 0x1FF6, 0xAA, 0x00, 0x01, 0xBB, 0x01, 0x01, 0xBB, 0x00, 0x00, 0xBB, 0x02, 0x02, 0x0C, 0x01, 0x00, 0x0C, 0x01, 0x02, 0x0C, 0x01, 0x03, 0x02, 0x00, 0x21E, 0xAA, 0x01, 0x00, 0xBB, 0x01, 0x01, 0xBB, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x0D, 0x00, 0x01, 0x0C, 0x00, 0x02, 0x02, 0x03, 0x3331, 0xAA, 0x00, 0x03, 0xBB, 0x00, 0x04, 0xBB, 0x01, 0x05, 0xBB, 0x02, 0x06, 0x02, 0x03, 0x63, 0x0C, 0x00, 0x03, 0x02, 0x03, 0x68, 0x01, 0x00, 0x03, 0x02, 0x03, 0x152, 0xAA, 0x00, 0x03, 0x02, 0x03, 0x33, 0x0D, 0x01, 0x03, 0x02, 0x03, 0x63, 0x0E, 0x01, 0x03, 0x02, 0x00, 0x441, 0xAA, 0x00, 0x01, 0x02, 0x03, 0x63, 0x01, 0x02, 0x03, 0x02, 0x03, 0x6B, 0x0C, 0x02, 0x03, 0x02, 0x01, 0x10E, 0xAA, 0x02, 0x01, 0x02, 0x01, 0x9E, 0xBB, 0x00, 0x07, 0xAA, 0x00, 0x01, 0xBB, 0x00, 0x08, 0xBB, 0x01, 0x09, 0xBB, 0x02, 0x0A, 0xBB, 0x03, 0x0B, 0x0E, 0x00, 0x03, 0x02, 0x03, 0x36CE, 0xAA, 0x00, 0x03, 0xBB, 0x00, 0x08, 0xBB, 0x03, 0x0B, 0x0C, 0x00, 0x01, 0x0E, 0x00, 0x02, 0x0D, 0x00, 0x03, 0x02, 0x02, 0x682D, 0xAA, 0x00, 0x02, 0xBB, 0x02, 0x0A, 0x02, 0x00, 0x63, 0x01, 0x02, 0x00, 0xBB, 0x00, 0x08, 0x0E, 0x00, 0x02, 0x0D, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x02, 0x01, 0x15, 0xAA, 0x00, 0x01, 0xBB, 0x01, 0x09, 0xBB, 0x00, 0x08, 0xBB, 0x02, 0x0A, 0x0C, 0x01, 0x00, 0x0C, 0x01, 0x02, 0x0C, 0x01, 0x03, 0x02, 0x00, 0x1AE, 0xAA, 0x01, 0x00, 0xBB, 0x01, 0x09, 0xBB, 0x00, 0x08, 0x0E, 0x00, 0x03, 0x0D, 0x00, 0x01, 0x0C, 0x00, 0x02, 0x02, 0x03, 0x3709, 0xAA, 0x00, 0x03, 0xBB, 0x00, 0x0C, 0xBB, 0x01, 0x0D, 0xBB, 0x02, 0x0E, 0x02, 0x03, 0x63, 0x0C, 0x00, 0x03, 0x02, 0x03, 0x68, 0x01, 0x00, 0x03, 0x02, 0x03, 0xFA, 0xAA, 0x00, 0x03, 0x02, 0x03, 0x1E, 0x0D, 0x01, 0x03, 0x02, 0x03, 0x63, 0x0E, 0x01, 0x03, 0x02, 0x00, 0x18C, 0xAA, 0x00, 0x01, 0x02, 0x03, 0x63, 0x01, 0x02, 0x03, 0x02, 0x03, 0x6B, 0x0C, 0x02, 0x03, 0x02, 0x01, 0x83, 0xAA, 0x02, 0x01, 0x02, 0x01, 0x47, 0xBB, 0x00, 0x0F, 0xAA]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
case 0xFuLL:
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v22 = v43[count + 1];
if ( v22 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v23 = v43[count + 2];
if ( v23 >= 4 )
goto LABEL_97;
v24 = *((_QWORD *)v42 + v23);
if ( !v24 )
{
v31 = runtime_panicdivide(v30);
LABEL_97:
runtime_panicIndexU((__int64)v30, v31);
}
v0 = v3;
*((_QWORD *)v42 + v22) /= v24;
count += 3LL;
break;

如果opcode == 0xf,那么后两位操作数进行一个相除

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
case 0xAAuLL:
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v25 = v43[count + 1];
if ( v25 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v26 = *((_QWORD *)v42 + v25);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v27 = v43[count + 2];
if ( v27 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v27);
if ( v0 != v26 )
{
v47[0] = &unk_D62740;
v47[1] = &off_DA0B58;
fmt_Fprintln((__int64)&off_DA2218, qword_E23428, (__int64)v47, 1LL, 1LL, v33, *((__int64 *)&v33 + 1), v34);
v31 = os_Exit(0LL);
count = v38;
v2 = v37;
v3 = v44;
}
count += 3LL;
break;

如果opcode == 0xAA,就退出程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case 0xBBuLL:
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v28 = v43[count + 2];
if ( v28 >= v2 )
runtime_panicIndexU((__int64)v30, v31);
v29 = *(_QWORD *)(v3 + 8 * v28);
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v0 = v43[count + 1];
if ( v0 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
*((_QWORD *)v42 + v0) = v29;
count += 3LL;
break;

如果opcode == 0xbb,是一个赋值reg[0] = input[0]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
else if ( opcode == 13 )
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v18 = v43[count + 1];
if ( v18 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v19 = v43[count + 2];
if ( v19 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v18) - *((_QWORD *)v42 + v19);
*((_QWORD *)v42 + v18) = v0;
count += 3LL;
}

opcode == 13,是一个减法,第一个操作数减去第二个操作数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if ( opcode <= 2 )
{
if ( opcode == 1 )
{
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v6 = v43[count + 1];
if ( v6 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v7 = v43[count + 2];
if ( v7 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
v0 = *((_QWORD *)v42 + v7) ^ *((_QWORD *)v42 + v6);
*((_QWORD *)v42 + v6) = v0;
count += 3LL;
}

如果opcode == 1,那么是个异或

1
2
3
4
5
6
7
8
9
10
11
12
13
else if ( opcode == 2 )
{
if ( (unsigned __int64)(count + 2) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v0 = v43[count + 2];
if ( (unsigned __int64)(count + 1) >= 0x176 )
runtime_panicIndex((__int64)v30, v31);
v8 = v43[count + 1];
if ( v8 >= 4 )
runtime_panicIndexU((__int64)v30, v31);
*((_QWORD *)v42 + v8) = v0;
count += 3LL;
}

如果opcode == 2,是个赋值等于第二个操作数

用脚本恢复一下,发现可以用z3解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
opcode = [187, 0, 0, 187, 1, 1, 187, 2, 2, 187, 3, 3, 12, 1, 2, 2, 2, 283, 170, 1, 2, 187, 1, 1, 187, 2, 2, 12, 0, 1, 14, 0, 2, 13, 0, 3, 2, 2, 30977, 170, 0, 2, 187, 2, 2, 2, 0, 99, 1, 2, 0, 187, 0, 0, 14, 0, 2, 13, 0, 1, 12, 0, 3, 2, 1, 8182, 170, 0, 1, 187, 1, 1, 187, 0, 0, 187, 2, 2, 12, 1, 0, 12, 1, 2, 12, 1, 3, 2, 0, 542, 170, 1, 0, 187, 1, 1, 187, 0, 0, 14, 0, 3, 13, 0, 1, 12, 0, 2, 2, 3, 13105, 170, 0, 3, 187, 0, 4, 187, 1, 5, 187, 2, 6, 2, 3, 99, 12, 0, 3, 2, 3, 104, 1, 0, 3, 2, 3, 338, 170, 0, 3, 2, 3, 51, 13, 1, 3, 2, 3, 99, 14, 1, 3, 2, 0, 1089, 170, 0, 1, 2, 3, 99, 1, 2, 3, 2, 3, 107, 12, 2, 3, 2, 1, 270, 170, 2, 1, 2, 1, 158, 187, 0, 7, 170, 0, 1, 187, 0, 8, 187, 1, 9, 187, 2, 10, 187, 3, 11, 14, 0, 3, 2, 3, 14030, 170, 0, 3, 187, 0, 8, 187, 3, 11, 12, 0, 1, 14, 0, 2, 13, 0, 3, 2, 2, 26669, 170, 0, 2, 187, 2, 10, 2, 0, 99, 1, 2, 0, 187, 0, 8, 14, 0, 2, 13, 0, 1, 12, 0, 3, 2, 1, 21, 170, 0, 1, 187, 1, 9, 187, 0, 8, 187, 2, 10, 12, 1, 0, 12, 1, 2, 12, 1, 3, 2, 0, 430, 170, 1, 0, 187, 1, 9, 187, 0, 8, 14, 0, 3, 13, 0, 1, 12, 0, 2, 2, 3, 14089, 170, 0, 3, 187, 0, 12, 187, 1, 13, 187, 2, 14, 2, 3, 99, 12, 0, 3, 2, 3, 104, 1, 0, 3, 2, 3, 250, 170, 0, 3, 2, 3, 30, 13, 1, 3, 2, 3, 99, 14, 1, 3, 2, 0, 396, 170, 0, 1, 2, 3, 99, 1, 2, 3, 2, 3, 107, 12, 2, 3, 2, 1, 131, 170, 2, 1, 2, 1, 71, 187, 0, 15, 170, 0, 1]
for i in range(0, len(opcode), 3):
op = opcode[i]
num1 = opcode[i + 1]
num2 = opcode[i + 2]
if op == 0xbb:
print(f"buf[{num1}] = input[{num2}]")
elif op == 0xaa:
print(f"if buf[{num1}] != buf[{num2}] goto exit")
elif op == 0xf:
print(f"buf[{num1}] /= buf[{num2}]")
elif op == 0xd:
print(f"buf[{num1}] -= buf[{num2}]")
elif op == 0xe:
print(f"buf[{num1}] *= buf[{num2}]")
elif op == 0x1:
print(f"buf[{num1}] ^= buf[{num2}]")
elif op == 0x2:
print(f"buf[{num1}] = {num2}")
elif op == 0xc:
print(f"buf[{num1}] += buf[{num2}]")
else:
print("gg")
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
buf[0] = input[0]
buf[1] = input[1]
buf[2] = input[2]
buf[3] = input[3]
buf[1] += buf[2]
buf[2] = 283
if buf[1] != buf[2] goto exit
buf[1] = input[1]
buf[2] = input[2]
buf[0] += buf[1]
buf[0] *= buf[2]
buf[0] -= buf[3]
buf[2] = 30977
if buf[0] != buf[2] goto exit
buf[2] = input[2]
buf[0] = 99
buf[2] ^= buf[0]
buf[0] = input[0]
buf[0] *= buf[2]
buf[0] -= buf[1]
buf[0] += buf[3]
buf[1] = 8182
if buf[0] != buf[1] goto exit
buf[1] = input[1]
buf[0] = input[0]
buf[2] = input[2]
buf[1] += buf[0]
buf[1] += buf[2]
buf[1] += buf[3]
buf[0] = 542
if buf[1] != buf[0] goto exit
buf[1] = input[1]
buf[0] = input[0]
buf[0] *= buf[3]
buf[0] -= buf[1]
buf[0] += buf[2]
buf[3] = 13105
if buf[0] != buf[3] goto exit
buf[0] = input[4]
buf[1] = input[5]
buf[2] = input[6]
buf[3] = 99
buf[0] += buf[3]
buf[3] = 104
buf[0] ^= buf[3]
buf[3] = 338
if buf[0] != buf[3] goto exit
buf[3] = 51
buf[1] -= buf[3]
buf[3] = 99
buf[1] *= buf[3]
buf[0] = 1089
if buf[0] != buf[1] goto exit
buf[3] = 99
buf[2] ^= buf[3]
buf[3] = 107
buf[2] += buf[3]
buf[1] = 270
if buf[2] != buf[1] goto exit
buf[1] = 158
buf[0] = input[7]
if buf[0] != buf[1] goto exit
buf[0] = input[8]
buf[1] = input[9]
buf[2] = input[10]
buf[3] = input[11]
buf[0] *= buf[3]
buf[3] = 14030
if buf[0] != buf[3] goto exit
buf[0] = input[8]
buf[3] = input[11]
buf[0] += buf[1]
buf[0] *= buf[2]
buf[0] -= buf[3]
buf[2] = 26669
if buf[0] != buf[2] goto exit
buf[2] = input[10]
buf[0] = 99
buf[2] ^= buf[0]
buf[0] = input[8]
buf[0] *= buf[2]
buf[0] -= buf[1]
buf[0] += buf[3]
buf[1] = 21
if buf[0] != buf[1] goto exit
buf[1] = input[9]
buf[0] = input[8]
buf[2] = input[10]
buf[1] += buf[0]
buf[1] += buf[2]
buf[1] += buf[3]
buf[0] = 430
if buf[1] != buf[0] goto exit
buf[1] = input[9]
buf[0] = input[8]
buf[0] *= buf[3]
buf[0] -= buf[1]
buf[0] += buf[2]
buf[3] = 14089
if buf[0] != buf[3] goto exit
buf[0] = input[12]
buf[1] = input[13]
buf[2] = input[14]
buf[3] = 99
buf[0] += buf[3]
buf[3] = 104
buf[0] ^= buf[3]
buf[3] = 250
if buf[0] != buf[3] goto exit
buf[3] = 30
buf[1] -= buf[3]
buf[3] = 99
buf[1] *= buf[3]
buf[0] = 396
if buf[0] != buf[1] goto exit
buf[3] = 99
buf[2] ^= buf[3]
buf[3] = 107
buf[2] += buf[3]
buf[1] = 131
if buf[2] != buf[1] goto exit
buf[1] = 71
buf[0] = input[15]
if buf[0] != buf[1] goto exit
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
from z3 import*
flag = [BitVec("x%d" % i ,16) for i in range(16)]
s = Solver()

s.add(flag[1] + flag[2] == 283)
s.add((((flag[0] + flag[1]) * flag[2]) - flag[3]) == 30977)
s.add((flag[0] * (flag[2] ^ 99)) - flag[1] + flag[3] == 8182)
s.add((flag[0] + flag[1] + flag[2] + flag[3]) == 542)
s.add(((flag[0] * flag[3]) - flag[1] + flag[2]) == 13105)

s.add((flag[4] + 99) ^ 104 == 338)
s.add((flag[5] - 51) * 99 == 1089)
s.add((flag[6] ^ 99) + 107 == 270)
s.add(flag[7] == 158)
s.add(flag[8] * flag[11] == 14030)
s.add((flag[8] + flag[9]) * flag[10] - flag[11] == 26669)
s.add(flag[8] * (flag[10] ^ 99) - flag[9] + flag[11] == 21)
s.add((flag[8] + flag[9] + flag[10] + flag[11]) == 430)
s.add(flag[8] * flag[11] - flag[9] + flag[10] == 14089)
s.add((flag[12] + 99) ^ 104 == 250)
s.add((flag[13] - 30) * 99 == 396)
s.add((flag[14] ^ 99) + 107 == 131)
s.add(flag[15] == 71)

if s.check() == sat:
model = s.model()
print(model)
else:
print("unsat")

得到的结果取0xff然后拼接就对了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[x12 = 47,
x9 = 40,
x4 = 215,
x6 = 192,
x8 = 230,
x2 = 32847,
x1 = 32972,
x10 = 99,
x11 = 61,
x0 = 189,
x3 = 70,
x15 = 71,
x13 = 34,
x7 = 158,
x5 = 62]

PCL{bdcc4f46d73ec09ee628633d2f227b47}

dsctf

catchme

这题太折磨了,其实逻辑巨简单,就是一个aes和base64,,但其中的密文和密钥全部要先进行异或。当时看密文感觉不对,就想着动调,但里面反调试太多了,现在看着其实交叉引用就能定位到,只是简单的xor。

jadx看到关键函数是check函数,直接在so文件搜索不到,应该是JNI OnLoad里使用RegisterNatives注册check sub B2A4

jni里,本来以为 sub_AEC8是关键函数,但后面那个aes数据解密出来是:Congratulations,but tryagain?

image-20220718114127868

通过交叉引用发现,key和对比数据都进行了异或

image-20220718114211385

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
import base64
key = "\x24<=76!5&?72*rrrrS"
flag = ""
for i in range(len(key)):
flag += chr(ord(key[i]) ^ 0x53)
print(flag)
data = ""
data_encode = [0x4F, 0x1C, 0x36, 0x49, 0x09, 0x3A, 0x3F, 0x07, 0x4D, 0x3D, 0x22, 0x39, 0x00, 0x0A, 0x22, 0x25, 0x06, 0x09, 0x01, 0x20, 0x4A, 0x1B, 0x51, 0x51, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
for i in range(len(data_encode)):
data += chr(data_encode[i] ^ 0x6c)
print(data)
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
diy_base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()+/"
s = """#pZ%eVSk!QNUlfNIjemL&w=="""
ss = ''
for i in range(len(s) - 2):
ss += base[diy_base.find(s[i])]
ss += "=="
a = base64.b64decode(ss)
print(a)
print(list(map(hex, a)))
x = [0] * len(flag)
for i in range(len(flag)):
x[i] = hex(ord(flag[i]))
print(x)

之后aes解密

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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
/****************************************************************************************************************/
typedef enum {
AES_CYPHER_128,
AES_CYPHER_192,
AES_CYPHER_256,
} AES_CYPHER_T;
/****************************************************************************************************************/
/*
* Encryption Rounds
*/
int g_aes_key_bits[] = {
/* AES_CYPHER_128 */ 128,
/* AES_CYPHER_192 */ 192,
/* AES_CYPHER_256 */ 256,
};
int g_aes_rounds[] = {
/* AES_CYPHER_128 */ 10,
/* AES_CYPHER_192 */ 12,
/* AES_CYPHER_256 */ 14,
};
int g_aes_nk[] = {
/* AES_CYPHER_128 */ 4,
/* AES_CYPHER_192 */ 6,
/* AES_CYPHER_256 */ 8,
};
int g_aes_nb[] = {
/* AES_CYPHER_128 */ 4,
/* AES_CYPHER_192 */ 4,
/* AES_CYPHER_256 */ 4,
};
/****************************************************************************************************************/
/*
* aes Rcon:
*
* WARNING: Rcon is designed starting from 1 to 15, not 0 to 14.
* FIPS-197 Page 9: "note that i starts at 1, not 0"
*
* i | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
* -----+------------------------------------------------------------------------------------------
* | [01] [02] [04] [08] [10] [20] [40] [80] [1b] [36] [6c] [d8] [ab] [4d] [9a]
* RCON | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
*/
static const uint32_t g_aes_rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0xed000000, 0x9a000000
};
/****************************************************************************************************************/
/*
* aes sbox and invert-sbox
*/
static const uint8_t g_aes_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
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
};
static const uint8_t g_inv_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
/****************************************************************************************************************/
uint8_t aes_sub_sbox(uint8_t val)
{
return g_aes_sbox[val];
}
/****************************************************************************************************************/
uint32_t aes_sub_dword(uint32_t val)
{
uint32_t tmp = 0;

tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 0) & 0xFF))) << 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 8) & 0xFF))) << 8;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 16) & 0xFF))) << 16;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 24) & 0xFF))) << 24;

return tmp;
}
/****************************************************************************************************************/
uint32_t aes_rot_dword(uint32_t val)
{
uint32_t tmp = val;

return (val >> 8) | ((tmp & 0xFF) << 24);
}
/****************************************************************************************************************/
uint32_t aes_swap_dword(uint32_t val)
{
return (((val & 0x000000FF) << 24) |
((val & 0x0000FF00) << 8) |
((val & 0x00FF0000) >> 8) |
((val & 0xFF000000) >> 24));
}
/****************************************************************************************************************/
/*
* nr: number of rounds
* nb: number of columns comprising the state, nb = 4 dwords (16 bytes)
* nk: number of 32-bit words comprising cipher key, nk = 4, 6, 8 (KeyLength/(4*8))
*/
void aes_key_expansion(AES_CYPHER_T mode, uint8_t *key, uint8_t *round)
{
uint32_t *w = (uint32_t *)round;
uint32_t t;
int i = 0;

do {
w[i] = *((uint32_t *)&key[i * 4 + 0]);
} while (++i < g_aes_nk[mode]);

do {
if ((i % g_aes_nk[mode]) == 0) {
t = aes_rot_dword(w[i - 1]);
t = aes_sub_dword(t);
t = t ^ aes_swap_dword(g_aes_rcon[i / g_aes_nk[mode] - 1]);
}
else if (g_aes_nk[mode] > 6 && (i % g_aes_nk[mode]) == 4) {
t = aes_sub_dword(w[i - 1]);
}
else {
t = w[i - 1];
}
w[i] = w[i - g_aes_nk[mode]] ^ t;
} while (++i < g_aes_nb[mode] * (g_aes_rounds[mode] + 1));
}
/****************************************************************************************************************/
void aes_add_round_key(AES_CYPHER_T mode, uint8_t *state,
uint8_t *round, int nr)
{
uint32_t *w = (uint32_t *)round;
uint32_t *s = (uint32_t *)state;
int i;

for (i = 0; i < g_aes_nb[mode]; i++) {
s[i] ^= w[nr * g_aes_nb[mode] + i];
}
}
/****************************************************************************************************************/
void aes_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (j = 0; j < 4; j++) {
state[i * 4 + j] = aes_sub_sbox(state[i * 4 + j]);
}
}
}
/****************************************************************************************************************/
void aes_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;

for (i = 1; i < g_aes_nb[mode]; i++) {
for (j = 0; j < i; j++) {
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++) {
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
/****************************************************************************************************************/
uint8_t aes_xtime(uint8_t x)
{
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
}
/****************************************************************************************************************/
uint8_t aes_xtimes(uint8_t x, int ts)
{
while (ts-- > 0) {
x = aes_xtime(x);
}

return x;
}
/****************************************************************************************************************/
uint8_t aes_mul(uint8_t x, uint8_t y)
{
/*
* encrypt: y has only 2 bits: can be 1, 2 or 3
* decrypt: y could be any value of 9, b, d, or e
*/

return ((((y >> 0) & 1) * aes_xtimes(x, 0)) ^
(((y >> 1) & 1) * aes_xtimes(x, 1)) ^
(((y >> 2) & 1) * aes_xtimes(x, 2)) ^
(((y >> 3) & 1) * aes_xtimes(x, 3)) ^
(((y >> 4) & 1) * aes_xtimes(x, 4)) ^
(((y >> 5) & 1) * aes_xtimes(x, 5)) ^
(((y >> 6) & 1) * aes_xtimes(x, 6)) ^
(((y >> 7) & 1) * aes_xtimes(x, 7)));
}
/****************************************************************************************************************/
void aes_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 };
uint8_t s[4];
int i, j, r;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (r = 0; r < 4; r++) {
s[r] = 0;
for (j = 0; j < 4; j++) {
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++) {
state[i * 4 + r] = s[r];
}
}
}
/****************************************************************************************************************/
int aes_encrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */

int nr, i, j;

/* key expansion */
aes_key_expansion(mode, key, w);

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) {

if (nr > 0) {

/* do SubBytes */
aes_sub_bytes(mode, s);

/* do ShiftRows */
aes_shift_rows(mode, s);

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
aes_mix_columns(mode, s);
}
}

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}

return 0;
}
/****************************************************************************************************************/
int aes_encrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_encrypt(mode, data, len, key);
}
/****************************************************************************************************************/
int aes_encrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */
uint8_t v[4 * 4] = { 0 }; /* iv */

int nr, i, j;


/* key expansion */
aes_key_expansion(mode, key, w);

memcpy(v, iv, sizeof(v));

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j] ^ v[j];

/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) {

if (nr > 0) {

/* do SubBytes */
aes_sub_bytes(mode, s);

/* do ShiftRows */
aes_shift_rows(mode, s);

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
aes_mix_columns(mode, s);
}
}

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = v[j] = s[j];
}

return 0;
}
/****************************************************************************************************************/
void inv_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;

for (i = 1; i < g_aes_nb[mode]; i++) {
for (j = 0; j < g_aes_nb[mode] - i; j++) {
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++) {
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
/****************************************************************************************************************/
uint8_t inv_sub_sbox(uint8_t val)
{
return g_inv_sbox[val];
}
/****************************************************************************************************************/
void inv_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (j = 0; j < 4; j++) {
state[i * 4 + j] = inv_sub_sbox(state[i * 4 + j]);
}
}
}
/****************************************************************************************************************/
void inv_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d,
0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09, 0x0e };
uint8_t s[4];
int i, j, r;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (r = 0; r < 4; r++) {
s[r] = 0;
for (j = 0; j < 4; j++) {
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++) {
state[i * 4 + r] = s[r];
}
}
}
/****************************************************************************************************************/
int aes_decrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */

int nr, i, j;

/* key expansion */
aes_key_expansion(mode, key, w);

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) {

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);

if (nr > 0) {

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
inv_mix_columns(mode, s);
}

/* do ShiftRows */
inv_shift_rows(mode, s);

/* do SubBytes */
inv_sub_bytes(mode, s);
}
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}

return 0;
}
/****************************************************************************************************************/
int aes_decrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_decrypt(mode, data, len, key);
}
/****************************************************************************************************************/
int aes_decrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */
uint8_t v[4 * 4] = { 0 }; /* iv */


int nr, i, j;

/* key expansion */
aes_key_expansion(mode, key, w);

memcpy(v, iv, sizeof(v));

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {


/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) {

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);

if (nr > 0) {

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
inv_mix_columns(mode, s);
}

/* do ShiftRows */
inv_shift_rows(mode, s);

/* do SubBytes */
inv_sub_bytes(mode, s);
}
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++) {
uint8_t p = s[j] ^ v[j];
v[j] = data[i + j];
data[i + j] = p;
}
}

return 0;
}
/****************************************************************************************************************/
void aes_cypher_128_test()
{
#if 1
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
#else
uint8_t buf[] = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };
uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
#endif

aes_encrypt(AES_CYPHER_128, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void aes_cypher_192_test()
{
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

aes_encrypt(AES_CYPHER_192, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void aes_cypher_256_test()
{
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };

aes_encrypt(AES_CYPHER_256, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void main()
{
//数据
uint8_t buf[] = { 0xda, 0x96, 0x78, 0x79, 0x54, 0xa4, 0xd1, 0x3, 0x54, 0x95, 0xf3, 0x48, 0x8d, 0xe9, 0x8b, 0xeb};

//密钥
uint8_t key[] = { 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x66, 0x75, 0x6c,0x64, 0x61,0x79, 0x21, 0x21, 0x21, 0x21};
//向量
uint8_t iv[] = {0x3c, 0x3d, 0x37, 0x36, 0x21, 0x35, 0x26, 0x3f, 0x37,0x32, 0x2a, 0x72, 0x72, 0x72, 0x72, 0x53};
switch (sizeof(key))
{
//ECB

case 16:aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key); break;
case 24:aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key); break;
case 32:aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key); break;
//CBC
/*
case 16:aes_decrypt_cbc(AES_CYPHER_128, buf, sizeof(buf), key, iv); break;
case 24:aes_decrypt_cbc(AES_CYPHER_192, buf, sizeof(buf), key, iv); break;
case 32:aes_decrypt_cbc(AES_CYPHER_256, buf, sizeof(buf), key, iv); break;
*/
}
for (int i = 0; i < sizeof(buf); i++)
{
printf("%c", buf[i] & 0xFF);
}
printf("\n");
return;
}

得到:flag{weu/.,iopl}

FFunction

这题搞得其实有点晕,好多信息要猜测,给了很多文件,我们找到关键my_plugin这个dll文件,在f函数中调试断点。

image-20220719184430550

发现tea加密,提取数据,又发现传进来的数据进行了疑似base64的加密,据说只能猜。而且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 <stdio.h>
#include <stdint.h>

//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0x79B99E37 << 5, i; /* set up */
uint32_t delta=0x79B99E37; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t k[]={0x0BABEC0FE,0x0DEADBEEF,0x0FACEB00C,0xDEADC0DE},v[]={0x5C15754C, 0xD1D781E7, 0x501BF173, 0xCB4DB222, 0x215D61F5, 0x3FCA9EE7, 0x7C76B5C7, 0xC7DD8CB9, 0x990D23FA, 0x0BAB1AD3, 0x8E12C932, 0xD307BAF2, 0xE52DD123, 0xFBB68F2C, 0xBDD853E3, 0x892E1E4E, 0x39DD66FA, 0x87FEEC65, 0x307C5E60, 0x340C6C00};
decrypt(v, k);
decrypt(v+2, k);
decrypt(v+4, k);
decrypt(v+6, k);
decrypt(v+8, k);
decrypt(v+10, k);
decrypt(v+12, k);
decrypt(v+14, k);
decrypt(v+16, k);
decrypt(v+18, k);
decrypt(v+20, k);
printf("decode:%x %x\n",v[0],v[1]);
printf("decode:%x %x\n",v[2],v[3]);
printf("decode:%x %x\n",v[4],v[5]);
printf("decode:%x %x\n",v[6],v[7]);
printf("decode:%x %x\n",v[8],v[9]);
printf("decode:%x %x\n",v[10],v[11]);
printf("decode:%x %x\n",v[12],v[13]);
printf("decode:%x %x\n",v[14],v[15]);
printf("decode:%x %x\n",v[16],v[17]);
printf("decode:%x %x\n",v[18],v[19]);
printf("decode:%x %x\n",v[20]);
return 0;
}

decode小端序拼接一下,两两相加进行一个base64解密,然后再手动搞一下flag就对了,

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

a="30014006400460044007500230035008600c400a600e6003600c300930016004300340025004400d7007500250086002600f5006300050083007400e3000500a600840055007400970033001600e500a"
import re
ccc=re.findall(".{2}",a)
ccc=[int(i,16) for i in ccc]
fl=""
for index in range(0,len(ccc),2):
fl+=(chr(ccc[index]+ccc[index+1]))
print(fl[::-1])
print(base64.b64decode(fl[::-1]).decode())
#Zn1sIWEhZ0N7X0VobXRwMTB3d19lcnJlX3RGdDF1
#f}l!a!gC{_Ehmtp10ww_erre_tFt1u

手动一下:flag{Emp0wer_F1utter_w1th_C!!}