litctf 逆向wp

First Post:

Last Update:

世界上最棒的程序员

ida打开程序就看到了

ez_XOR

输入一个字符串,与3*3惊醒异或,之后与已知密文比较

exp:

1
2
3
4
5
char aa[] = "E`}J]OrQF[V8zV:hzpV}fVF[t";
for (int i = 0; i < 26; i++)
{
printf("%c", aa[i] ^ 9);
}

enbase64

ida打开,直接动调输入的地方,判断长度之后有两个函数,第一个函数先把表换了之后进行base加密,第二个函数是与密文比较的,动调到换表处,dump出新的表:gJ1BRjQie/FIWhEslq7GxbnL26M4+HXUtcpmVTKaydOP38of5v90ZSwrkYzCAuND,解密即可

snake

是一个pyc文件,但是文件头被改了,根据文件名提示是python3.7版本的,所以手动修改一下文件头(42 0D 0D 0A)即可正常反编译

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

"""贪吃蛇"""
import random, sys, time, pygame
from pygame.locals import *
from collections import deque
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 480
SIZE = 20
LINE_WIDTH = 1
SCOPE_X = (
0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)
FOOD_STYLE_LIST = [
(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]
LIGHT = (100, 100, 100)
DARK = (200, 200, 200)
BLACK = (0, 0, 0)
RED = (200, 30, 30)
BGCOLOR = (40, 40, 60)

def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
imgText = font.render(text, True, fcolor)
screen.blit(imgText, (x, y))


def init_snake():
snake = deque()
snake.append((2, SCOPE_Y[0]))
snake.append((1, SCOPE_Y[0]))
snake.append((0, SCOPE_Y[0]))
return snake


def create_food(snake):
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
while (food_x, food_y) in snake:
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])

return (
food_x, food_y)


def get_food_style():
return FOOD_STYLE_LIST[random.randint(0, 2)]


def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('贪吃蛇')
font1 = pygame.font.SysFont('SimHei', 24)
font2 = pygame.font.Font(None, 72)
fwidth, fheight = font2.size('GAME OVER')
b = True
snake = init_snake()
food = create_food(snake)
food_style = get_food_style()
pos = (1, 0)
game_over = True
start = False
score = 0
orispeed = 0.5
speed = orispeed
last_move_time = None
pause = False
while 1:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()

screen.fill(BGCOLOR)
for x in range(SIZE, SCREEN_WIDTH, SIZE):
pygame.draw.line(screen, BLACK, (x, SCOPE_Y[0] * SIZE), (x, SCREEN_HEIGHT), LINE_WIDTH)

for y in range(SCOPE_Y[0] * SIZE, SCREEN_HEIGHT, SIZE):
pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), LINE_WIDTH)

curTime = game_over or time.time()
if curTime - last_move_time > speed and not pause:
b = True
last_move_time = curTime
next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
if next_s == food:
snake.appendleft(next_s)
score += food_style[0]
speed = orispeed - 0.03 * (score // 100)
food = create_food(snake)
food_style = get_food_style()
else:
if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1]:
if SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1]:
if next_s not in snake:
snake.appendleft(next_s)
snake.pop()
else:
game_over = True
if not game_over:
pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)
for s in snake:
pygame.draw.rect(screen, DARK, (s[0] * SIZE + LINE_WIDTH, s[1] * SIZE + LINE_WIDTH,
SIZE - LINE_WIDTH * 2, SIZE - LINE_WIDTH * 2), 0)

print_text(screen, font1, 30, 7, f"速度: {score // 100}")
print_text(screen, font1, 450, 7, f"得分: {score}")
if score > 1000:
flag = [
30, 196,
52, 252, 49, 220, 7, 243,
3, 241, 24, 224, 40, 230,
25, 251, 28, 233, 40, 237,
4, 225, 4, 215, 40, 231,
22, 237, 14, 251, 10, 169]
for i in range(0, len(flag), 2):
flag[i], flag[i + 1] = flag[i + 1] ^ 136, flag[i] ^ 119

print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, bytes(flag).decode(), RED)
pygame.display.update()
if game_over:
if start:
print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)
pygame.display.update()


if __name__ == '__main__':
main()

score>1000后,会对flag进行一点操作,直接执行那一段代码即可,输出就是flag

程序和人有一个能跑就行

首先很明显是一个rc4加密,密文也给出。但解密出来的是假的flag,并且输出right?这个问号说明有一部分逻辑被应该是被隐藏起来了,看汇编流程图可以发现右边有一大块指令,隐藏了真正的密文,密钥没变,再解密一下即可

debase64

主要逻辑就是那个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
string table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int main()
{

int key[4][3] = { 0x46,0xed,0x18,0x96,0x56,0x9e,0xd2,0x72,0xb2,0xb3,0x80,0x70 };
for (int cnt = 0; cnt < 4; cnt++)
{
for (int i = 0; i <= 62; i++)
{
for (int j = 0; j <= 62; j++)
{
for (int k = 0; k <= 62; k++)
{
for (int l = 0; l <= 62; l++)
{
int temp1 = ((4 * i) | (j >> 4) & 3) & 0xff;
int temp2 = ((16 * j) | (k >> 2)) & 0xff;
int temp3 = ((k << 6) | l) & 0xff;

if (temp1 == key[cnt][0] && temp2 == key[cnt][1] && temp3 == key[cnt][2]) {
cout << table[l] << table[k] << table[j] << table[i];
break;
}
}
}
}
}
}
}

需要注意的是最后四个字符,hint给出的是后三个都是===,那么只需要再猜一个字符就行,总体的md5值也给出,按道理应该再写个python脚本爆一下,但是我当时做的时候感觉来了,看这个flag样子估计最后一位是个数字,一下就猜对了

For Aiur

python打包的,解包,pyc反编译,可以主函数里引入了check的包,很明显与flag有关,引入的包都在PYZ-00.pyz_extracted这个文件夹下,在里面找到check的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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8

enc = [
98,
77,
94,
91,
92,
107,
125,
66,
87,
70,
113,
92,
83,
70,
85,
81,
19,
21,
109,
99,
87,
107,
127,
65,
65,
64,
109,
87,
93,
90,
65,
64,
64,
65,
81,
3,
109,
85,
86,
80,
91,
64,
91,
91,
92,
0,
94,
107,
66,
77,
94,
91,
92,
71]
lis = []

def check(num):
flag = 'LitCTF{'
if num % 2 == 0 and num % 4 == 0 and num % 6 == 0 and num % 8 == 0 and num % 12 == 0 and num % 13 == 11:
k = str(num)
for i in range(len(enc)):
flag += chr(ord(k[i % len(k)]) ^ enc[i])
lis.append(ord(k[i % len(k)]) ^ enc[i])
flag += '}'
imread = imread
imshow = imshow
namedWindow = namedWindow
WINDOW_NORMAL = WINDOW_NORMAL
FONT_HERSHEY_SIMPLEX = FONT_HERSHEY_SIMPLEX
getTickCount = getTickCount
getTickFrequency = getTickFrequency
putText = putText
LINE_AA = LINE_AA
waitKey = waitKey
getTextSize = getTextSize
resize = resize
moveWindow = moveWindow
IMREAD_UNCHANGED = IMREAD_UNCHANGED
destroyAllWindows = destroyAllWindows
import cv2
uint8 = uint8
zeros = zeros
import numpy
img = zeros((200, 20000, 3), uint8)
img.fill(255)
text = flag
font = FONT_HERSHEY_SIMPLEX
pos = (50, 120)
color = (0, 0, 0)
thickness = 2
putText(img, text, pos, font, 1, color, thickness, LINE_AA)
imshow('flag', img)
waitKey(0)
destroyAllWindows()

num值是24,直接运行那一段即可