比赛那几天忙了做各种各样的课设,加上ciscn刚打完不太想动,所以就纯看看题了(为自己菜找借口)现在缓过来了,就做一下复现吧。

Reserve

Snake

打开软件发现是pygame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PS C:\Users\Derrick Li\Desktop> python pyinstxtractor.py snake.exe
[+] Processing snake.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.8
[+] Length of package: 12997948 bytes
[+] Found 121 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_pkgres.pyc
[+] Possible entry point: pyi_rth_inspect.pyc
[+] Possible entry point: pyi_rth_pkgutil.pyc
[+] Possible entry point: snack.pyc
[!] Warning: This script is running in a different Python version than the one used to build the executable.
[!] Please run this script in Python 3.8 to prevent extraction errors during unmarshalling
[!] Skipping pyz extraction
[+] Successfully extracted pyinstaller archive: snake.exe

You can now use a python decompiler on the pyc files within the extracted directory
PS C:\Users\Derrick Li\Desktop>

用在线pyc反编译网站分析
https://www.lddgo.net/string/pyc-compile-decompile

snake.pyc

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

import pygame
import random
import key

def initialize(key):
key_length = len(key)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i] = S[j]
S[j] = S[i]
return S


def generate_key_stream(S, length):
i = 0
j = 0
key_stream = []
for _ in range(length):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i] = S[j]
S[j] = S[i]
key_stream.append(S[(S[i] + S[j]) % 256])
return key_stream


def decrypt(data, key):
S = initialize(key)
key_stream = generate_key_stream(S, len(data))
decrypted_data = None((lambda .0 = None: [ i ^ data[i] ^ key_stream[i] for i in .0 ])(range(len(data))))
return decrypted_data

pygame.init()
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
SNAKE_SIZE = 20
SNAKE_SPEED = 20
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('贪吃蛇')
font = pygame.font.Font(None, 36)
snake = [
(200, 200),
(210, 200),
(220, 200)]
snake_direction = (SNAKE_SPEED, 0)
food = ((random.randint(0, WINDOW_WIDTH - SNAKE_SIZE) // SNAKE_SIZE) * SNAKE_SIZE, (random.randint(0, WINDOW_HEIGHT - SNAKE_SIZE) // SNAKE_SIZE) * SNAKE_SIZE)
key_bytes = bytes((lambda .0: [ ord(char) for char in .0 ])(key.xor_key))
data = [
101,
97,
39,
125,
218,
172,
205,
3,
235,
195,
72,
125,
89,
130,
103,
213,
120,
227,
193,
67,
174,
71,
162,
248,
244,
12,
238,
92,
160,
203,
185,
155]
decrypted_data = decrypt(bytes(data), key_bytes)
running = True
if running:
window.fill(BLACK)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN or event.key == pygame.K_UP:
snake_direction = (0, -SNAKE_SPEED)
elif event.key == pygame.K_DOWN:
snake_direction = (0, SNAKE_SPEED)
elif event.key == pygame.K_LEFT:
snake_direction = (-SNAKE_SPEED, 0)
elif event.key == pygame.K_RIGHT:
snake_direction = (SNAKE_SPEED, 0)
continue
snake_head = (snake[0][0] + snake_direction[0], snake[0][1] + snake_direction[1])
snake.insert(0, snake_head)
snake.pop()
if snake[0] == food:
food = ((random.randint(0, WINDOW_WIDTH - SNAKE_SIZE) // SNAKE_SIZE) * SNAKE_SIZE, (random.randint(0, WINDOW_HEIGHT - SNAKE_SIZE) // SNAKE_SIZE) * SNAKE_SIZE)
snake.append(snake[-1])
if snake[0][0] < 0 and snake[0][0] >= WINDOW_WIDTH and snake[0][1] < 0 and snake[0][1] >= WINDOW_HEIGHT or snake[0] in snake[1:]:
running = False
for segment in snake:
pygame.draw.rect(window, WHITE, (segment[0], segment[1], SNAKE_SIZE, SNAKE_SIZE))
pygame.draw.rect(window, RED, (food[0], food[1], SNAKE_SIZE, SNAKE_SIZE))
score_text = font.render(f'''Score: {len(snake)}''', True, WHITE)
speed_text = font.render(f'''Speed: {SNAKE_SPEED}''', True, WHITE)
window.blit(score_text, (10, 10))
window.blit(speed_text, (10, 40))
score = len(snake)
if score >= 9999:
flag_text = font.render('Flag: ' + decrypted_data.decode(), True, WHITE)
window.blit(flag_text, (10, 70))
pygame.display.update()
pygame.time.Clock().tick(10)
continue
pygame.quit()

代码中写道是流密码加密
使用python3.8重新跑一遍脚本可以发现key.pyc在PYZ-00.pyz_extracted目录下

xor_key = ‘V3rY_v3Ry_Ez’

这边解密甚至可以直接把加密的部分拿来用

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
def initialize(key):
key_length = len(key)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i]
return S

def generate_key_stream(S, length):
i = 0
j = 0
key_stream = []
for _ in range(length):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
key_stream.append(S[(S[i] + S[j]) % 256])
return key_stream

def decrypt(data, key):
S = initialize(key)
key_stream = generate_key_stream(S, len(data))
decrypted_data = [i ^ data[i] ^ key_stream[i] for i in range(len(data))]
for i in decrypted_data:
print(chr(i), end='')
return decrypted_data


key = [ord(c) for c in "V3rY_v3Ry_Ez"]
data = [
101, 97, 39, 125, 218, 172, 205, 3, 235, 195, 72, 125, 89, 130, 103, 213,
120, 227, 193, 67, 174, 71, 162, 248, 244, 12, 238, 92, 160, 203, 185, 155
]
decrypted = decrypt(data, key)

flag{KMLTz3lT_MePUDa7A_P5LpzCBT}