前两天有别的比赛,没怎么打这场,第二天晚上才 开始重点做。第三天晚上九点疯狂上分,攒了三天的flag倾泻而出,得分趋势变成了竖线。队友们TQL~
reverse
签到
ida直接找到flag
zzzz3333333
38*38的矩阵,正则提取系数,然后matlab解。
提取系数:
code = '''int __cdecl sub_401500(char *a1)
{
int result; // eax
if ( 48 * a1[7]
+ 64 * a1[5]
+ 4 * a1[4]
+ 59 * a1[1]
+ 85 * *a1
+ 76 * a1[2]
+ 65 * a1[3]
+ 50 * a1[6]
+ 11 * a1[8]
+ 66 * a1[9] != 44858 )
return 0;
if ( 96 * a1[7]
+ 6 * a1[6]
+ 97 * a1[4]
+ 71 * a1[1]
+ 87 * *a1
+ 26 * a1[2]
+ 80 * a1[3]
+ 100 * a1[5]
+ 20 * a1[8]
+ 46 * a1[9] != 54177 )
return 0;
if ( 82 * a1[8]
+ 29 * a1[7]
+ 54 * a1[4]
+ 22 * a1[1]
+ 27 * *a1
+ 92 * a1[2]
+ 9 * a1[3]
+ 35 * a1[5]
+ 36 * a1[6]
+ 90 * a1[9] != 40412 )
return 0;
if ( 60 * a1[7]
+ 31 * a1[5]
+ 47 * *a1
+ 32 * a1[1]
+ 55 * a1[2]
+ 17 * a1[3]
+ 70 * a1[4]
+ 10 * a1[6]
+ 34 * a1[8]
+ 25 * a1[9] != 32362 )
return 0;
if ( 53 * a1[7]
+ 89 * a1[6]
+ 13 * a1[4]
+ 72 * a1[3]
+ 49 * a1[1]
+ 18 * *a1
+ 61 * a1[2]
+ 3 * a1[5]
+ 67 * a1[8]
+ 15 * a1[9] != 37176 )
return 0;
if ( 78 * a1[8]
+ 38 * a1[5]
+ 69 * a1[2]
+ 77 * *a1
+ 16 * a1[1]
+ 99 * a1[3]
+ 33 * a1[4]
+ 8 * a1[6]
+ 5 * a1[7]
+ 91 * a1[9] != 42742 )
return 0;
if ( 62 * a1[8]
+ 52 * a1[7]
+ 58 * a1[2]
+ 45 * a1[1]
+ 40 * *a1
+ 51 * a1[3]
+ 24 * a1[4]
+ 95 * a1[5]
+ 19 * a1[6]
+ 94 * a1[9] != 47553 )
return 0;
if ( 28 * a1[8]
+ 63 * a1[7]
+ 12 * a1[6]
+ 57 * a1[4]
+ 30 * a1[3]
+ 42 * a1[2]
+ a1[1]
+ 88 * *a1
+ 83 * a1[5]
+ 73 * a1[9] != 41059 )
return 0;
if ( 41 * a1[8]
+ 93 * a1[6]
+ 68 * a1[5]
+ 98 * a1[2]
+ 75 * a1[1]
+ 39 * *a1
+ 86 * a1[3]
+ 14 * a1[4]
+ 23 * a1[7]
+ 7 * a1[9] != 43919 )
return 0;
if ( 56 * a1[8] + 74 * a1[5] + 43 * a1[4] + 84 * a1[3] + 44 * a1[2] + 37 * *a1 + 81 * a1[1] + 2 * a1[6] + 21 * a1[9] != 35933 )
return 0;
if ( 36 * a1[16]
+ 98 * a1[14]
+ 79 * a1[10]
+ 97 * a1[11]
+ 33 * a1[12]
+ 60 * a1[15]
+ 24 * a1[17]
+ 78 * a1[18]
+ 72 * a1[19] != 47783 )
return 0;
if ( 74 * a1[17]
+ 39 * a1[16]
+ 51 * a1[15]
+ 8 * a1[14]
+ 77 * a1[13]
+ 69 * a1[12]
+ 16 * a1[11]
+ 73 * a1[10]
+ 64 * a1[18]
+ 28 * a1[19] != 44266 )
return 0;
if ( 47 * a1[18]
+ 52 * a1[17]
+ 53 * a1[16]
+ 99 * a1[15]
+ a1[14]
+ 38 * a1[13]
+ 67 * a1[12]
+ 45 * a1[11]
+ 61 * a1[10]
+ 66 * a1[19] != 44988 )
return 0;
if ( 5 * a1[17]
+ 4 * a1[13]
+ 89 * a1[12]
+ 31 * a1[10]
+ 11 * a1[11]
+ 93 * a1[14]
+ 3 * a1[15]
+ 84 * a1[16]
+ 65 * a1[18]
+ 100 * a1[19] != 46698 )
return 0;
if ( 82 * a1[16]
+ 62 * a1[13]
+ 58 * a1[12]
+ 42 * a1[11]
+ 86 * a1[10]
+ 85 * a1[14]
+ 27 * a1[15]
+ 43 * a1[17]
+ 15 * a1[18]
+ 26 * a1[19] != 45689 )
return 0;
if ( 22 * a1[16]
+ 34 * a1[13]
+ 2 * a1[12]
+ 23 * a1[11]
+ 46 * a1[10]
+ 29 * a1[14]
+ 48 * a1[15]
+ 35 * a1[17]
+ 19 * a1[18]
+ 70 * a1[19] != 27224 )
return 0;
if ( 96 * a1[18]
+ 81 * a1[17]
+ 92 * a1[15]
+ 54 * a1[14]
+ 94 * a1[11]
+ 57 * a1[10]
+ 55 * a1[12]
+ 80 * a1[13]
+ 71 * a1[16]
+ 25 * a1[19] != 58395 )
return 0;
if ( 13 * a1[17]
+ 75 * a1[13]
+ 21 * a1[11]
+ 59 * a1[10]
+ 56 * a1[12]
+ 50 * a1[14]
+ 41 * a1[15]
+ 44 * a1[16]
+ 40 * a1[18]
+ 49 * a1[19] != 40625 )
return 0;
if ( 12 * a1[16]
+ 91 * a1[14]
+ 88 * a1[13]
+ 87 * a1[12]
+ 68 * a1[10]
+ 7 * a1[11]
+ 83 * a1[15]
+ 20 * a1[17]
+ 32 * a1[18]
+ 37 * a1[19] != 45008 )
return 0;
if ( 10 * a1[17]
+ 18 * a1[16]
+ 9 * a1[15]
+ 6 * a1[14]
+ 76 * a1[10]
+ 14 * a1[11]
+ 17 * a1[12]
+ 90 * a1[13]
+ 63 * a1[18]
+ 30 * a1[19] != 32400 )
return 0;
if ( 83 * a1[26]
+ 45 * a1[25]
+ 4 * a1[24]
+ 48 * a1[22]
+ 38 * a1[20]
+ 22 * a1[21]
+ 7 * a1[23]
+ 62 * a1[27]
+ 25 * a1[28]
+ 85 * a1[29] != 37450 )
return 0;
if ( 14 * a1[28]
+ 86 * a1[26]
+ 93 * a1[25]
+ 42 * a1[24]
+ 94 * a1[21]
+ 70 * a1[20]
+ 58 * a1[22]
+ 40 * a1[23]
+ 76 * a1[27]
+ 11 * a1[29] != 48740 )
return 0;
if ( 72 * a1[28]
+ 46 * a1[26]
+ 92 * a1[25]
+ 98 * a1[24]
+ 55 * a1[23]
+ 80 * a1[20]
+ 32 * a1[21]
+ 12 * a1[22]
+ 84 * a1[27]
+ 27 * a1[29] != 53599 )
return 0;
if ( 53 * a1[27]
+ 49 * a1[23]
+ 99 * a1[22]
+ 41 * a1[20]
+ 20 * a1[21]
+ 87 * a1[25]
+ 81 * a1[26]
+ 71 * a1[28]
+ 73 * a1[29] != 52140 )
return 0;
if ( 68 * a1[28]
+ 61 * a1[21]
+ 28 * a1[20]
+ 91 * a1[22]
+ 31 * a1[23]
+ 67 * a1[24]
+ 15 * a1[25]
+ 44 * a1[26]
+ 6 * a1[27]
+ 64 * a1[29] != 44449 )
return 0;
if ( 9 * a1[27]
+ 60 * a1[25]
+ 96 * a1[23]
+ 17 * a1[20]
+ 10 * a1[21]
+ 29 * a1[22]
+ 5 * a1[24]
+ 100 * a1[26]
+ 21 * a1[28]
+ 69 * a1[29] != 35276 )
return 0;
if ( 59 * a1[26]
+ 66 * a1[25]
+ 23 * a1[22]
+ 8 * a1[20]
+ 24 * a1[21]
+ 16 * a1[23]
+ 56 * a1[24]
+ 90 * a1[27]
+ 36 * a1[28]
+ 39 * a1[29] != 35577 )
return 0;
if ( 35 * a1[25]
+ 65 * a1[23]
+ 63 * a1[22]
+ 75 * a1[20]
+ 88 * a1[21]
+ 33 * a1[24]
+ 82 * a1[26]
+ 18 * a1[27]
+ a1[28]
+ 37 * a1[29] != 42004 )
return 0;
if ( 54 * a1[28]
+ 57 * a1[27]
+ 43 * a1[24]
+ 74 * a1[21]
+ 19 * a1[20]
+ 51 * a1[22]
+ 13 * a1[23]
+ 79 * a1[25]
+ 3 * a1[26]
+ 26 * a1[29] != 35802 )
return 0;
if ( 34 * a1[28]
+ 50 * a1[27]
+ 78 * a1[26]
+ 52 * a1[25]
+ 77 * a1[24]
+ 95 * a1[23]
+ 30 * a1[22]
+ 89 * a1[20]
+ 2 * a1[21]
+ 97 * a1[29] != 54527 )
return 0;
if ( 46 * a1[36] + 73 * a1[34] + 15 * a1[30] + 16 * a1[31] + 41 * a1[32] + 94 * a1[33] + 28 * a1[35] + 45 * a1[37] != 34469 )
return 0;
if ( 82 * a1[36] + 10 * a1[32] + 48 * a1[31] + 65 * a1[30] + 6 * a1[33] + 30 * a1[34] + 27 * a1[35] + 32 * a1[37] != 31558 )
return 0;
if ( 62 * a1[36] + 39 * a1[35] + 36 * a1[33] + 97 * a1[31] + 52 * a1[30] + 70 * a1[32] + 13 * a1[34] + 66 * a1[37] != 41820 )
return 0;
if ( 44 * a1[34] + 42 * a1[33] + 78 * a1[32] + 83 * a1[31] + 96 * a1[30] + 4 * a1[35] + 9 * a1[36] + 51 * a1[37] != 38668 )
return 0;
if ( 79 * a1[36] + 37 * a1[33] + 92 * a1[30] + 18 * a1[31] + 86 * a1[32] + 7 * a1[34] + 95 * a1[37] != 45530 )
return 0;
if ( 71 * a1[36] + 43 * a1[35] + 57 * a1[34] + 49 * a1[33] + 88 * a1[32] + 61 * a1[30] + 24 * a1[31] + 91 * a1[37] != 51396 )
return 0;
if ( 34 * a1[36] + 75 * a1[35] + 35 * a1[32] + 23 * a1[30] + 3 * a1[31] + 53 * a1[33] + 14 * a1[34] + 47 * a1[37] != 28874 )
return 0;
if ( 22 * a1[36] + 84 * a1[35] + 26 * a1[34] + 90 * a1[33] + 99 * a1[30] + 98 * a1[31] + 25 * a1[32] + a1[37] != 38231 )
return 0;
}'''
code = code.replace('*a1', 'a1[0]')
import re
l = []
right = []
r = re.finditer(r'if.+?;', code, re.S)
for line in r:
tmp = [0] * 38
rr = re.finditer(r'(\d+?) \* a1\[(\d+?)\]', line.group())
for i in rr:
a, b = int(i.group(1)), int(i.group(2))
tmp[b] = a
_rr = re.search(r'\+ a1\[(\d+?)\]', line.group())
if _rr:
a, b = 1, int(_rr.group(1))
tmp[b] = a
l.append(tmp)
rrr = re.search(r'!\= (\d+)', line.group())
right.append(int(rrr.group(1)))
for i in l:
print(str(i)[1:-1] + ';')
print()
print(str(right).replace(',', ';'))
matlab部分截图:
能用matlab解的最好不要用z3。z3基本靠爆破,matlab解线性方程是直接调用数学公式,不是一个时间复杂度哦。
奇怪的exe
pyinstaller打包的python程序,用pyinstxtractor.py解包,uncomlyle6提取python代码。
源码:
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: 3.py
# Compiled at: 2020-12-24 10:52:17
# Size of source mod 2**32: 14 bytes
import base64
from binascii import *
c = [35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
print('please input your flag:')
key = input()
a = base64.b64encode(key.swapcase().encode('utf-8'))
print(a)
print(hexlify(a))
f = 1
s = []
for x in range(3):
for i in range(len(a)):
if (i + x) % 3 == 0:
s.append(a[i])
print(s)
for i in range(len(s)):
print(enc[i] ^ c[(i % 5)], s[i] )
if enc[i] != s[i] ^ c[(i % 5)]:
f = 0
break
if f == 1:
print('RIGHT')
else:
print('WRONG')
# okay decompiling 3.pyc
难度不大,我就不解释了,直接放解题脚本:
c = [ 35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
for i in range(len(enc)):
enc[i] ^= c[i%5]
print(enc)
new = [0] * len(enc)
o = 0
for x in range(3):
for i in range(len(enc)):
if (i + x) % 3 == 0:
new[i] = enc[o]
print(enc[o],end=' ')
o+=1
print()
print(new)
b = b''
import struct
for i in range(len(new)):
b += struct.pack('B', new[i])
print(b)
import base64
r = base64.b64decode(b)
print(r.swapcase())
swapcase()大小写互换有点意思哦。我和炜昊都倒在这里。
ez_code
python字节码。
分析大概是这样的,只是分析的草稿,注释可能有小疏漏哦。
3 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('please input your flag:')
4 CALL_FUNCTION 1
6 POP_TOP
4 8 LOAD_GLOBAL 1 (input)
10 CALL_FUNCTION 0
12 STORE_FAST 0 (flag)
5 14 LOAD_GLOBAL 2 (len)
16 LOAD_FAST 0 (flag)
18 CALL_FUNCTION 1
20 LOAD_CONST 2 (36)
22 COMPARE_OP 3 (!=) # len = 36
24 POP_JUMP_IF_FALSE 30
6 26 LOAD_CONST 3 (0)
28 RETURN_VALUE
7 >> 30 BUILD_LIST 0
32 STORE_FAST 1 (a)
8 34 LOAD_CONST 3 (0)
36 STORE_FAST 2 (t) # t = 0
12 38 LOAD_FAST 0 (flag)
40 GET_ITER
>> 42 FOR_ITER 58 (to 102)
44 STORE_FAST 3 (i)
13 46 LOAD_FAST 2 (t)
48 LOAD_CONST 4 (1)
50 BINARY_AND
52 LOAD_CONST 4 (1)
54 COMPARE_OP 2 (==) # t & 1 == 1 奇数则跳
56 POP_JUMP_IF_FALSE 78
14 58 LOAD_FAST 1 (a)
60 LOAD_METHOD 3 (append)
62 LOAD_GLOBAL 4 (ord)
64 LOAD_FAST 3 (i)
66 CALL_FUNCTION 1
68 LOAD_CONST 5 (128) # 偶数则a.append(ord(i)+128)
70 BINARY_ADD
72 CALL_METHOD 1
74 POP_TOP
76 JUMP_FORWARD 14 (to 92)
16 >> 78 LOAD_FAST 1 (a)
80 LOAD_METHOD 3 (append)
82 LOAD_GLOBAL 4 (ord)
84 LOAD_FAST 3 (i)
86 CALL_FUNCTION 1
88 CALL_METHOD 1 # 奇数则a.append(ord(i))
90 POP_TOP
17 >> 92 LOAD_FAST 2 (t)
94 LOAD_CONST 4 (1)
96 INPLACE_ADD
98 STORE_FAST 2 (t) # t+1
100 JUMP_ABSOLUTE 42 # 跳回循环开始
21 >> 102 LOAD_FAST 1 (a)
104 LOAD_CONST 3 (0)
106 BINARY_SUBSCR
108 LOAD_CONST 6 (5)
110 BINARY_RSHIFT
112 STORE_FAST 4 (b) # a[0] >> 5
22 114 LOAD_GLOBAL 5 (range)
116 LOAD_GLOBAL 2 (len)
118 LOAD_FAST 1 (a)
120 CALL_FUNCTION 1
122 CALL_FUNCTION 1
124 GET_ITER
>> 126 FOR_ITER 82 (to 210)
128 STORE_FAST 3 (i)
23 130 LOAD_FAST 3 (i)
132 LOAD_GLOBAL 2 (len)
134 LOAD_FAST 1 (a)
136 CALL_FUNCTION 1
138 LOAD_CONST 4 (1)
140 BINARY_SUBTRACT # len(a) - 1
142 COMPARE_OP 2 (==)
144 POP_JUMP_IF_FALSE 172 # 循环体在172,而146是循环后运行的
24 146 LOAD_FAST 1 (a)
148 LOAD_FAST 3 (i)
150 BINARY_SUBSCR
152 LOAD_CONST 7 (8)
154 BINARY_MULTIPLY # a[i] * 8
156 LOAD_CONST 8 (255)
158 BINARY_AND # (a[i] * 8) & 0xff
160 LOAD_FAST 4 (b)
162 BINARY_OR
164 LOAD_FAST 1 (a)
166 LOAD_FAST 3 (i)
168 STORE_SUBSCR # a[i] = (a[0] >> 5) | ((a[i] << 3) & 0xff)
170 JUMP_ABSOLUTE 126
26 >> 172 LOAD_FAST 1 (a)
174 LOAD_FAST 3 (i)
176 BINARY_SUBSCR
178 LOAD_CONST 7 (8)
180 BINARY_MULTIPLY
182 LOAD_CONST 8 (255)
184 BINARY_AND # (a[i] * 8) & 0xff
186 LOAD_FAST 1 (a)
188 LOAD_FAST 3 (i)
190 LOAD_CONST 4 (1)
192 BINARY_ADD
194 BINARY_SUBSCR
196 LOAD_CONST 6 (5)
198 BINARY_RSHIFT # a[i+1] >> 5
200 BINARY_OR
202 LOAD_FAST 1 (a)
204 LOAD_FAST 3 (i)
206 STORE_SUBSCR # a[i] = (a[i+1] >> 5) | ((a[i] << 3) & 0xff)
208 JUMP_ABSOLUTE 126
28 >> 210 BUILD_LIST 0
212 STORE_FAST 5 (num)
32 214 LOAD_GLOBAL 5 (range)
216 LOAD_CONST 9 (2)
218 LOAD_CONST 10 (129)
220 CALL_FUNCTION 2
222 GET_ITER
>> 224 FOR_ITER 60 (to 286)
226 STORE_FAST 3 (i) # for i in range(2, 129)
33 228 LOAD_CONST 11 (False)
230 STORE_FAST 2 (t)
34 232 LOAD_GLOBAL 5 (range)
234 LOAD_CONST 9 (2)
236 LOAD_FAST 3 (i)
238 CALL_FUNCTION 2
240 GET_ITER
>> 242 FOR_ITER 26 (to 270)
244 STORE_FAST 6 (j)
35 246 LOAD_FAST 3 (i)
248 LOAD_FAST 6 (j)
250 BINARY_MODULO
252 LOAD_CONST 3 (0)
254 COMPARE_OP 2 (==) # i % j == 0
256 POP_JUMP_IF_FALSE 242
36 258 LOAD_CONST 12 (True)
260 STORE_FAST 2 (t) # t = True
37 262 POP_TOP
264 EXTENDED_ARG 1
266 JUMP_ABSOLUTE 270
268 JUMP_ABSOLUTE 242
38 >> 270 LOAD_FAST 2 (t)
272 POP_JUMP_IF_TRUE 224 # not t
39 274 LOAD_FAST 5 (num)
276 LOAD_METHOD 3 (append)
278 LOAD_FAST 3 (i) # num.append(i)
280 CALL_METHOD 1
282 POP_TOP
284 JUMP_ABSOLUTE 224
40 >> 286 LOAD_CONST 3 (0)
288 BUILD_LIST 1
290 LOAD_GLOBAL 2 (len)
292 LOAD_FAST 1 (a)
294 CALL_FUNCTION 1
296 BINARY_MULTIPLY
298 STORE_FAST 7 (c)
41 300 LOAD_GLOBAL 5 (range)
302 LOAD_GLOBAL 2 (len)
304 LOAD_FAST 1 (a)
306 CALL_FUNCTION 1
308 CALL_FUNCTION 1
310 GET_ITER
>> 312 FOR_ITER 78 (to 392)
314 STORE_FAST 3 (i) # for i in range(len(a))
42 316 LOAD_FAST 1 (a)
318 LOAD_FAST 3 (i)
320 BINARY_SUBSCR
322 LOAD_CONST 13 (4)
324 BINARY_RSHIFT # a[i] >> 4
326 LOAD_FAST 5 (num)
328 LOAD_FAST 3 (i)
330 LOAD_CONST 14 (31)
332 BINARY_MODULO
334 BINARY_SUBSCR # num[i % 31]
336 LOAD_CONST 15 (15)
338 BINARY_AND # num[i % 31] & 0xf
340 BINARY_XOR
342 STORE_FAST 8 (x1) # x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)
43 344 LOAD_FAST 1 (a)
346 LOAD_FAST 3 (i)
348 BINARY_SUBSCR
350 LOAD_CONST 15 (15)
352 BINARY_AND # a[i] & 0xf
354 LOAD_FAST 5 (num)
356 LOAD_FAST 3 (i)
358 LOAD_CONST 14 (31)
360 BINARY_MODULO
362 BINARY_SUBSCR # num[i % 31]
364 LOAD_CONST 13 (4)
366 BINARY_RSHIFT # num[i % 31] >> 4
368 BINARY_XOR
370 STORE_FAST 9 (x2) # x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)
44 372 LOAD_FAST 9 (x2)
374 LOAD_CONST 16 (16)
376 BINARY_MULTIPLY # 16 * x2
378 LOAD_FAST 8 (x1)
380 BINARY_ADD # 16 * x2 + x1
382 LOAD_FAST 7 (c)
384 LOAD_FAST 3 (i)
386 STORE_SUBSCR # c[i] = 16 * x2 + x1
388 EXTENDED_ARG 1
390 JUMP_ABSOLUTE 312
47 >> 392 LOAD_CONST 17 (227) # 密文
394 LOAD_CONST 18 (169)
396 LOAD_CONST 17 (227)
398 LOAD_CONST 19 (45)
400 LOAD_CONST 20 (234)
402 LOAD_CONST 21 (39)
404 LOAD_CONST 22 (98)
406 LOAD_CONST 23 (190)
408 LOAD_CONST 24 (197)
410 LOAD_CONST 25 (7)
412 LOAD_CONST 26 (229)
414 LOAD_CONST 27 (137)
416 LOAD_CONST 24 (197)
418 LOAD_CONST 28 (132)
420 LOAD_CONST 29 (119)
422 LOAD_CONST 30 (142)
424 LOAD_CONST 31 (97)
426 LOAD_CONST 32 (167)
428 LOAD_CONST 33 (59)
430 LOAD_CONST 34 (96)
432 LOAD_CONST 35 (166)
434 LOAD_CONST 36 (94)
436 LOAD_CONST 37 (136)
438 LOAD_CONST 17 (227)
440 LOAD_CONST 38 (131)
442 LOAD_CONST 39 (202)
444 LOAD_CONST 37 (136)
446 LOAD_CONST 40 (250)
448 LOAD_CONST 41 (21)
450 LOAD_CONST 42 (99)
452 LOAD_CONST 43 (20)
454 LOAD_CONST 44 (173)
456 LOAD_CONST 45 (121)
458 LOAD_CONST 46 (41)
460 LOAD_CONST 47 (125)
462 LOAD_CONST 48 (165)
464 BUILD_LIST 36
466 STORE_FAST 10 (d)
48 468 LOAD_CONST 4 (1)
470 STORE_FAST 11 (e)
49 472 LOAD_GLOBAL 5 (range)
474 LOAD_GLOBAL 2 (len)
476 LOAD_FAST 10 (d)
478 CALL_FUNCTION 1
480 CALL_FUNCTION 1
482 GET_ITER
>> 484 FOR_ITER 34 (to 520)
486 STORE_FAST 3 (i)
50 488 LOAD_FAST 10 (d)
490 LOAD_FAST 3 (i)
492 BINARY_SUBSCR
494 LOAD_FAST 7 (c)
496 LOAD_FAST 3 (i)
498 BINARY_SUBSCR
500 COMPARE_OP 3 (!=)
502 EXTENDED_ARG 1
504 POP_JUMP_IF_FALSE 484
51 506 LOAD_CONST 3 (0)
508 STORE_FAST 11 (e)
52 510 POP_TOP
512 EXTENDED_ARG 2
514 JUMP_ABSOLUTE 520
516 EXTENDED_ARG 1
518 JUMP_ABSOLUTE 484
53 >> 520 LOAD_FAST 11 (e)
522 LOAD_CONST 4 (1)
524 COMPARE_OP 2 (==)
526 EXTENDED_ARG 2
528 POP_JUMP_IF_FALSE 540
54 530 LOAD_GLOBAL 0 (print)
532 LOAD_CONST 49 ('YOU ARE RIGHT')
534 CALL_FUNCTION 1
536 POP_TOP
538 JUMP_FORWARD 8 (to 548)
56 >> 540 LOAD_GLOBAL 0 (print)
542 LOAD_CONST 50 ('WRONG')
544 CALL_FUNCTION 1
546 POP_TOP
>> 548 LOAD_CONST 0 (None)
550 RETURN_VALUE
手写其逻辑:
flag = input()
if len(flag) != 36:
exit()
t = 0
a = []
for i in flag:
if t & 1 == 1:
a.append(ord(i)+128)
else:
a.append(ord(i))
t += 1
a[len(a)-1] = ((a[len(a)-1] << 3) & 0xff) | (a[0] >> 5)
for i in range(len(a)-1):
a[i] = ((a[i] << 3) & 0xff) | (a[i+1] >> 5)
num = []
for i in range(2, 129):
t = False
for j in range(2, i):
if i % j == 0:
t = True
if not t:
num.append(i)
c = [0] * len(flag)
for i in range(len(a)):
x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)
x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)
c[i] = (x2 << 4) + x1
d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
for i in range(len(d)):
if d[i] != c[i]:
print('WRONG')
exit()
print('YOU ARE RIGHT')
逆向主要是两段,第一段就是简单的左移3右移5。
第二段简单分析下见下图,就是a[i]交换高低4bit后与num[i%31]异或。
逆向脚本:
num=[]
for i in range(2,129):
t=False
for j in range(2,i):
if i%j==0:
t=True
if not t:
num.append(i)
print(len(num))
c=d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
print(c)
a = []
for i in range(len(c)):
tmp = d[i] ^ num[i % 31]
tmp = (tmp >> 4) + ((tmp & 0xf) << 4)
a.append(tmp)
s = ''
for i in range(len(a)):
s += bin(a[i])[2:].zfill(8)
print(s)
s = s[-3:] + s[:-3]
print(s)
flag = []
for i in range(len(a)):
tmp = int(s[i*8: i*8+8], 2)
if i % 2 == 0:
flag.append(tmp)
else:
flag.append(tmp-128)
print(flag)
print(''.join(list(map(chr, flag))))
time
这题很有意思哦。
输入flag前会验证时间,必须在特定的年月日时分秒才能继续。但是还不能简单地patch掉这些验证。因为会把这些参数计算出一个int后传入验证flag的函数,并参与flag验证的逻辑。所以需要计算出这个int,然后patch掉时间验证之后,进入flag验证函数前,手动修改传入的这个参数 55*7*903274960*9*2018*32 = 0xec48d400
。
这题应该是用了一些C语言没有的函数,伪代码有点奇怪,但没有特别的c++的特征(其实是有点的。不知道怎么编译的。识别不出来这些奇怪的库函数,只能动调慢慢推测。
输入flag后,创建一个flag备份,记作buffer,并通过下面逻辑,将传入的与时间有关的int进行转换,生成0~4的字节,并拼接到buffer的首部。
从int中分出4个byte, &0x7f后如果满足上述逻辑,就添加到buffer的头部。可能添加0~3个字节,这取决于时间参数。对于通过验证的唯一参数0xec48d400,会添加3个字节。
创建一个table,长62,值为0-9a-zA-Z
从buffer(3个时间参数导出的字节+flag)中找到每个字符在table0-9a-zA-Z中首次出现的索引:
然后主要的逻辑在sub_401541。
这次是从flag中找到每个字符在table0-9a-zA-Z中首次出现的索引,然后与上一步的table_from_find_first_index_by_buffer[i]模62相加。
什么意思呢?
一个数组是3个时间参数相关字节+flag,一个”数组“是flag,这两个数组对于元素模62相加,然后作为索引取table0-9a-zA-Z的字符。
所以其实就是个错位相加。
动调到这个函数,拿到这3个时间参数相关字节0x0d, 0x0c, 0x38。然后错位计算。
解密脚本:
import string
from z3 import *
time = 55*7*903274960*9*2018*32
print(hex(time&0xffffffff))
cipher = 'P6GvwFypZN1BbFn5tVgoWeK81LkeQ6uvuiovDgO'
print(len(cipher))
table = string.digits + string.ascii_lowercase + string.ascii_uppercase
print(table)
a = (table.find(cipher[0]) - 0x0d + 62) % 62
b = (table.find(cipher[1]) - 0x0c + 62) % 62
c = (table.find(cipher[2]) - 0x38 + 62) % 62
index = [a, b, c]
print(index)
for i in range(3, len(cipher)):
tmp = (table.find(cipher[i]) - index[i-3] + 62) % 62
index.append(tmp)
for i in index[:-3]:
print(table[i],end='')
print()
baby_encrypt
把flag主体按-分割拆成3部分,分别进入函数验证
三个main都是md5,逐渐魔改递进。
main是原版md5,然后把md5走一些古典算法,然后比较密文。
从密文可以逆回md5。然后可以查彩虹表。
main1算法:
int __cdecl main1(char *part1)
{
int v1; // eax
int v2; // eax
unsigned int k; // eax
int v5[16]; // [esp+10h] [ebp-D8h]
char Src[8]; // [esp+50h] [ebp-98h] BYREF
int md5_ctx[2]; // [esp+58h] [ebp-90h] BYREF
int ctx_state; // [esp+60h] [ebp-88h] BYREF
char md5_digest[16]; // [esp+B0h] [ebp-38h] BYREF
const char *v10; // [esp+C0h] [ebp-28h]
int tmp; // [esp+C4h] [ebp-24h]
int low; // [esp+C8h] [ebp-20h]
int high; // [esp+CCh] [ebp-1Ch]
int v14; // [esp+D0h] [ebp-18h]
unsigned int v15; // [esp+D4h] [ebp-14h]
int j; // [esp+D8h] [ebp-10h]
int i; // [esp+DCh] [ebp-Ch]
md5_init(md5_ctx);
v1 = strlen(part1);
MD5Update((int)md5_ctx, part1, v1);
v14 = 0; // 以下是MD5Final
v15 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
if ( v15 > 0x37 )
v2 = 120 - v15;
else
v2 = 56 - v15;
v14 = v2;
MD5Encode((int)Src, (int)md5_ctx, 8u);
MD5Update((int)md5_ctx, &padding, v14);
MD5Update((int)md5_ctx, Src, 8);
MD5Encode((int)md5_digest, (int)&ctx_state, 0x10u);// 以上是MD5Final
for ( i = 0; i <= 15; ++i )
{
high = (unsigned __int8)md5_digest[i] >> 4;
low = md5_digest[i] & 0xF;
md5_digest[i] = 16 * low + (high ^ low);
*((_BYTE *)&v5[8] + 2 * i) = (unsigned __int8)md5_digest[i] >> 4;// = low, 0~15
*((_BYTE *)&v5[8] + 2 * i + 1) = md5_digest[i] & 0xF;// = high ^ low
}
for ( i = 0; i <= 31; i += 8 )
{
for ( j = 0; j <= 3; ++j )
{
tmp = *((char *)&v5[8] + i + j);
*((_BYTE *)&v5[8] + j + i) = *((_BYTE *)&v5[8] + i + 7 - j);
*((_BYTE *)&v5[8] + i + 7 - j) = tmp;
} // 07,16,25,34互换
}
for ( k = 0; k < 8; ++k ) // memset(v5, 0, 8)
v5[k] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&v5[8] + i) > 9 || *((char *)&v5[8] + i) < 0 )// num2char
{
if ( *((char *)&v5[8] + i) > 9 && *((char *)&v5[8] + i) <= 15 )
*((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 87;
}
else
{
*((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 48;
}
}
v10 = "e0c1942932d5845b5128552378fb20bf";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)v5 + i) != v10[i] )
return 0;
}
return 1;
}
逆向脚本:
a = 'e0c1942932d5845b5128552378fb20bf'
a = [ord(i) for i in a]
#print(a)
for i in range(0, 32, 8):
for j in range(4):
a[i+j], a[i+7-j] = a[i+7-j], a[i+j]
#print(a)
a = [int(str(chr(i)), 16) for i in a]
#print(a)
for i in range(16):
t1 = a[i*2]
t2 = a[i*2+1]
t1, t2 = t1 ^ t2, t1
a[i*2], a[i*2+1] = t1, t2
hash1 = ''
for i in a:
hash1 += str(hex(i)[2:])
print(hash1)
# md5 = b9d4d1e0ebc485121305a8414f204bf8
# plain = R2e
main2算法(只比main1多了一步)
int __cdecl main2(char *Str)
{
int v1; // eax
int v2; // eax
unsigned int k; // eax
unsigned int m; // eax
int v6[16]; // [esp+14h] [ebp-E4h]
char Src[8]; // [esp+54h] [ebp-A4h] BYREF
int md5_ctx[2]; // [esp+5Ch] [ebp-9Ch] BYREF
int v9; // [esp+64h] [ebp-94h] BYREF
char digest[16]; // [esp+B4h] [ebp-44h] BYREF
const char *v11; // [esp+C4h] [ebp-34h]
int v12; // [esp+C8h] [ebp-30h]
int v13; // [esp+CCh] [ebp-2Ch]
int v14; // [esp+D0h] [ebp-28h]
unsigned int v15; // [esp+D4h] [ebp-24h]
int *ctx_state; // [esp+D8h] [ebp-20h]
int len; // [esp+DCh] [ebp-1Ch]
unsigned int v18; // [esp+E0h] [ebp-18h]
int l; // [esp+E4h] [ebp-14h]
int j; // [esp+E8h] [ebp-10h]
int i; // [esp+ECh] [ebp-Ch]
md5_init(md5_ctx);
v1 = strlen(Str);
MD5Update((int)md5_ctx, Str, v1);
len = 0;
v18 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
if ( v18 > 0x37 )
v2 = 0x78 - v18;
else
v2 = 0x38 - v18;
len = v2;
MD5Encode((int)Src, (int)md5_ctx, 8u);
MD5Update((int)md5_ctx, &padding, len);
MD5Update((int)md5_ctx, Src, 8);
ctx_state = &v9; // 比main1多了这块
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 2; ++j )
{
v15 = (unsigned int)ctx_state[i] >> 28;
ctx_state[i] = 16 * ctx_state[i] + v15; // << 4 | >> 28
} // <<12 | >> 20
ctx_state[i] ^= 0xA3DFA1DB;
}
MD5Encode((int)digest, (int)ctx_state, 0x10u);
for ( k = 0; k < 8; ++k )
v6[k + 8] = 0;
for ( i = 0; i <= 15; ++i )
{
v14 = (unsigned __int8)digest[i] >> 4;
v13 = digest[i] & 0xF;
*((_BYTE *)&v6[8] + 2 * i) = v13;
*((_BYTE *)&v6[8] + 2 * i + 1) = v14 ^ v13;
}
for ( i = 0; i <= 31; i += 8 )
{
for ( l = 0; l <= 3; ++l )
{
v12 = *((char *)&v6[8] + i + l);
*((_BYTE *)&v6[8] + l + i) = *((_BYTE *)&v6[8] + i + 7 - l);
*((_BYTE *)&v6[8] + i + 7 - l) = v12;
}
}
for ( m = 0; m < 8; ++m )
v6[m] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&v6[8] + i) > 9 || *((char *)&v6[8] + i) < 0 )
{
if ( *((char *)&v6[8] + i) > 9 && *((char *)&v6[8] + i) <= 15 )
*((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 87;
}
else
{
*((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 48;
}
}
v11 = "d039a1b9c6daa1b450b044aeb2696a44";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)v6 + i) != v11[i] )
return 0;
}
return 1;
}
逆向脚本(注意MD5Encode的大小端转换哦)
b = 'd039a1b9c6daa1b450b044aeb2696a44'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
for j in range(4):
b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)
for i in range(16):
t1 = b[i*2]
t2 = b[i*2+1]
t1, t2 = t1 ^ t2, t1
b[i*2], b[i*2+1] = t1, t2
b_data = []
for i in range(16):
tmp = (b[i*2]<<4) + b[i*2+1]
b_data.append(tmp)
print(b_data)
for i in range(4):
tmp = b_data[i*4] + (b_data[i*4+1]<<8) + (b_data[i*4+2]<<16) + (b_data[i*4+3]<<24)
tmp ^= 0xA3DFA1DB
#print(bin(tmp)[2:].zfill(32))
tmp = ((tmp<<20)&0xffffffff) + (tmp>>12)
#print(bin(tmp)[2:].zfill(32))
#print()
b_data[i*4] = tmp&0xff
b_data[i*4+1] = (tmp>>8)&0xff
b_data[i*4+2] = (tmp>>16)&0xff
b_data[i*4+3] = (tmp>>24)&0xff
print(b_data)
b_md5 = ''
for i in b_data:
b_md5 += hex(i)[2:].zfill(2)
print(b_md5)
# md5 = 6137270f515af002fa365f596612f3bd
# plain = 1S
main3算法:
int __cdecl main3(char *part3)
{
int v1; // eax
int v2; // eax
unsigned int l; // eax
int result; // eax
int Buffer; // [esp+18h] [ebp-120h] BYREF
int f_part3[20]; // [esp+20h] [ebp-118h] BYREF
char Src[8]; // [esp+70h] [ebp-C8h] BYREF
int ctx[2]; // [esp+78h] [ebp-C0h] BYREF
_BYTE v9[80]; // [esp+80h] [ebp-B8h] BYREF
char digest[16]; // [esp+D0h] [ebp-68h] BYREF
char _part3[16]; // [esp+E0h] [ebp-58h] BYREF
const char *cipher; // [esp+F0h] [ebp-48h]
int v13; // [esp+F4h] [ebp-44h]
size_t v14; // [esp+F8h] [ebp-40h]
FILE *fFLAG; // [esp+FCh] [ebp-3Ch]
FILE *fdata; // [esp+100h] [ebp-38h]
int v17; // [esp+104h] [ebp-34h]
int v18; // [esp+108h] [ebp-30h]
int v19; // [esp+10Ch] [ebp-2Ch]
int v20; // [esp+110h] [ebp-28h]
_BYTE *v21; // [esp+114h] [ebp-24h]
int padlen; // [esp+118h] [ebp-20h]
unsigned int v23; // [esp+11Ch] [ebp-1Ch]
int k; // [esp+120h] [ebp-18h]
char part3_b3; // [esp+126h] [ebp-12h]
char part3_b1; // [esp+127h] [ebp-11h]
int j; // [esp+128h] [ebp-10h]
int i; // [esp+12Ch] [ebp-Ch]
strcpy(_part3, part3);
md5_init(ctx);
v1 = strlen(part3);
MD5Update((int)ctx, part3, v1);
padlen = 0;
v23 = ((unsigned int)ctx[0] >> 3) & 0x3F;
if ( v23 > 0x37 )
v2 = 120 - v23;
else
v2 = 56 - v23;
padlen = v2;
MD5Encode((int)Src, (int)ctx, 8u);
MD5Update((int)ctx, &padding, padlen);
MD5Update((int)ctx, Src, 8);
v21 = v9;
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 2; ++j )
{
v20 = *(_DWORD *)&v21[4 * i] >> 28;
*(_DWORD *)&v21[4 * i] = 16 * *(_DWORD *)&v21[4 * i] + v20;
}
*(_DWORD *)&v21[4 * i] ^= 0xA3DFA1DB;
}
MD5Encode((int)digest, (int)v9, 0x10u);
for ( i = 0; i <= 15; ++i )
{
v19 = (unsigned __int8)digest[i] >> 4;
v18 = digest[i] & 0xF;
*((_BYTE *)&f_part3[12] + 2 * i) = v18;
*((_BYTE *)&f_part3[12] + 2 * i + 1) = v19 ^ v18;
}
part3_b1 = _part3[1] & 0x7F; // 差异
part3_b3 = _part3[3] & 0x7F;
for ( i = 0; i <= 31; ++i )
{
if ( i != 1 )
part3_b1 ^= *((_BYTE *)&f_part3[12] + i);
if ( i )
part3_b3 ^= *((_BYTE *)&f_part3[12] + i);
} // 上 差异
for ( i = 0; i <= 31; i += 8 )
{
for ( k = 0; k <= 3; ++k )
{
v17 = *((char *)&f_part3[12] + i + k);
*((_BYTE *)&f_part3[12] + k + i) = *((_BYTE *)&f_part3[12] + i + 7 - k);
*((_BYTE *)&f_part3[12] + i + 7 - k) = v17;
}
}
for ( l = 0; l < 8; ++l )
f_part3[l + 4] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&f_part3[12] + i) > 9 || *((char *)&f_part3[12] + i) < 0 )
{
if ( *((char *)&f_part3[12] + i) > 9 && *((char *)&f_part3[12] + i) <= 15 )
*((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 87;
}
else
{
*((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 48;
}
}
fdata = fopen("data", "rb");
fFLAG = fopen("FLAG", "w+b");
if ( fdata && fFLAG )
{
f_part3[2] = 0;
f_part3[3] = 0;
v14 = 0;
v13 = 0;
i = 0;
while ( 1 )
{
v14 = fread(f_part3, 1u, 1u, fdata);
if ( !v14 )
break;
if ( (i & 1) == 0 ) // 偶
Buffer = f_part3[0] ^ part3_b1;
if ( i % 2 == 1 ) // 奇
Buffer = f_part3[0] ^ part3_b3;
++i;
fwrite(&Buffer, 1u, 1u, fFLAG);
}
fclose(fdata);
fclose(fFLAG);
cipher = "46f627c53e41fc2a2182ba286295bc35";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)&f_part3[4] + i) != cipher[i] )
return 0;
}
result = 1;
}
else
{
puts("error!");
result = 0;
}
return result;
}
main3是在main2基础上改的。
hint中有提示jpg。答案就是,第三段的md5查表查不出来,长度是13,爆破也不太容易。但是第三段flag就在jpg里面写着(data是jpg的密文)
那data的密钥是啥呢?来看下逻辑。
首先flag的第三部分&0x7f后,分奇偶分别与md5计算后但是验证前的中间值循环异或。
好的,中间值我们可以逆向得到,但是这个输入值拿不到啊。这里不是突破点。
那再来看下,从data读入密文,异或后,buffer是解密的明文。
buffer是输出,f_part3[0]是从data文件中读入的一个字节,part3_b1是密钥。
如果是jpg,那么文件头是固定(ffd8ffe0)的,所以buffer已知一定的字节。然后是f_part3[0],这是异或和的密文,就在data里,也已知。所以我们可求密钥。
解密脚本:
b = '46f627c53e41fc2a2182ba286295bc35'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
for j in range(4):
b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)
part3_b1 = 0xbd ^ 0xff
part3_b3 = 0x8b ^ 0xd8
print(part3_b1, part3_b3)
with open('data', 'rb')as f:
b = f.read()
b = list(b)
for i in range(len(b)):
if i % 2 == 0:
b[i] ^= part3_b1
else:
b[i] ^= part3_b3
bb = b''
import struct
for i in b:
bb += struct.pack('B', i)
with open(r'data.jpg', 'wb')as f:
f.write(bb)
crypto
RSA签到
n = 807862607863494903203347547751222668477246136996519972166847
c = 6525071913169990474785757170304035615411828876052879070297
e = 65537
from Crypto.Util.number import *
from gmpy2 import *
P31 = 1034526559407993507734818408829
P30 = 780900790334269659443297956843
phi = (P31-1) * (P30-1)
d = inverse(e, phi)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))
简单的密码学
task.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import libnum
import random
e=libnum.s2n(flag)
n = 2 ** 514
m = random.randint(2, n-1) | 1
c = pow(m, e, n)
print('m = ' + str(m))
print('c = ' + str(c))
# m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
# c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041
flag是e,所以是离散对数的求解。
贴个资料:
直接上sympy的轮子:
from sympy.ntheory import *
from Crypto.Util.number import *
n = 2 ** 514
m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041
flag = discrete_log(n,c,m)
print(long_to_bytes(flag))
名字不重要
给出一个pyc,一个流量包。
pyc改成python3.8.5的魔数,然后转成python代码。
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: res.py
# Compiled at: 2020-12-26 02:08:16
# Size of source mod 2**32: 5 bytes
import hmac, hashlib, random, struct
KIDING_SIZE = 32
SIG_SIZE = 16
TOTAL_SIZE = set((c for c in range(256)))
KEY = b'af5f76f605a700ae8c0895c3e6175909'
def func1(v):
return bytes([v])
def sign_sign_sign(val, key):
return hmac.new(key,
val, digestmod=(hashlib.sha256)).digest()[:SIG_SIZE]
def chaff_chaff_chaff_b(val, key):
messgs = {}
messgs[val[0]] = sign_sign_sign(val, key)
while len(messgs) < KIDING_SIZE:
arg1 = list(TOTAL_SIZE - set(messgs.keys()))
c = random.choice(arg1)
if c == val:
raise ValueError('C~h~o~s~e d~u~p~l~i~c~a~t~e~!')
bad_sig = bytes(random.choices((list(TOTAL_SIZE)), k=SIG_SIZE))
messgs[c] = bad_sig
block = []
for k, v in messgs.items():
block.append(b'%s%s' % (func1(k), v))
else:
random.shuffle(block)
return ''.join(block)
def chaff_chaff_chaff_m(val, key):
if not isinstance(val, bytes):
val = val.encode('utf-8')
the_out = []
for b in val:
the_out.append(chaff_chaff_chaff_b(func1(b), key))
else:
out1 = ''.join(the_out)
return struct.pack('>I', len(val)) + out1
def winnow_winnow_winnow_m(val, key):
if not isinstance(val, bytes):
val = val.encode('utf-8')
msglen = struct.unpack('>I', val[:4])[0]
val = val[4:]
block_len = (SIG_SIZE + 1) * KIDING_SIZE
expected_len = block_len * msglen
if len(val) != expected_len:
raise ValueError('E~x~p~e~c~t~e~d l~e~n~g~t~h %d, saw %d.' % (expected_len, len(val)))
pieces = []
for c in range(msglen):
chunk = val[block_len * c:block_len * (c + 1)]
res = winnow_winnow_winnow_b(chunk, key)
pieces.append(res)
else:
return ''.join(pieces)
def winnow_winnow_winnow_b(val, key):
while val:
c = func1(val[0])
sig = val[1:SIG_SIZE + 1]
if sign_sign_sign(c, key) == sig:
return c
val = val[SIG_SIZE + 1:]
raise ValueError('~N~o v~a~l~i~d s~i~g f~o~u~n~d!')
def main():
inp = b'~T~h~i~s i~s a t~e~s~t m~e~s~s~a~g~e!'
msg = chaff_chaff_chaff_m(inp, KEY)
ret = winnow_winnow_winnow_m(msg, KEY)
if inp != ret:
print('W~r~o~n~g r~e~t: %s' % ret)
if __name__ == '__main__':
main()
# okay decompiling just_a_name.pyc
传输模型为首先4个字节是消息长度。然后是消息,每32*17字节为一组,每组的有效信息只有1字节。对该字节求hash,取前16byte添加在有效信息这一字节后面,这是共17字节。然后随机选31字节,这是非有效的垃圾信息,重复上述步骤,共得到32*17字节,最后随机打乱32小组的相对顺序。有效信息其实只有一字节。然后后面的有效信息同理。
另一端取出一组后,共32*17字节,循环32次。利用提前约定好的key,计算32个字节的hash,共32*16字节,对比计算结果和每个小组中的第2~17个字节的签名是否相符,相符则是有效信息,其余31字节则是垃圾信息。
但我们没有key怎么办呢?统计。
由于一个字节的签名永远是相同的。所以如果一组中的签名也在其余组中出现,那么这大概率就是有效信息及其签名。
from Crypto.Util.number import *
from scapy.all import rdpcap
packets = rdpcap("message.pcap")
sport=3199
src="127.0.0.1"
f = b''
for packet in packets:
if "TCP" in packet and packet['TCP'].payload:
if packet["IP"].src==src and packet["TCP"].sport==sport:
f += packet['TCP'].payload.load
f = f[4:]
packets = []
for i in range(0, len(f), 32*17):
packets.append(f[i:i+32*17])
data = []
all_value = []
for packet in packets:
tmp = []
for i in range(0, 32*17, 17):
group = packet[i:i+17]
ch, sig = group[0], group[1:]
all_value.append((ch, sig))
tmp.append((ch, sig))
data.append(tmp)
result = []
for item in data:
for m in item:
if all_value.count(m) > 1:
result.append(m)
break
print(b''.join([long_to_bytes(item[0]) for item in result]))
名字没想好
task.py
from gmpy2 import *
import gmpy2
from Crypto.Util.number import *
from sympy import *
import sympy
#part1
flag1 = b'CUMTCTF{**********'
m1 = bytes_to_long(flag1)
p1 = getPrime(1024)
q1 = getPrime(1024)
e1 = 103738
n1 = p1 * q1
gift = lcm(p1 - 1, q1 - 1)
c1 = pow(m1, e1, n1)
print('n1 = ', n1)
print('c1 = ', c1)
print('gift = ', gift)
#part2
flag2 = b'**********************'
e2 = 65537
m2 = bytes_to_long(flag2)
p2 = getPrime(1024)
q2 = sympy.nextprime(p2)
n2 = p2 * q2
phi2 = (p2 - 1) * (q2 - 1)
d2 = gmpy2.invert(e2, phi2)
c2 = pow(m2, e2, n2)
print('d = ', d2)
print('c2 = ', c2)
data:
n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
d = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579
一共两关。
首先观察到e明显不是素数,但是e/2是。所以rsa的公司转换成m的平方的e/2方。套公式的时候,要把e/2当成e代入,求出的是m的平方。然后开方可得m。
然后得想办法求phi。很明显题目给出了p-1和q-1的最小公倍数。由于lcm(p-1, q-1) * gcd(p-1, q-1) = (p-1)*(q-1)
。
简记为lcm * gcd = phi
phi和n的长度差不太多,n的长度是2048,而lcm的长度是2047,所以gcd只需要爆个位数就行。爆出phi就可以求第一段flag.
那第二关呢?
已知e, d, c。求n。
很明显p和q是相邻素数,在这前提下p约等于根号下n约等于根号下phi。
phi可以表示成(e*d-1)/k,e和d已知。所以可以爆破k。ed乘积是2063,phi必然比d要大,而d的长度是2047,所以爆破上限是2的16次方。
稍微约束下就开始爆破。对phi开根号,可以得到p的近似值tmp。然后next_prime(tmp)必然是p或者q。为啥呢?因为p<q,如果p和q都在tmp的左侧,那么p*q<tmp的平方即phi。矛盾哦。
脚本:
from gmpy2 import *
from Crypto.Util.number import *
from sympy import *
n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
_lcm = gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
e1 = 103738 // 2
for _gcd in range(1, 10):
try:
phi = _lcm * _gcd
d1 = inverse(e1, phi)
m1 = pow(c1, d1, n1)
m1 = iroot(m1, 2)[0]
msg = long_to_bytes(m1)
if b'CUMTCTF{' in msg:
print(msg)
break
except:
pass
d2 = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579
e2 = 65537
ed = e2 * d2
print(len(bin(ed)[2:]))
for k in range(2**14, 2**15):
if (ed - 1) % k == 0:
phi2 = (ed - 1) // k
tmp = iroot(phi2, 2)[0]
p2 = next_prime(tmp)
#print(k)
#print(phi2 % (p2-1))
if phi2 % (p2-1) == 0:
q2 = phi2 // (p2-1) + 1
n2 = p2 * q2
m2 = pow(c2, d2, n2)
msg = long_to_bytes(m2)
print(msg)
break
Merry_Christmas
task.py
from Crypto.Util.number import *
from gmpy2 import *
#from secret import flag
bit_length = 1024
p = getPrime(bit_length)
q = getPrime(bit_length)
n = p*q
m = bytes_to_long(flag)
n= p * q
e = 65537
c = pow(m,e,n)
p1 = getPrime(bit_length)
q1 = getPrime(bit_length)
n1 = p1*q1
e1 = 979691
c1 = pow(p,e1,n1)
gift1 = pow(907*p1+q1,587,n1)
gift2 = pow(p1+q1,691,n1)
print('n={}'.format(n))
print('c={}'.format(c))
print('n1={}'.format(n1))
print('c1={}'.format(c1))
print('gift1={}'.format(gift1))
print('gift2={}'.format(gift2))
data:
n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665
之前上海市ctf的题,原地tp我之前的wp
解题脚本:
from Crypto.Util.number import *
from gmpy2 import *
n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665
e1 = 979691
e = 65537
#gift1 = pow(907*p1+q1,587,n1)
#gift2 = pow(p1+q1,691,n1)
tmp = pow(gift2, 587, n1) - pow(gift1, 691, n1)
p1 = gcd(tmp, n1)
q1 = n1 // p1
phi1 = (p1 - 1) * (q1 - 1)
d1 = inverse(e1, phi1)
p = pow(c1, d1, n1)
q = n // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
msg = long_to_bytes(m)
print(msg)
老张:不到最后时刻,很难分出高低
8点59的时候学弟你们还是第一,短短一小时就发生了翻天覆地的变化