1-4 生

考点:

upx

出题思路:

upx改壳+循环自异或逻辑 第一周压轴应该没啥问题

wp:

upx改壳

直接脱壳会有报错 这里有两种做法 看做题人学习的时候会学到哪个

依靠工具的就是去修正标志位

如此修正便可以机脱

另一种方法是手托 可以用x64dbg 也可以直接用ida动态去看(如果是ida动态看的话 就比较吃基础了) 这里手托的方法就不放在wp里了 不会的新生在新生赛结束后来问学长就行

那么脱壳之后就是找到main进行分析

简单的重命名一下 最后enput与flag进行比较 enput由input加密得到 所以所需要的输入时flag 解密 得到正确input 长度30位

分析加密 输入和下一位异或 最后一位和第一位异或 那么复原的时候就是先让最后一位和第一位异或得到最后一位 再从后往前 每一位和下一位异或

convert提取flag 解密即可获得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
void decry(char* a1)
{
a1[29] ^= a1[0];
for (int i = 28; i >= 0; i--)
{
a1[i] ^= a1[i + 1];
}
}
int main()
{
char flag[31] = {
0x1B, 0x00, 0x01, 0x0E, 0x17, 0x12, 0x1D, 0x2E, 0x32, 0x56, 0x48, 0x26, 0x2A, 0x42, 0x4F, 0x27,
0x1F, 0x2E, 0x0A, 0x3B, 0x3D, 0x56, 0x56, 0x1B, 0x26, 0x27, 0x48, 0x42, 0x0F, 0x66, 0
};
decry(flag);
printf("%s", flag);
//wllmctf{Ug1y_u7x_@nd_b4by_x0r}
return 0;
}

这里之所以最后加一个0 是因为%s是读取到0暂停 如果不加截止字符 会输出其他东西

源码

upx+简单异或

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

#define Len 50
#define flaglen 30
char flag[Len] = { 0x1b, 0x00, 0x01, 0x0e, 0x17, 0x12, 0x1d, 0x2e, 0x32, 0x56, 0x48, 0x26, 0x2a, 0x42, 0x4f, 0x27, 0x1f, 0x2e, 0x0a, 0x3b, 0x3d, 0x56, 0x56, 0x1b, 0x26, 0x27, 0x48, 0x42, 0x0f, 0x66, };

int len(char* str)
{
int ret = 0;
while (str[ret] != 0) ret++;
return ret;
}

void encrypt(char* input, char* enput)
{
int i;
for (i = 0; i < flaglen - 1; i++)
{
enput[i] = input[i] ^ input[i + 1];
}
enput[i] = input[i] ^ enput[0];
}

int cmp(char* a, char* b)
{
for (int i = 0; i < flaglen; i++)
{
if (a[i] != b[i])
{
return 0;
}
}
return 1;
}

int main()
{
//"wllmctf{Ug1y_u7x_@nd_b4by_x0r}"
char input[Len];
char enput[Len];
memset(input, 0, Len);
memset(enput, 0, Len);


printf("please input:");
scanf("%s", input);

if (len(input) != flaglen)
{
printf("your len is wrong!");
return 0;
}

encrypt(input, enput);

if (!cmp(enput, flag))
{
printf("try ageen!");
return 0;
}
printf("You_have_flag!");
return 0;
}

wp

​

2-1 嗔

考点:

elf + md5爆破

出题思路:

限制输入长度在三字节且是字母 简单编写一个脚本爆破md5获得key 调试或者运行可以自解密输出flag

wp:

elf文件 拖入ida分析

输入的是key 经过checkkey函数

这里checkkey先判断长度是否为3 在判断每一个都是否是在a-z之间 最后返回整体的结果

后续是md5加密 md5加密不可逆所以要编写爆破脚本或者在线网站

获得key是ipu key输入正确后会自解密输出flag 这里提示说了 运行即可获得 那么就是虚拟机运行得到flag

wllmctf{Wo0o0oW!Md5_&nd_El7_You_a1l_Defe@t_!t}

源码

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
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include<time.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char FA(unsigned char b);
unsigned char FB(unsigned char b);
unsigned char FC(unsigned char b);
unsigned char FD(unsigned char b);
unsigned char FE(unsigned char b);
unsigned char Ff(unsigned char b);
void Cipher(unsigned char* input, unsigned char* output, unsigned char* w);//加密
void InvCipher(unsigned char* input, unsigned char* output, unsigned char* w);//解密

static unsigned char AesSbox[16 * 16] =
{
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 unsigned char AesiSbox[16 * 16] =
{
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
};
static unsigned char AesRcon[11 * 4] =
{
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00
};

unsigned char FA(unsigned char b) { if (b < 0x80) return (b << 1); else return ((b << 1) ^ (0x1b)); }
unsigned char FB(unsigned char b) { return FA(b) ^ b; }
unsigned char FC(unsigned char b) { return FA(FA(FA(b))) ^ b; }
unsigned char FD(unsigned char b) { return FA(FA(FA(b))) ^ FA(b) ^ b; }
unsigned char FE(unsigned char b) { return FA(FA(FA(b))) ^ FA(FA(b)) ^ b; }
unsigned char Ff(unsigned char b) { return FA(FA(FA(b))) ^ FA(FA(b)) ^ FA(b); }

void Cipher(unsigned char* input, unsigned char* output, unsigned char* exp_key)
{
int i, j;
int round;
unsigned char ttt[4 * 4];
unsigned char State[4][4];
for (i = 0; i < 16; i++) State[i % 4][i / 4] = input[i];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * j + i];
for (round = 1; round <= 9; round++)
{
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = AesSbox[State[i][j]];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)ttt[4 * i + j] = State[i][j];
for (i = 1; i < 4; i++)for (j = 0; j < 4; j++)
{
if (i == 1)State[i][j] = ttt[4 * i + (j + 1) % 4]; else if (i == 2)State[i][j] = ttt[4 * i + (j + 2) % 4]; else if (i == 3)State[i][j] = ttt[4 * i + (j + 3) % 4];
}
for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) ttt[4 * i + j] = State[i][j];
for (j = 0; j < 4; j++)
{
State[0][j] = FA(ttt[0 + j]) ^ FB(ttt[4 * 1 + j]) ^ ttt[4 * 2 + j] ^ ttt[4 * 3 + j];
State[1][j] = ttt[0 + j] ^ FA(ttt[4 * 1 + j]) ^ FB(ttt[4 * 2 + j]) ^ ttt[4 * 3 + j];
State[2][j] = ttt[0 + j] ^ ttt[4 * 1 + j] ^ FA(ttt[4 * 2 + j]) ^ FB(ttt[4 * 3 + j]);
State[3][j] = FB(ttt[0 + j]) ^ ttt[4 * 1 + j] ^ ttt[4 * 2 + j] ^ FA(ttt[4 * 3 + j]);
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * ((round * 4) + j) + i];
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = AesSbox[State[i][j]];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)ttt[4 * i + j] = State[i][j];
for (i = 1; i < 4; i++)for (j = 0; j < 4; j++)
{
if (i == 1)State[i][j] = ttt[4 * i + (j + 1) % 4]; else if (i == 2)State[i][j] = ttt[4 * i + (j + 2) % 4]; else if (i == 3)State[i][j] = ttt[4 * i + (j + 3) % 4];
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * (40 + j) + i];
for (i = 0; i < 16; i++)output[i] = State[i % 4][i / 4];
}

//Aes解密函数
void InvCipher(unsigned char* input, unsigned char* output, unsigned char* exp_key)
{
int round;
int i, j;
unsigned char ttt[4 * 4];
unsigned char State[4][4];
for (i = 0; i < 16; i++)State[i % 4][i / 4] = input[i];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * (40 + j) + i];
for (round = 9; round >= 1; round--)
{
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)ttt[4 * i + j] = State[i][j];
for (i = 1; i < 4; i++)for (j = 0; j < 4; j++)
{
if (i == 1)State[i][j] = ttt[4 * i + (j + 3) % 4]; else if (i == 2)State[i][j] = ttt[4 * i + (j + 2) % 4]; else if (i == 3)State[i][j] = ttt[4 * i + (j + 1) % 4];
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = AesiSbox[State[i][j]];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * ((round * 4) + j) + i];
for (i = 0; i < 4; i++)for (j = 0; j < 4; j++) ttt[4 * i + j] = State[i][j];
for (j = 0; j < 4; j++)
{
State[0][j] = Ff(ttt[j]) ^ FD(ttt[4 + j]) ^ FE(ttt[4 * 2 + j]) ^ FC(ttt[4 * 3 + j]);
State[1][j] = FC(ttt[j]) ^ Ff(ttt[4 + j]) ^ FD(ttt[4 * 2 + j]) ^ FE(ttt[4 * 3 + j]);
State[2][j] = FE(ttt[j]) ^ FC(ttt[4 + j]) ^ Ff(ttt[4 * 2 + j]) ^ FD(ttt[4 * 3 + j]);
State[3][j] = FD(ttt[j]) ^ FE(ttt[4 + j]) ^ FC(ttt[4 * 2 + j]) ^ Ff(ttt[4 * 3 + j]);
}
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)ttt[4 * i + j] = State[i][j];
for (i = 1; i < 4; i++)for (j = 0; j < 4; j++)
{
if (i == 1)State[i][j] = ttt[4 * i + (j + 3) % 4]; else if (i == 2)State[i][j] = ttt[4 * i + (j + 2) % 4]; else if (i == 3)State[i][j] = ttt[4 * i + (j + 1) % 4];
}
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = AesiSbox[State[i][j]];
for (j = 0; j < 4; j++)for (i = 0; i < 4; i++)State[i][j] = State[i][j] ^ exp_key[4 * j + i];
for (i = 0; i < 16; i++)output[i] = State[i % 4][i / 4];
}

/*****************************************************
*函数功能: AES加密, 模式CBC,数据块128位,填充方式:pkcs5padding
* 参数:
* input_buff:需要加密的数组指针
* InputLen:加密数据的字节长度
* p_key: 指向密钥数据的指针, 1~16字节长度
* output_buff:加密结果输出指针
*
* 返回值: OutLength 加密后的输出长度
*********************************************************/
unsigned long AES128_CBC_Encrypt(unsigned char* input_buff, unsigned long InputLen, unsigned char* p_key, unsigned char* output_buff, unsigned char* iv)
{
unsigned long OutLength = 0;
long i, j;
unsigned char* lpCurInBuff = input_buff;
unsigned char* lpCurOutBuff = output_buff;
long blocknum = InputLen / 16;
long leftnum = InputLen % 16;

int row;
unsigned char temp[4];
unsigned char ex_key[16 * 15];
for (row = 0; row < 4; row++) //拷贝seed 密钥
{
ex_key[4 * row + 0] = *(p_key + 4 * row);
ex_key[4 * row + 1] = *(p_key + 4 * row + 1);
ex_key[4 * row + 2] = *(p_key + 4 * row + 2);
ex_key[4 * row + 3] = *(p_key + 4 * row + 3);
}
for (row = 4; row < 44; row++)
{
temp[0] = ex_key[4 * row - 4]; //当前列的前一列
temp[1] = ex_key[4 * row - 3];
temp[2] = ex_key[4 * row - 2];
temp[3] = ex_key[4 * row - 1];
if (row % 4 == 0)
{
unsigned char exchange_buff = 0;
exchange_buff = temp[0];
temp[0] = AesSbox[16 * (temp[1] >> 4) + (temp[1] & 0x0f)];
temp[1] = AesSbox[16 * (temp[2] >> 4) + (temp[2] & 0x0f)];
temp[2] = AesSbox[16 * (temp[3] >> 4) + (temp[3] & 0x0f)];
temp[3] = AesSbox[16 * (exchange_buff >> 4) + (exchange_buff & 0x0f)];

temp[0] = temp[0] ^ AesRcon[4 * (row / 4) + 0];
temp[1] = temp[1] ^ AesRcon[4 * (row / 4) + 1];
temp[2] = temp[2] ^ AesRcon[4 * (row / 4) + 2];
temp[3] = temp[3] ^ AesRcon[4 * (row / 4) + 3];
}
ex_key[4 * row + 0] = ex_key[4 * (row - 4) + 0] ^ temp[0];
ex_key[4 * row + 1] = ex_key[4 * (row - 4) + 1] ^ temp[1];
ex_key[4 * row + 2] = ex_key[4 * (row - 4) + 2] ^ temp[2];
ex_key[4 * row + 3] = ex_key[4 * (row - 4) + 3] ^ temp[3];
}
for (i = 0; i < blocknum; i++)
{
for (j = 0; j < 16; j++)lpCurOutBuff[j] = lpCurInBuff[j] ^ iv[j];
Cipher(lpCurOutBuff, lpCurOutBuff, ex_key);
memcpy(iv, lpCurOutBuff, 16);
lpCurInBuff += 16;
lpCurOutBuff += 16;
OutLength += 16;
}
if (leftnum)
{
unsigned char inbuff[16];
memset(inbuff, 16 - leftnum, 16);
memcpy(inbuff, lpCurInBuff, leftnum);
for (j = 0; j < 16; j++)lpCurOutBuff[j] = inbuff[j] ^ iv[j];
Cipher(lpCurOutBuff, lpCurOutBuff, ex_key);
memcpy(iv, lpCurOutBuff, 16);
lpCurOutBuff += 16;
OutLength += 16;
}
else
{
unsigned char extrabuff[16];
memset(extrabuff, 16, 16);
for (j = 0; j < 16; j++)lpCurOutBuff[j] = extrabuff[j] ^ iv[j];
Cipher(lpCurOutBuff, lpCurOutBuff, ex_key);
memcpy(iv, lpCurOutBuff, 16);
OutLength += 16;
}
return OutLength;
}

/*******************************************************
*函数功能: AES解密, 模式CBC,数据块128位,填充方式:pkcs5padding
* 参数:
* input_buff:需要解密的数组指针
* InputLen:需要解密数据的字节长度
* p_key: 指向密钥数据的指针, 1~16字节长度
* output_buff:加密结果输出指针
*
* 返回值: OutLength 加密后的输出长度
********************************************************/
unsigned long AES128_CBC_Decrypt(unsigned char* input_buff, unsigned long InputLen, unsigned char* p_key, unsigned char* output_buff, unsigned char* iv)
{
unsigned long OutLength = 0;
long blocknum = InputLen / 16;
long leftnum = InputLen % 16;
long i, j;
unsigned char temp[16];

unsigned char* pCurInBuf = input_buff;
unsigned char* pCurOutBuf = output_buff;
int row;
unsigned char ex_key[16 * 15];
for (row = 0; row < 4; row++)
{
ex_key[4 * row + 0] = *(p_key + 4 * row);
ex_key[4 * row + 1] = *(p_key + 4 * row + 1);
ex_key[4 * row + 2] = *(p_key + 4 * row + 2);
ex_key[4 * row + 3] = *(p_key + 4 * row + 3);
}
for (row = 4; row < 44; row++)
{
temp[0] = ex_key[4 * row - 4]; //当前列的前一列
temp[1] = ex_key[4 * row - 3];
temp[2] = ex_key[4 * row - 2];
temp[3] = ex_key[4 * row - 1];
if (row % 4 == 0)
{
unsigned char exchange_buff = 0;
exchange_buff = temp[0];
temp[0] = AesSbox[16 * (temp[1] >> 4) + (temp[1] & 0x0f)];
temp[1] = AesSbox[16 * (temp[2] >> 4) + (temp[2] & 0x0f)];
temp[2] = AesSbox[16 * (temp[3] >> 4) + (temp[3] & 0x0f)];
temp[3] = AesSbox[16 * (exchange_buff >> 4) + (exchange_buff & 0x0f)];
temp[0] = temp[0] ^ AesRcon[4 * (row / 4) + 0];
temp[1] = temp[1] ^ AesRcon[4 * (row / 4) + 1];
temp[2] = temp[2] ^ AesRcon[4 * (row / 4) + 2];
temp[3] = temp[3] ^ AesRcon[4 * (row / 4) + 3];
}
ex_key[4 * row + 0] = ex_key[4 * (row - 4) + 0] ^ temp[0];
ex_key[4 * row + 1] = ex_key[4 * (row - 4) + 1] ^ temp[1];
ex_key[4 * row + 2] = ex_key[4 * (row - 4) + 2] ^ temp[2];
ex_key[4 * row + 3] = ex_key[4 * (row - 4) + 3] ^ temp[3];
}
for (i = 0; i < blocknum; i++)
{
InvCipher(pCurInBuf, pCurOutBuf, ex_key);
for (j = 0; j < 16; j++)
{
pCurOutBuf[j] = pCurOutBuf[j] ^ iv[j];
}
memcpy(iv, pCurInBuf, 16);
if (i == (blocknum - 1))
{
memset(temp, 0, 16);
if (pCurOutBuf[15] != 0x10)
{
if (pCurOutBuf[15] < 0x10)
{
OutLength = InputLen - pCurOutBuf[15];
memcpy(temp, pCurOutBuf, 16 - pCurOutBuf[15]);
memcpy(pCurOutBuf, temp, 16);
}
else
break;
}
else
{
OutLength = InputLen - 16;
memcpy(pCurOutBuf, temp, 16);
}
}
pCurInBuf += 16;
pCurOutBuf += 16;
}
return OutLength;
}

typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
}MD5_CTX;

#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
a += F(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
a += G(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
a += H(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
a += I(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
void MD5Init(MD5_CTX* context);
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen);
void MD5Final(MD5_CTX* context, unsigned char digest[16]);
void MD5Transform(unsigned int state[4], unsigned char block[64]);
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len);
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len);

unsigned char PADDING[] = { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

char rightkey[] = "f9f5db212d8c814b045e79ef4cc02bf0";

void md5(unsigned char* encrypt, unsigned char* decrypt, size_t size)
{
int i;
MD5_CTX md5;
MD5Init(&md5);
MD5Update(&md5, encrypt, size);
MD5Final(&md5, decrypt);
return;
}

char str2hex(char a1,char a2)
{
if (a1 >= 'a' && a1 <= 'f')
{
a1 = a1 - 'a' + 10;
}
else if (a1 >= '0' && a1 <= '9')
{
a1 = a1 - '0';
}

if (a2 >= 'a' && a2 <= 'f')
{
a2 = a2 - 'a' + 10;
}
else if (a2 >= '0' && a2 <= '9')
{
a2 = a2 - '0';
}

return ((a1 << 4) & 0xf0) | (a2 & 0xf);
}

int checkkey(char* key)
{
int ret = 0;
ret |= (strlen(key) == 3);
for (int i = 0; i < strlen(key); i++)
ret &= (key[i] >= 'a' && key[i] <= 'z');
return ret;
}

char* makeflag(char* md5_key)
{
unsigned long outlen;
unsigned char en_flag[49] = { 0x7c, 0x15, 0x47, 0xa1, 0x23, 0xc1, 0x42, 0x4b, 0xbc, 0x99, 0x86, 0xe1, 0xc9, 0x35, 0x33, 0xcd, 0x3b, 0xe0, 0x3e, 0x85, 0xc9, 0x64, 0x1b, 0xab, 0x08, 0x70, 0x1b, 0xee, 0x77, 0xad, 0x77, 0x21, 0xbc, 0x9d, 0xf2, 0xa7, 0x46, 0x55, 0xa8, 0x7b, 0x0d, 0x16, 0xc4, 0x6a, 0xa3, 0xc2, 0xc3, 0x4c, };
unsigned char de_iv[49] = { 0 };
unsigned char* de_flag = (unsigned char*)malloc(49);

for (int i = 0; i < 37; i += 16)
outlen = AES128_CBC_Decrypt(en_flag + i, 16, md5_key, de_flag + i, de_iv + i);
return de_flag;
}

int main()
{
char key[100];
char save_key[4];
char md5_key[16];

printf("please give me your password:");
scanf("%s", key);

int IsPkey = 1;

if (checkkey(key))
{
md5(key, md5_key, 3);

for (int i = 0; i < 16; i++)
IsPkey &= (md5_key[i] == str2hex(rightkey[i * 2], rightkey[i * 2 + 1]));

if (IsPkey)
{
printf("you pass!\n");
printf("Now run this elf to catch flag! what? you don't know how to run? \n");
printf("this website will help you: https://www.yuque.com/hututu-mknzl/ohkff2/apbe1hiep71iealy \n");
printf("So your flag is wllmctf{%s}\n", makeflag(md5_key));
return 0;
}
printf("[-] !!!error!!! : 0xC0000005\n");
return 0;
}
printf("[-] !!!error!!! : 0xC0000005\n");
return 0;
}

void MD5Init(MD5_CTX* context)
{
context->count[0] = 0;
context->count[1] = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
}
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen)
{
unsigned int i = 0, index = 0, partlen = 0;
index = (context->count[0] >> 3) & 0x3F;
partlen = 64 - index;
context->count[0] += inputlen << 3;
if (context->count[0] < (inputlen << 3))
context->count[1]++;
context->count[1] += inputlen >> 29;

if (inputlen >= partlen)
{
memcpy(&context->buffer[index], input, partlen);
MD5Transform(context->state, context->buffer);
for (i = partlen; i + 64 <= inputlen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index], &input[i], inputlen - i);
}
void MD5Final(MD5_CTX* context, unsigned char digest[16])
{
unsigned int index = 0, padlen = 0;
unsigned char bits[8];
index = (context->count[0] >> 3) & 0x3F;
padlen = (index < 56) ? (56 - index) : (120 - index);
MD5Encode(bits, context->count, 8);
MD5Update(context, PADDING, padlen);
MD5Update(context, bits, 8);
MD5Encode(digest, context->state, 16);
}
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[j] = input[i] & 0xFF;
output[j + 1] = (input[i] >> 8) & 0xFF;
output[j + 2] = (input[i] >> 16) & 0xFF;
output[j + 3] = (input[i] >> 24) & 0xFF;
i++;
j += 4;
}
}
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[i] = (input[j]) |
(input[j + 1] << 8) |
(input[j + 2] << 16) |
(input[j + 3] << 24);
i++;
j += 4;
}
}
void MD5Transform(unsigned int state[4], unsigned char block[64])
{
unsigned int a = state[0];
unsigned int b = state[1];
unsigned int c = state[2];
unsigned int d = state[3];
unsigned int x[64];
MD5Decode(x, block, 64);
FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */

/* Round 2 */
GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */

/* Round 3 */
HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], 23, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */

/* Round 4 */
II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}

2-2 妄

考点:花指令 + rc4

出题思路:

本题提示很多 所以花指令个数会增加 不过都是简单花指令 分析汇编去掉即可

wp:

拖入ida

一开始有提示 运行获取hint 那么运行一下

大段的提示就是再说 花指令爆红原理 那么要分析汇编去除

回到题目 获取到输入后现有一个sub_401480函数 点进去发现是爆红的了 这时候就要分析汇编了

这里很明显是跳到loc_4019C4+1的位置 也就是说call的E8实际上是被跳过了 那么u重定义 ctr+n快速nop修掉

于是得到2025wllm 紧接着是sub_401870函数 这里第一二个参数是输入和输入长度 三四参数是key和key长度

进去看到三个未知函数

先将v5赋值0第一个函数点进去

简单分析发现是永真跳 那么这里还是要nop第一个字节

这里可以选择整理一下函数 点击一下函数名字 然后y重定义 将返回值类型改成void 然后点击a1 这里很明显 a1是字符串 所以改成char* 的定义

这样就十分好看了 就是将传入的参数赋值0-255

这里我将函数名命名为initbox 同时将前面的v5命名为box 因为这明显是一个很大的盒子 后续可能是通过盒子进行加密

第一个函数分析完毕 分析第二个

可以先假设zf是1 那么第一个jz要跳转到jz那里 然后第二个jz依然会跳走 可以看出来loc_401021这里是十分有争议的 可以先u转换为无定义

无定义后发现22和25这两个地方是指令 E8是完全被忽略掉的 所以可以nop掉然后将后面换成指令 这里换成指令会发现后面又爆红了 咱们把后面u掉

这样看就很明显的25前的E8没用 nop掉

长得很丑 修一修

因为看函数传入参数会发现 a1和a2分别是key和box 所以定义需要修成char 那么这里还会有unsigned _int8其实是因为这个定义是unsigned char* 按\健可以隐藏掉 那么这里最后会变成这样

还有个函数点进入

还是花指令 分析一下 最开始xor eax, eax eax就变成0了

然后eax+1+2=3 之后第一次的比较结果肯定是不跳转 3*3=9 9-2=7 7^8=15 15&11:

1111

1011

1011 = 11 所以这里的结果还是不等于 但是不等于会跳转回去 这时候在11的基础上+3是14 那刚好是E就跳转了 所以这里实际上就是通过复杂计算骗过ida来造成花指令

所以去掉花指令+修复后得到函数

也就是两个参数互换值

那么再回到这个函数 大家在逆向分析的时候采取一个取巧的思路 这里传入的是key和box 也就是说对输入的本身是完全没有影响的 所以不需要逆向获取解密 这里分析过其实会发现 最终真的发生了实际变化的只有盒 因为等式右边的操作都是临时的 不会对本身操作的比如说

b=1 a=b+1 这个过程中b变了吗 显然是否定的 那么我们可以把这个函数命名为changebox

那么就差最后一个函数了

、

这里和前面两段jzjnz有点像 这里也可以先假设 假设eax是0那么他就直接跳转到D7 如果他不是0那么会跳转到归0的地方 再回来 那么回来之后就是0了 就可以跳转了

去掉花再修复就变成这样子 这里其实对加密真正变化的就是^= 所以这里完全可以运行的时候dump下来异或的对象 也可以将前面的操作复现出来 然后^

还有种更简单的 因为这个加密的本质就是异或 而异或是可逆的 所以完全可以将flag直接patch掉输入得到flag 这里我用最后一种做法

这里flag的长度是38位 先填充38位东西

断点下在加密前 然后patch即可

得到wllmctf{B4by_RC4_@nd_Beautifu1_7lower}

源码

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
#include<Windows.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include <time.h>
#include<iostream>
#include <conio.h>
#define StrSpeed 1 //字慢打印速度
#define MaxLen 50
#define FlagLen 38
#define Time 1 //微秒
#define Seed 714 //随机种子
#define MaxLen 1000 //最大宽度

char flag[FlagLen] = { 0x25, 0xdd, 0x0a, 0x76, 0x44, 0xbf, 0x54, 0xfa, 0x22, 0xf8, 0xb1, 0x66, 0x4e, 0xa0, 0xcb, 0x8c, 0x1d, 0x27, 0xd2, 0xaa, 0xeb, 0xab, 0x89, 0x71, 0x45, 0x34, 0xed, 0x03, 0xec, 0x16, 0x85, 0xae, 0xda, 0x0c, 0x6f, 0xf5, 0xf4, 0x9d, };

int r; //随机数
int hang = 0; //行
int lie = 0; //列

char needbox[] = " -+*.=|/1_(')<";
int colors[13] = { 31, 32, 33, 34, 35, 36, 37, 90, 91, 92, 93, 94, 95 };

void printSlowly(const char* str) {
int fastMode = 0; // 快进模式标志
while (*str) {
// 检查是否有键盘输入
if (_kbhit()) {
char key = _getch(); // 获取按下的键
if (key == 'f' || key == 'F') {
fastMode = 1; // 启用快进模式
}
}

if (fastMode) {
// 快进模式,直接打印剩余内容
printf("%s", str);
fflush(stdout);
break;
}
else {
// 普通模式逐字打印
std::cout << *str++;
fflush(stdout);
Sleep(StrSpeed); // 控制字符打印的间隔时间
}
}
}

void precise_sleep_us(long microseconds)
{
LARGE_INTEGER freq, start, now;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
do {
QueryPerformanceCounter(&now);
} while ((now.QuadPart - start.QuadPart) * 1000000 / freq.QuadPart < microseconds);
}

//行位移
void tohang(int mh)
{
if (mh == -1)
{
return;
}
//如果当前行大于目标行 那么上移
while (hang > mh) {
printf("\x1b[1A");
hang--;
}
//反之下移
while (hang < mh) {
printf("\x1b[1B");
hang++;
}
}
void myprintf1(char* str, int len)
{
int num_colors = sizeof(colors) / sizeof(colors[0]);

int a;
int i, j;
int l[MaxLen];

for (i = 0; str[i] != '\n'; i++)
{
r = rand() % 14;
printf("%c", needbox[r]);
l[i] = 0; //将每一行对应的列填充 后续根据这个数组进行追位
}

//开始主题
do
{
a = 0;
j = i;
//归位
while (j > 0)
{
printf("\x1b[1D");
j--;
}
for (j = 0; j < i; j++)
{
tohang(l[j]);

if (l[j] == -1)
{
printf("\x1b[1C");
continue;
}

r = rand() % 14;
int color = colors[rand() % 14 % num_colors];

if (needbox[r] == str[l[j] * (i + 1) + j])
{
l[j]++;
if (l[j] * (i + 1) + j + 2 > len)
{
l[j] = -1;
printf("\033[%dm%c\033[0m", color, needbox[r]);
continue;
}
}
printf("\033[%dm%c\033[0m", color, needbox[r]);
precise_sleep_us(Time);
}
for (int j = 0; j < i; j++)
{
if (l[j] != -1)
{
a = 1;
}
}
} while (a);
}

void kaichang()
{
char pic[] =
"-------------------------------------------------------\n"
" \n"
" ++*++ .=== \n"
" |*** /*+ \n"
" =---------+++-------+++------_ \n"
" -**+ 1** \n"
" ___- .. \n"
" *** |*+*** \n"
" -****| |*++/ ** \n"
" _=+++**| |*++ _-+ \n"
" ('--' |**| *++- \n"
" |**| +*<*+ \n"
" |**| _+' *+ \n"
" |**| *+ * \n"
" |**| *+........*+ \n"
" |** -*+********+ \n"
" \n"
"-------------------------------------------------------\n";
srand(time(NULL));
int len = 0;
while (pic[len] != 0)len++;
myprintf1(pic, len);
}
void hint()
{
printSlowly("机器不往往按照真实逻辑分析,而是要全部分析一遍\n");
printSlowly("就像是走迷宫,未知的道路中存在着陷阱,你在上帝视角中已经看到了正确的道路,但机器看不到上帝\n");
printSlowly("视角,于是一头栽入陷阱中,发出警告,这时候就需要你的帮助\n");
printSlowly("用你的逻辑走一遍代码,分析出“花”的部分(爆红的地方需要自己分析分析汇编指令)");
return;
}

int return1()
{
return 1;
}

void WrongEncry(char *input)
{
for (int i = 0; i < strlen(input); i++)
{
input[i] ^= i;
}
}

char* makekey()
{
__asm
{
xor eax, eax;

jz a;
jnz a;
__emit 0xE8;
a:
}
char* key = (char*)"2O25w11m";
return key;
}

void makebox(unsigned char* s)
{
int i = 0;
__asm
{
xor eax, eax;
cmp eax, 0;
jz addr2;
__emit 0xE8;
addr2:
}

for (i = 0; i < 256; i++) {
s[i] = i;
}
}

void exchange(unsigned char* a, unsigned char* b)
{
__asm
{
xor eax, eax;
addr3:
add eax, 1;
add eax, 2;
cmp eax, 0xe;
jz addr4;
mul eax;
sub eax, 2;
xor eax, 8;
and eax, 11;
cmp eax, 10;
jnz addr3;
__emit 0xE8;
addr4:
}

char c = *a;
*a = *b;
*b = c;
}

void KSA(unsigned char* s, unsigned char* key, int key_Len)
{
int i, j;
__asm {
jz addr5;
jnz addr6;
addr5:
jz addr7;
__emit 0xE8;
addr6:
jnz addr7;
__emit 0xE8;
addr7:
}
for (i = 0, j = 0; i < 256; i++) {
j = (j + s[i] + key[i % key_Len]) % 256;
exchange(&s[i], &s[j]);
}
}

void PRGA(unsigned char *s, unsigned char *data, int data_Len)
{
int i, j, q, t;
__asm {
cmp eax, 0;
jnz addr8;
addr9:
jz addr10;
__emit 0xE8;
addr8:
xor eax, eax;
jmp addr9;
addr10:
}
for (i = 0, j = 0, q = 0; q < data_Len; q++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;

exchange(&s[i], &s[j]);

t = (s[i] + s[j]) % 256;
data[q] ^= s[t];
}
}

void rc4(unsigned char* key, int key_Len, unsigned char* data, int data_Len) //加解密
{
unsigned char s[256] = { 0 };
makebox(s);
KSA(s, key, key_Len);
PRGA(s, data, data_Len);
}

int main()
{
kaichang();
int len = 0;
int keylen;
char input[MaxLen];

printSlowly("\nPlease run this program\nit might give you a hint.\n");

hint();

if (return1())
{
goto addr1;
}
else
{
return 0;
}

WrongEncry(input);
addr1:
printSlowly("\nThe function always returns 1, so why does IDA still keep the if condition?\n");

//wllmctf{B4by_RC4_@nd_Beautifu1_7lower}
printSlowly("please give me your answer:");
fgets(input, MaxLen, stdin);
while (input[len] != '\n')len++;

char* key = makekey();
keylen = strlen(key);

rc4((unsigned char*)key, keylen, (unsigned char*)input, len);

if (!strncmp(input, flag, len) && len == FlagLen)
{
printSlowly("ohhh!You have passed my second level!\nThat’s really cool!!");
}
else
{
printSlowly("I know it’s a bit tough, but don’t give up — victory is just around the corner!");
}
return 0;
}

3-2 爱

​考点:js

​出题思路:

一个听音乐的js 一个检验key一个flag aes+des+js 其他的啥也没加了

​wp:

拿到题之后先解压 打开Listen_music.html 这里有准备好的几首歌 可以放着听着做喜喜

打开音乐选择界面 感觉还算明显的try to click me

点开后

打开后是人机验证 这里直接F12看源代码

script下的都是 可以通过ctrl+F找到具体代码位置 其实看名字也能猜出来了 在check里面

获取输入框的内容 创建一个encrypto的对象 新生可能不是很了解对象 其实就是让这里可以调用到encrypto.js的函数 这里后面立马有enxor函数的调用

异或0x72 密文是3b1f1c1d06101d06 所以直接得到bot的话是Imnotbot并且后面还有一个setdeskey 函数作用是将this.key赋值Imnotbot 前面constructor给ai分析也能知道 是当这个js对象第一次被创建的时候被调用的 所以到现在为止就是给aeskey aesiv deskey赋值 后面跟着去分析会回到

这里先获取输入列表里的输入 然后aes加密+des加密 这里用到的key都在前面分析出来了 只需要解密即可 (这里有个小彩蛋 在music文件夹下 不仅有音乐还有一个hint)

这里用记事本打开会获得“这是js逆向 解密可以用Cyberchef哦”

所以cyberchef一把梭!

wllmctf{1_10v3_y0u_w15h_y0u_h4v3_m0r3_h4ppy_m3m0r135_1n_un1v3r517y}

4-2 痴

考点:smc+tea

出题思路:

smc+tes改 这里的tea稍微混淆了一下 合并几个同样的值其实就有了

wp:

拖进ida字符串定位到主函数慢慢分析就好不要着急

整体的去看把unk_140061560和v5的差值给v7后面同理给v8v9 v11

这里不要着急他什么意思往后去看v12 = v5 + 2 取v12[v8-2]首先要知道v12[v8 - 2]是等价于*(v12 + v8 - 2)的v8=&unk_140061560-v5代入

(v5+2+&unk_140061560-v5-2)=(&unk_140061560)

现在应该就清楚这里是做什么了把其实就是对unk_140061560数组进行异或v6那边也是同理的所以这里做的等价于

unk_140061560[i]^=aWllm[i%4];

后面基本上都一样的接着分析

写保护 注意开头的函数 其实就是刚刚异或的结果 v15赋值 然后调用异或结果 显然就是对 unk_140061560 SMC然后调用了后面就是验证了现在只差加密了

调试去看

看着难实际上合并合并是魔改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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include<stdio.h>
void decrypt(unsigned int* text, unsigned int* key) {
unsigned int delta = 0x9E3779B9;
unsigned int sum = delta * 32;
unsigned int v0, v1;
v0 = text[0];
v1 = text[1];

unsigned int k1, k2;
unsigned int a3, a4;
unsigned int s3, s4;
unsigned int s5, s6;
unsigned int a5, a6;

int cn = 1;

for (int i = 31; i >= 0; i--)
{
sum -= delta;
k1 = key[(i & 1) << cn++];
k2 = key[(sum & cn++) ^ 1];
s3 = sum << cn++;
s4 = sum >> cn--;
a3 = v1 << cn++;
a4 = v1 >> cn++;
s5 = sum * 5;
s6 = sum / 6;
v0 += ((k1 + k2 - a3) ^ (a4 + s5) ^ s6);
a5 = v0 * 5;
a6 = v0 / 6;
v1 += (k1 ^ (k2 + s3) ^ (s4 + a5 - a6));
cn = 1;
}
text[0] = v0;
text[1] = v1;
}
int main()
{
unsigned char* key = (unsigned char*)"wllm";
unsigned int returnkey[10];
unsigned char keyk[] = { 2,0,2,5 };
for (int i = 0; i < 4; i++)
{
returnkey[i] = key[i] * keyk[i];
}
unsigned int flag[8] = {
0xB40C4875, 0x1FA8F157, 0x9CBEE2DB, 0x5F8E5DD2, 0xBC593BB6, 0xF3F2381F, 0x46620137, 0xBC1873B1
};
for (int i = 0; i < 8; i +=2)
decrypt(&flag[i], returnkey);
for (int i = 0; i < 8; i++)
{
printf("%c", (flag[i] & 0xff));
printf("%c", (flag[i] >> 8) & 0xff);
printf("%c", (flag[i] >> 16) & 0xff);
printf("%c", (flag[i] >> 24) & 0xff);
}
return 0;
}

源码:

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
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>

#define FlagLen 32
//wllmctf{3nj0y_5mC_@nd_dR1nk_T3@}
unsigned int flag[] = { 0x76f759b0, 0x69469f34, 0x8188475f, 0x9bfe06fb, 0xbea2400, 0x260d6d28, 0xd6876753, 0x88c6111e, };

unsigned char encodebyte[] = {
0x3f, 0xe5, 0x38, 0x49, 0x67, 0x24, 0xe5, 0x21, 0x53, 0x64, 0x39, 0x3a, 0x3f, 0xed, 0x80, 0x85, 0x76, 0x6c, 0x6c, 0x25,
0xfc, 0x80, 0xd4, 0x69, 0x77, 0x6c, 0x6c, 0x25, 0x1c, 0xac, 0x6c, 0x25, 0xfc, 0xe1, 0x6c, 0x6f, 0x77, 0x6c, 0xe7, 0x69,
0x76, 0xe5, 0x29, 0x69, 0xcf, 0x68, 0x6c, 0x6d, 0x77, 0x24, 0x07, 0xad, 0x76, 0x24, 0xe7, 0xe0, 0x77, 0x6e, 0x6c, 0x6d,
0xfc, 0x68, 0x6d, 0xe4, 0x32, 0x48, 0xab, 0x28, 0x33, 0x6c, 0x6c, 0x6d, 0x77, 0xab, 0xe9, 0xe9, 0x77, 0x6c, 0x6c, 0xd4,
0x0e, 0x5b, 0xf2, 0xd5, 0x73, 0x6c, 0x6c, 0x6d, 0x3f, 0x07, 0xac, 0x6d, 0x3f, 0xe7, 0xe1, 0x65, 0x75, 0x6c, 0x6c, 0xe6,
0x73, 0x6d, 0xe5, 0xe8, 0xd3, 0x6c, 0x6c, 0x6d, 0xcf, 0x68, 0x6c, 0x6d, 0x77, 0x24, 0x07, 0xad, 0x76, 0x24, 0xe7, 0xe0,
0x7f, 0x6e, 0x6c, 0x6d, 0xfc, 0x68, 0x6d, 0xe4, 0xf2, 0xa8, 0x6c, 0x6d, 0x77, 0xd4, 0x68, 0x6d, 0x77, 0x6c, 0x24, 0x06,
0xb7, 0x6e, 0x24, 0xe6, 0xfa, 0x64, 0x6e, 0x6d, 0x77, 0xe7, 0x68, 0x6c, 0xfe, 0xe9, 0x88, 0x6d, 0x77, 0x6c, 0xd4, 0x69,
0x77, 0x6c, 0x6c, 0x25, 0x1c, 0xac, 0x6f, 0x25, 0xfc, 0xe1, 0x64, 0x6f, 0x77, 0x6c, 0xe7, 0x69, 0x76, 0xe5, 0xe9, 0x69,
0x76, 0x6c, 0x6c, 0xaa, 0x32, 0x08, 0x6c, 0x6d, 0x77, 0x6c, 0x87, 0x65, 0xfc, 0x29, 0x08, 0x92, 0xb7, 0xe5, 0x29, 0x09,
0xf4, 0x11, 0x08, 0x4d, 0x04, 0x1e, 0xe7, 0xe8, 0xf3, 0x6c, 0x6c, 0x6d, 0xfc, 0x21, 0x28, 0x6e, 0xbf, 0xe7, 0xad, 0xe4,
0x32, 0x28, 0xe7, 0x28, 0x53, 0xad, 0x8c, 0x69, 0x74, 0xe9, 0xc8, 0x6d, 0x77, 0x6c, 0xe7, 0x20, 0x33, 0xe7, 0x39, 0x49,
0x74, 0xbd, 0xe7, 0xa7, 0x44, 0xad, 0xe7, 0x20, 0x53, 0xad, 0x85, 0x68, 0x74, 0xe1, 0xa8, 0x6d, 0x77, 0x6c, 0x5f, 0xac,
0xfc, 0x21, 0x68, 0x6e, 0xbf, 0xe7, 0xad, 0xe4, 0x32, 0x68, 0xe7, 0x28, 0x73, 0xad, 0x8c, 0x69, 0x74, 0xe9, 0x88, 0x6d,
0x77, 0x6c, 0xe7, 0x20, 0x33, 0xe7, 0x39, 0x69, 0x74, 0xbd, 0xe7, 0xa7, 0x44, 0xad, 0xe7, 0x20, 0x73, 0xad, 0x85, 0x68,
0x74, 0xe1, 0x68, 0x6c, 0x77, 0x6c, 0x5f, 0xac, 0xfc, 0x21, 0x48, 0x6e, 0xbf, 0xe7, 0xad, 0xe4, 0x32, 0x48, 0x87, 0xed,
0xcf, 0x68, 0x6c, 0x6d, 0x77, 0x24, 0x07, 0xad, 0x77, 0x24, 0xe7, 0xe0, 0x77, 0x6e, 0x6c, 0x6d, 0xfc, 0x39, 0x68, 0xe4,
0x63, 0x6d, 0xd4, 0x69, 0x77, 0x6c, 0x6c, 0x25, 0x1c, 0xac, 0x6d, 0x25, 0xfc, 0xe1, 0x6c, 0x6f, 0x77, 0x6c, 0xe7, 0x38,
0x53, 0xe5, 0x78, 0x6c, 0x3f, 0xe1, 0xc9, 0x85, 0x76, 0x6c, 0x6c, 0x32, 0x2a, 0xaf,
};
typedef struct {
char* str;
int len;
unsigned int* key;
unsigned int* tstr;
}Input, * pInput;
typedef void (*ptea)(unsigned int* a, unsigned int* b);
unsigned char* key = "wllm";
unsigned char* Acode;
ptea pCode;
int smcmain()
{
int size = sizeof(encodebyte);
Acode = (unsigned char*)malloc(size);
for (int i = 0; i < size; i++)
{
Acode[i] = encodebyte[i] ^ key[i % 4];
}
PDWORD oldProtect;
if (!VirtualProtect(Acode, size, PAGE_EXECUTE_READWRITE, &oldProtect))
{
return 0;
}
pCode = (ptea)Acode;
return 1;
}

unsigned int* makekey()
{
unsigned int* returnkey = (unsigned int*)malloc(sizeof(int) * 4);
unsigned char keyk[] = { 2,0,2,5 };
for (int i = 0; i < 4; i++)
{
returnkey[i] = key[i] * keyk[i];
}
return returnkey;
}

int cmp(unsigned int a, unsigned int b)
{
return a != b;
}

int main()
{
pInput Sinput = (pInput)malloc(sizeof(Input));
Sinput->len = 0;
char* input = (char*)malloc(FlagLen);
if (printf("This is a challenge about patience\nHave you found 'it':") && scanf("%s", input))
{
int len = strlen(input);
if (len == FlagLen)
{
Sinput->str = (char*)malloc(FlagLen);
memcpy(Sinput->str, input, FlagLen);
Sinput->len = FlagLen;
}
}

if (Sinput->len)
{
switch (smcmain())
{
case 1:
Sinput->key = makekey();
break;
default:
printf("Something wrong!@_@");
return 0;
}
}
else
{
printf("You're wrong in the first step!");
return 0;
}
int i = 0;

do
{
pCode(&Sinput->str[i * 8], Sinput->key);
i++;
} while (i < Sinput->len / 8);

for (Sinput->tstr = (unsigned int*)Sinput->str, i = 0; i < 8 ;i++)
{
if (cmp(Sinput->tstr[i], flag[i]))
{
printf("胜利就在眼前!加油特种兵!");
return 0;
}
}
printf("wow!!!!!!!YOUR FLAG IS %s", input);
return 0;
}

4-3 死

考点:

smc+tea

出题思路:

异常+rc4+模拟汇编执行

wp:

源码:

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
#include<Windows.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include <time.h>
#include<iostream>
using namespace std;

string flag = "wllmctf{this_is_fake_flag_it_just_told_you_right_len_good_luck~~~}";
unsigned char realflag[66] = { 0x24, 0xdf, 0x6a, 0xd5, 0xb6, 0x96, 0x1d, 0xd7, 0x69, 0xa6, 0x21, 0x4c, 0x97, 0x63, 0x7a, 0xec, 0xe6, 0xb5, 0xad, 0x11, 0x57, 0x93, 0x9f, 0xb7, 0x1a, 0xd6, 0x76, 0x8b, 0x52, 0xe4, 0x75, 0xa6, 0xd7, 0x34, 0x86, 0xe0, 0xf7, 0xcc, 0xa8, 0x96, 0xf3, 0x4e, 0x61, 0x88, 0x9f, 0xbd, 0x4c, 0x62, 0x8e, 0xe5, 0xe0, 0xb2, 0x8d, 0x48, 0x6b, 0x16, 0x95, 0xbb, 0x7d, 0x5a, 0x04, 0x65, 0xa9, 0xf4, 0x20, 0xc3 };

unsigned char Qinput[66] = { 0 };

int main()
{
string input;
string key = "wllm2025";
try {
cout << "input:";
cin >> input;
//wllmctf{ez_Exception_but_so_hard_re_analyze_you_are_realy_good!!!}
if (input.length() == flag.length())
{
throw "exception!";
}
cout << "wrong length!" << endl;
return 0;

}
catch (const char* msg)
{
unsigned char stack[0x201] = { 0 };
unsigned char* sp = stack;
unsigned char* bp = &stack[0x200];
unsigned int zf;
unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
int newinput = 0x120;
int ilen = 0x119;
int klen = 0x115;
int q = 0x111;
int j = 0x107;
int i = 0x103;
int box = 0x0;
//i = 0;
*(int*)(bp - i) = 0;
//for(;i<0x100;i++)
// box[i] = i;
goto loc169CA;
loc1698C:
ax = *(int*)(bp - i);

ax++;

*(int*)(bp - i) = ax;
loc169CA:
zf = (*(int*)(bp - i) == 0x100);

if (zf == 1)
goto loc169ED;

ax = *(bp - i);

cx = *(bp - i);

*(bp - box - ax) = cx;
goto loc1698C;
loc169ED:

//i=0 j=0
*(int*)(bp - i) = 0;
*(int*)(bp - j) = 0;
*(int*)(bp - klen) = key.length();
//for (i = 0; i < 256; i++)
// j = (j + s[i] + key[i % key.length()]) % 256;
// swap(s[i], s[j]);
goto loc16A07;
loc169F9:
ax = *(int*)(bp - i);

ax++;

*(int*)(bp - i) = ax;
loc16A07:
zf = (*(int*)(bp - i) == 0x100);

if (zf == 1)
goto loc16AC7;

ax = *(bp - i); //ax = i

ax = *(bp - ax - box); //ax = box[i]

cx = *(bp - j); //cx = j

cx += ax; //cx = j + box[i]

ax = cx; //ax = j + box[i]

cx = *(bp - i); //cx = i

cx %= *(bp - klen); //cx = i % keylen

bx = key[cx]; //bx = key[i % keylen]

cx = ax; //cx = j + box[i]

bx += ax; //bx = j + box[i] + key[i % keylen]

ax = bx; //ax = j + box[i] + key[i % keylen]

ax %= 0x100; //ax = (j + box[i] + key[i % keylen]) % 256

*(bp - j) = ax; //j = (j + box[i] + key[i % keylen]) % 256

ax = *(bp - i); //ax = i

bx = *(bp - ax - box); //bx = box[i]

cx = *(bp - j); //cx = j

dx = *(bp - cx - box); //dx = box[j]

*(bp - ax - box) = dx; //box[i] = box[j]

*(bp - cx - box) = bx; //box[j] = box[i]

goto loc169F9;

loc16AC7:

//i=0 j=0 q=0
//for (q = 0; q < input.length(); q++)
// i = (i + 1) % 256;
// j = (j + s[i]) % 256;
// swap(s[i], s[j]);
// t = (s[i] + s[j]) % 256;
// input[q] ^= s[t];

*(int*)(bp - i) = 0;
*(int*)(bp - j) = 0;
*(int*)(bp - q) = 0;
*(int*)(bp - ilen) = input.length();

goto loc16B01;

loc16AF3:
ax = *(int*)(bp - q);

ax++;

*(int*)(bp - q) = ax;

loc16B01:
zf = (*(int*)(bp - q) == *(int*)(bp - ilen));

if (zf == 1)
goto loc16C16;

ax = *(bp - i); //ax = i

ax++; //i++

ax %= 0x100; //i%256

*(bp - i) = ax; //i = (i + 1) % 256

ax = *(bp - i); //ax = i;

ax = *(bp - ax - box); //ax = box[i]

cx = *(bp - j); //cx = j

cx += ax; //cx = j + box[i]

cx %= 0x100; //cx = (j + box[i]) % 256

*(bp - j) = cx; //j = (j + box[i]) % 256

ax = *(bp - i); //ax = i

bx = *(bp - ax - box); //bx = box[i]

cx = *(bp - j); //cx = j

dx = *(bp - cx - box); //dx = box[j]

*(bp - ax - box) = dx; //box[i] = box[j]

*(bp - cx - box) = bx; //box[j] = box[i]

bx += dx; //bx = box[i] + box[j]

bx %= 0x100; //bx = (box[i] + box[j]) % 256

ax = bx; //ax = (box[i] + box[j]) % 256

ax = *(bp - ax - box); //ax = box[(box[i] + box[j]) % 256]

cx = *(bp - q); //cx = q;

cx = input[cx]; //cx = input[q];

ax ^= cx; //ax = input[q] ^ box[(box[i] + box[j]) % 256]

cx = *(bp - q); //cx = q;

*(bp - cx - newinput) = ax; //newinput[q] = input[q] ^ box[(box[i] + box[j]) % 256]
goto loc16AF3;
loc16C16:

//i = 0;
*(int*)(bp - i) = 0;
//for(;i<0x100;i++)
// Qinput[i] = newinput[i];
goto loc16666;
loc16114:
ax = *(int*)(bp - i);

ax++;

*(int*)(bp - i) = ax;
loc16666:
zf = (*(int*)(bp - i) == *(int*)(bp - ilen));

if (zf == 1)
goto goodend;

ax = *(bp - i);

cx = *(bp - i);

zf = (*(bp - ax - newinput) == *(realflag + cx));

if (zf == 0)
goto badend;
goto loc16114;
goodend:
cout << "gooooooooooooooooooooooooooooooooooooooood!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
return 0;
badend:
cout << "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
return 0;
}
return 0;
}