狗儿

热爱的话就坚持吧~

0%

巅峰极客

这比赛没学到啥有意义的新知识。逆向有两道题是常规题,付出一定时间大家都能做出来,还有一题全场零解,还没给提示,赛后也没wp。misc很有意思,可惜我以后不走工控安全这条路。

virus

image-20200927103437050

走四次迷宫

image-20200927103538067

dddddddddsssssaaaaaaaaawww

sdsdsdsdsdsdsddwdwdwdwdwdwdw

aaaaaaaaasssssssddddddddd

wwwwwdddddddddsssss

不过flag的格式有点升级

image-20200927103732843

image-20200927104907201

意思是-和-之间的字符数,也就是走迷宫的步数。

那个判断数字是在v14=0,也就是还没扫描到-的时候,进行判断的,是数字的话就存储,直到出现了-。

后面check flag的时候,会根据先后的数字依次进行check。

image-20200927104542152

根据规定的步数,因此只能有一种走法:

flag{4312-wwwwwdddddddddsssss-aaaaaaaaasssssssddddddddd-dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw}

image-20200927105521725

fu!k.pyc

uncompyle6拿到源码:

1
2
3
4
5
6
7
8
9
10
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# 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: test233_ol.py
# Compiled at: 2020-03-20 13:22:50
(lambda __g, __print: [ [ (lambda __after: [ (lambda __after: (__print('Error len!'), (exit(), __after())[1])[1] if len(input) != 87 else __after())(lambda : [ [ [ [ (lambda __after: (__print('Error fmt!'), (exit(0), __after())[1])[1] if fmt1 != 'flag{' or fmt2 != '}' else __after())(lambda : (d.append(context[0:9]), (d.append(context[9:18]), (d.append(context[18:27]), (d.append(context[27:36]), (d.append(context[36:45]), (d.append(context[45:54]), (d.append(context[54:63]), (d.append(context[63:72]), (d.append(context[72:81]), [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[0][2] != '5' or d[0][3] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[1][0] != '8' or d[1][7] != '2' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[2][1] != '7' or d[2][4] != '1' or d[2][6] != '5' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[3][0] != '4' or d[3][5] != '5' or d[3][6] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[4][1] != '1' or d[4][4] != '7' or d[4][8] != '6' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[5][2] != '3' or d[5][3] != '2' or d[5][7] != '8' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[6][1] != '6' or d[6][3] != '5' or d[6][8] != '9' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[7][2] != '4' or d[7][7] != '3' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[8][5] != '9' or d[8][6] != '7' else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(h1) != 45 or check(h2) != 45 or check(h3) != 45 or check(h4) != 45 or check(h5) != 45 or check(h6) != 45 or check(h7) != 45 or check(h8) != 45 or check(h9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(l1) != 45 or check(l2) != 45 or check(l3) != 45 or check(l4) != 45 or check(l5) != 45 or check(l6) != 45 or check(l7) != 45 or check(l8) != 45 or check(l9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(k1) != 45 or check(k2) != 45 or check(k3) != 45 or check(k4) != 45 or check(k5) != 45 or check(k6) != 45 or check(k7) != 45 or check(k8) != 45 or check(k9) != 45 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(h1) != 1 or check1(h2) != 1 or check1(h3) != 1 or check1(h4) != 1 or check1(h5) != 1 or check1(h6) != 1 or check1(h7) != 1 or check1(h8) != 1 or check1(h9) != 1 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(l1) != 1 or check1(l2) != 1 or check1(l3) != 1 or check1(l4) != 1 or check1(l5) != 1 or check1(l6) != 1 or check1(l7) != 1 or check1(l8) != 1 or check1(l9) != 1 else __after())(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(k1) != 1 or check1(k2) != 1 or check1(k3) != 1 or check1(k4) != 1 or check1(k5) != 1 or check1(k6) != 1 or check1(k7) != 1 or check1(k8) != 1 or check1(k9) != 1 else __after())(lambda : (__print('Yes! You got it!'), __after())[1]))))))))))))))) for __g['k9'] in [context[60] + context[61] + context[62] + context[69] + context[70] + context[71] + context[78] + context[79] + context[80]] ][0] for __g['k8'] in [context[57] + context[58] + context[59] + context[66] + context[67] + context[68] + context[75] + context[76] + context[77]] ][0] for __g['k7'] in [context[54] + context[55] + context[56] + context[63] + context[64] + context[65] + context[72] + context[73] + context[74]] ][0] for __g['k6'] in [context[33] + context[34] + context[35] + context[42] + context[43] + context[44] + context[51] + context[52] + context[53]] ][0] for __g['k5'] in [context[30] + context[31] + context[32] + context[39] + context[40] + context[41] + context[48] + context[49] + context[50]] ][0] for __g['k4'] in [context[27] + context[28] + context[29] + context[36] + context[37] + context[38] + context[45] + context[46] + context[47]] ][0] for __g['k3'] in [context[6] + context[7] + context[8] + context[15] + context[16] + context[17] + context[24] + context[25] + context[26]] ][0] for __g['k2'] in [context[3] + context[4] + context[5] + context[12] + context[13] + context[14] + context[21] + context[22] + context[23]] ][0] for __g['k1'] in [context[0] + context[1] + context[2] + context[9] + context[10] + context[11] + context[18] + context[19] + context[20]] ][0] for __g['l9'] in [context[8] + context[17] + context[26] + context[35] + context[44] + context[53] + context[62] + context[71] + context[80]] ][0] for __g['l8'] in [context[7] + context[16] + context[25] + context[34] + context[43] + context[52] + context[61] + context[70] + context[79]] ][0] for __g['l7'] in [context[6] + context[15] + context[24] + context[33] + context[42] + context[51] + context[60] + context[69] + context[78]] ][0] for __g['l6'] in [context[5] + context[14] + context[23] + context[32] + context[41] + context[50] + context[59] + context[68] + context[77]] ][0] for __g['l5'] in [context[4] + context[13] + context[22] + context[31] + context[40] + context[49] + context[58] + context[67] + context[76]] ][0] for __g['l4'] in [context[3] + context[12] + context[21] + context[30] + context[39] + context[48] + context[57] + context[66] + context[75]] ][0] for __g['l3'] in [context[2] + context[11] + context[20] + context[29] + context[38] + context[47] + context[56] + context[65] + context[74]] ][0] for __g['l2'] in [context[1] + context[10] + context[19] + context[28] + context[37] + context[46] + context[55] + context[64] + context[73]] ][0] for __g['l1'] in [context[0] + context[9] + context[18] + context[27] + context[36] + context[45] + context[54] + context[63] + context[72]] ][0] for __g['h9'] in [context[72:81]] ][0] for __g['h8'] in [context[63:72]] ][0] for __g['h7'] in [context[54:63]] ][0] for __g['h6'] in [context[45:54]] ][0] for __g['h5'] in [context[36:45]] ][0] for __g['h4'] in [context[27:36]] ][0] for __g['h3'] in [context[18:27]] ][0] for __g['h2'] in [context[9:18]] ][0] for __g['h1'] in [context[0:9]] ][0])[1])[1])[1])[1])[1])[1])[1])[1])[1]) for __g['d'] in [[]] ][0] for __g['context'] in [input[5:-1]] ][0] for __g['fmt2'] in [input[(-1)]] ][0] for __g['fmt1'] in [input[0:5]] ][0])
for __g['input'] in [raw_input('Input your flag:')] ][0] if __name__ == '__main__' else __after())(lambda : None)
for __g['check1'], check1.__name__ in [(lambda arg: (lambda __l: [ (lambda __after: 0 if len(list(set(__l['arg']))) != 9 else 1)(lambda : None) for __l['arg'] in [arg] ][0])({}), 'check1')] ][0]
for __g['check'], check.__name__ in [(lambda arg: (lambda __l: [ sum(map(int, __l['arg'])) for __l['arg'] in [arg] ][0])({}), 'check')] ][0])(globals(), __import__('__builtin__', level=0).__dict__['print'])
# okay decompiling fu!k.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
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# 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: test233_ol.py
# Compiled at: 2020-03-20 13:22:50


(lambda __g, __print: [ [ (lambda __after: [

(lambda __after: (__print('Error len!'), (exit(), __after())[1])[1] if len(input) != 87 else __after())

(lambda :
[ [ [ [ (lambda __after: (__print('Error fmt!'), (exit(0), __after())[1])[1] if fmt1 != 'flag{' or fmt2 != '}' else __after())
(lambda : (d.append(context[0:9]), (d.append(context[9:18]), (d.append(context[18:27]), (d.append(context[27:36]), (d.append(context[36:45]), (d.append(context[45:54]), (d.append(context[54:63]), (d.append(context[63:72]), (d.append(context[72:81]), [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [


(lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[0][2] != '5' or d[0][3] != '3' else __after())

(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[1][0] != '8' or d[1][7] != '2' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[2][1] != '7' or d[2][4] != '1' or d[2][6] != '5' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[3][0] != '4' or d[3][5] != '5' or d[3][6] != '3' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[4][1] != '1' or d[4][4] != '7' or d[4][8] != '6' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[5][2] != '3' or d[5][3] != '2' or d[5][7] != '8' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[6][1] != '6' or d[6][3] != '5' or d[6][8] != '9' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[7][2] != '4' or d[7][7] != '3' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if d[8][5] != '9' or d[8][6] != '7' else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(h1) != 45 or check(h2) != 45 or check(h3) != 45 or check(h4) != 45 or check(h5) != 45 or check(h6) != 45 or check(h7) != 45 or check(h8) != 45 or check(h9) != 45 else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(l1) != 45 or check(l2) != 45 or check(l3) != 45 or check(l4) != 45 or check(l5) != 45 or check(l6) != 45 or check(l7) != 45 or check(l8) != 45 or check(l9) != 45 else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check(k1) != 45 or check(k2) != 45 or check(k3) != 45 or check(k4) != 45 or check(k5) != 45 or check(k6) != 45 or check(k7) != 45 or check(k8) != 45 or check(k9) != 45 else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(h1) != 1 or check1(h2) != 1 or check1(h3) != 1 or check1(h4) != 1 or check1(h5) != 1 or check1(h6) != 1 or check1(h7) != 1 or check1(h8) != 1 or check1(h9) != 1 else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(l1) != 1 or check1(l2) != 1 or check1(l3) != 1 or check1(l4) != 1 or check1(l5) != 1 or check1(l6) != 1 or check1(l7) != 1 or check1(l8) != 1 or check1(l9) != 1 else __after())
(lambda : (lambda __after: (__print('Error!'), (exit(), __after())[1])[1] if check1(k1) != 1 or check1(k2) != 1 or check1(k3) != 1 or check1(k4) != 1 or check1(k5) != 1 or check1(k6) != 1 or check1(k7) != 1 or check1(k8) != 1 or check1(k9) != 1 else __after())
(lambda : (__print('Yes! You got it!'), __after())[1]
)))))))))))))))


for __g['k9'] in [context[60] + context[61] + context[62] + context[69] + context[70] + context[71] + context[78] + context[79] + context[80]] ][0]
for __g['k8'] in [context[57] + context[58] + context[59] + context[66] + context[67] + context[68] + context[75] + context[76] + context[77]] ][0]
for __g['k7'] in [context[54] + context[55] + context[56] + context[63] + context[64] + context[65] + context[72] + context[73] + context[74]] ][0]
for __g['k6'] in [context[33] + context[34] + context[35] + context[42] + context[43] + context[44] + context[51] + context[52] + context[53]] ][0]
for __g['k5'] in [context[30] + context[31] + context[32] + context[39] + context[40] + context[41] + context[48] + context[49] + context[50]] ][0]
for __g['k4'] in [context[27] + context[28] + context[29] + context[36] + context[37] + context[38] + context[45] + context[46] + context[47]] ][0]
for __g['k3'] in [context[6] + context[7] + context[8] + context[15] + context[16] + context[17] + context[24] + context[25] + context[26]] ][0]
for __g['k2'] in [context[3] + context[4] + context[5] + context[12] + context[13] + context[14] + context[21] + context[22] + context[23]] ][0]
for __g['k1'] in [context[0] + context[1] + context[2] + context[9] + context[10] + context[11] + context[18] + context[19] + context[20]] ][0]



for __g['l9'] in [context[8] + context[17] + context[26] + context[35] + context[44] + context[53] + context[62] + context[71] + context[80]] ][0] # 竖
for __g['l8'] in [context[7] + context[16] + context[25] + context[34] + context[43] + context[52] + context[61] + context[70] + context[79]] ][0]
for __g['l7'] in [context[6] + context[15] + context[24] + context[33] + context[42] + context[51] + context[60] + context[69] + context[78]] ][0]
for __g['l6'] in [context[5] + context[14] + context[23] + context[32] + context[41] + context[50] + context[59] + context[68] + context[77]] ][0]
for __g['l5'] in [context[4] + context[13] + context[22] + context[31] + context[40] + context[49] + context[58] + context[67] + context[76]] ][0]
for __g['l4'] in [context[3] + context[12] + context[21] + context[30] + context[39] + context[48] + context[57] + context[66] + context[75]] ][0]
for __g['l3'] in [context[2] + context[11] + context[20] + context[29] + context[38] + context[47] + context[56] + context[65] + context[74]] ][0]
for __g['l2'] in [context[1] + context[10] + context[19] + context[28] + context[37] + context[46] + context[55] + context[64] + context[73]] ][0]
for __g['l1'] in [context[0] + context[9] + context[18] + context[27] + context[36] + context[45] + context[54] + context[63] + context[72]] ][0]


for __g['h9'] in [context[72:81]] ][0] # 横
for __g['h8'] in [context[63:72]] ][0]
for __g['h7'] in [context[54:63]] ][0]
for __g['h6'] in [context[45:54]] ][0]
for __g['h5'] in [context[36:45]] ][0]
for __g['h4'] in [context[27:36]] ][0]
for __g['h3'] in [context[18:27]] ][0]
for __g['h2'] in [context[9:18]] ][0]
for __g['h1'] in [context[0:9]] ][0])[1])[1])[1])[1])[1])[1])[1])[1])[1])



for __g['d'] in [[]] ][0]
for __g['context'] in [input[5:-1]] ][0]
for __g['fmt2'] in [input[(-1)]] ][0] # }
for __g['fmt1'] in [input[0:5]] ][0]) # flag{



for __g['input'] in [raw_input('Input your flag:')] ][0] if __name__ == '__main__' else __after())(lambda : None)

for __g['check1'], check1.__name__ in [(lambda arg: (lambda __l: [ (lambda __after: 0 if len(list(set(__l['arg']))) != 9 else 1)(lambda : None) for __l['arg'] in [arg] ][0])({}), 'check1')] ][0]

for __g['check'], check.__name__ in [(lambda arg: (lambda __l: [ sum(map(int, __l['arg'])) for __l['arg'] in [arg] ][0])({}), 'check')] ][0])(globals(), __import__('__builtin__', level=0).__dict__['print'])

注意这是python2,运行的话要注意下。

flag{}包裹着81个数字。

9个一组,check1检查9个元素不重复,check检查9个元素和为45.

9个元素的分法有三种,行为一组,列为一组,9*9矩阵内部的3*3矩阵为一组。这三种分法都要进行check和check1。

所以就是一个数独。

网上找到轮子,改改就能跑:

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
import re
import copy

# 默认模板,非标准数独 - 1000次平均耗时5ms/次
sudoku_template1 = [[1,0,0,0,0,0,0,0,0],
[0,2,0,0,0,0,0,0,0],
[0,0,3,0,0,0,0,0,0],
[0,0,0,4,0,0,0,0,0],
[0,0,0,0,5,0,0,0,0],
[0,0,0,0,0,6,0,0,0],
[0,0,0,0,0,0,7,0,0],
[0,0,0,0,0,0,0,8,0],
[0,0,0,0,0,0,0,0,9]]


# 芬兰数学家英卡拉(Arto Inkala)设计的号称“最难数独” - 1000次平均耗时320ms/次
sudoku_template2 = [[8,0,0,0,0,0,0,0,0],
[0,0,3,6,0,0,0,0,0],
[0,7,0,0,9,0,2,0,0],
[0,5,0,0,0,7,0,0,0],
[0,0,0,0,4,5,7,0,0],
[0,0,0,1,0,0,0,3,0],
[0,0,1,0,0,0,0,6,8],
[0,0,8,5,0,0,0,1,0],
[0,9,0,0,0,0,4,0,0]]

def crack_it(sudoku=sudoku_template1):
'''主函数,输入数独进行运算,如未输入则调用默认数独,格式为9x9的二维列表'''
init_sudoku = str_to_num(copy.deepcopy(sudoku)) # Python的坑!列表或字典等对象作为函数参数时,函数可能修改其元素的指针,导致外部列表也会改变
if is_valid_sudoku(sudoku): # 判断输入的Sudoku是否合理(是否冲突)
candidate_list = filter_candidate_list(init_sudoku, init_candidate_list(init_sudoku), start=0) # 针对Sudoku中的每一个空格(空格都默认填入数字0),都算出其可能的备选数,存入data_list中;每当空格被确认唯一值时,剩余data_list都需要再被刷新
cracked_sudoku = fill_blank(init_sudoku, candidate_list, start=0) # 破解数独
print(cracked_sudoku)
print_sudoku(cracked_sudoku) # 在控制台显示已破解的数独,默认开启
return cracked_sudoku
else:
return '请检查一下输入是否有误- -0'

def str_to_num(data):
'''初步校验+统一格式,空字符转0,无效字符转0'''
for i in range(9):
for j in range(9):
if re.match('[1-9]', str(data[i][j])): # 1-9字符转int 1-9
data[i][j] = int(data[i][j])
elif re.match('', str(data[i][j])): # 空位转int 0
data[i][j] = 0
else: # 无效字符转int 0,或者也可以return False,拒绝服务
data[i][j] = 0
return data


def is_valid_sudoku(data):
'''判断整个数独是否有效'''
for y in range(9):
for x in range(9):
if data[y][x] > 9:
return False

if data[y][x] != 0 and data[y].count(data[y][x]) > 1:
return False

for col in range(9):
if data[y][x] != 0 and col != y:
if data[col][x] == data[y][x]:
return False

for i in range(3):
for j in range(3):
if data[y][x] != 0 and (i+3*(y//3), j+3*(x//3)) != (y, x):
if data[i+3*(y//3)][j+3*(x//3)] == data[y][x]:
return False
return True

def init_candidate_list(data):
'''初始化建立一个数独的备选数列表,一个空格就对应其坐标以及填上1~9的备选数字,格式为81x9的二维列表'''
data_list = []
for y in range(9):
for x in range(9):
if data[y][x] == 0:
data_list.append([(x, y), [1, 2, 3, 4, 5, 6, 7, 8, 9]])
return data_list

def filter_candidate_list(data, data_list, start):
'''对数独的备选数表进行过滤,删除无效的备选数'''
for blank_index in range(start, len(data_list)):
data_list[blank_index][1] = []
for num in range(1,10):
if is_valid_num(data, data_list[blank_index][0][0], data_list[blank_index][0][1], num):
data_list[blank_index][1].append(num)
return data_list

def is_valid_num(data, x, y, num):
'''输入数独、坐标、数字,判断该位置填入该数字是否合理'''
if data[y].count(num) > 0: # 行判断
return False

for col in range(9): # 列判断
if data[col][x] == num:
return False

for a in range(3): # 九宫格判断
for b in range(3):
if data[a+3*(y//3)][b+3*(x//3)] == num:
return False
return True

def fill_blank(data, data_list, start):
'''
核心函数,递归尝试代入备选数,类似深度优先遍历算法。
一旦某位置填入为True(由is_valid_num函数判断),则开始下一位置的填入;若某位置填入为False,则return回上一级。
参数解释:
data: 数独矩阵,二维列表
data_list: 备选数表,二维列表
start: 递归进行的位置,对应data_list的下标
'''
all_data = []
if start < len(data_list):
one = data_list[start]
for num in one[1]:
if is_valid_num(data, one[0][0], one[0][1], num):
data[one[0][1]][one[0][0]] = num # 赋值,如果能给每一格成功赋值,则意味破解成功;如果出现失败,则需要将错误赋值清零
# data_list = filter_candidate_list(data, data_list, start) # 每一步赋值都会改变备选数表,但刷新备选数表的操作非常耗时,若加上这句,速度会慢100倍
tem_data = fill_blank(data, data_list, start+1) # start+1,使递归进入下一格点
if tem_data: # 注意!如果下一格点return,分两种情况:1.成功破解所有格点;2.发生错误,for loop结束也会return,此时返回值为None
return tem_data
data[one[0][1]][one[0][0]] = 0 # 注意!可能向下递归了若干格才发现前面是错误的(即for loop结束,return None),此时需要将所有错误的赋值清零。
else:
return data

def print_sudoku(data):
'''打印数独到控制台'''
print('>>> 破解结果:')
for i in range(9):
for j in range(9):
print('{:^3}'.format(data[i][j]), end='')
print('')
print('')

if __name__ == '__main__':
l = [
[0,0,5,3,0,0,0,0,0],
[8,0,0,0,0,0,0,2,0],
[0,7,0,0,1,0,5,0,0],
[4,0,0,0,0,5,3,0,0],
[0,1,0,0,7,0,0,0,6],
[0,0,3,2,0,0,0,8,0],
[0,6,0,5,0,0,0,0,9],
[0,0,4,0,0,0,0,3,0],
[0,0,0,0,0,9,7,0,0],
]
crack_it(l)

result = [[1, 4, 5, 3, 2, 7, 6, 9, 8], [8, 3, 9, 6, 5, 4, 1, 2, 7], [6, 7, 2, 9, 1, 8, 5, 4, 3], [4, 9, 6, 1, 8, 5, 3, 7, 2], [2, 1, 8, 4, 7, 3, 9, 5, 6], [7, 5, 3, 2, 9, 6, 4, 8, 1], [3, 6, 7, 5, 4, 2, 8, 1, 9], [9, 8, 4, 7, 6, 1, 2, 3, 5], [5, 2, 1, 8, 3, 9, 7, 6, 4]]
print('flag{',end='')
for i in result:
for j in i:
print(j,end='')
print('}')

baby取证

misc2

linux下file一波,发现是流量包

小鲨鱼打开,发现是一个用于电力控制的协议——IEC104

image-20200927105727265

主要流程就是一方发送ASDU,这个是包含数据的。

另一方发送类似于已接受序列号的东西。

IEC104协议的帧格式有三种(I帧、U帧、S帧),基本格式如下图所示:

12928033-9240deeccc11f675

I帧为信息帧,用于传输数据,长度大于6个字节,为长帧;

S帧为确认帧,用于确认接收的I帧,长度为6个字节,为短帧;

U帧为控制帧,用于控制启动/停止/测试,长度为6个字节,为短帧;

我们只许看后面跟着asdu的I帧:

主要数据如下:

image-20200927110253535

image-20200927110242400

上图:

01 类型标示,01表示01---不带时标的单点遥信,每个遥信占1个字节

遥信:

01—不带时标的单点遥信,每个遥信占1个字节

03—不带时标的双点遥信,每个遥信占1个字节

14—具有状态变位检测的成组单点遥信,每个字节包括8个遥信

SOE:记录即事件顺序记录

02—带3个字节短时标的单点遥信

04—带3个字节短时标的双点遥信

1E—带7个字节时标的单点遥信

1F—带7个字节时标的双点遥信

遥调:

0F—不带时标的电度量,每个电度量占5个字节

10—带3个字节短时标的电度量,每个电度量占8个字节

25—带7个字节长时标的电度量,每个电度量占12个字节

其他:

2D—单点遥控

2E—双点遥控

2F—双点遥调

64—召唤全数据

65—召唤全电度

67—时钟同步

常用的传送原因列表:

1—周期,循环

2—背景扫描

3—突发,自发上传

4—初始化

5—请求或被请求

6—激活

7—激活确认

8—停止激活

9—停止激活确认

0A—激活结束

14—响应总召唤

01 可变结构限定词,有1个变位遥信上送

03 00 传输原因,03 00 表示突发传输

01 00 传输地址,这个流量包的asdu的传输地址都为1

02 00 00 信息体地址IOA,这个流量包内的主要差异就在于这个IOA的变化。

后面的01是信息,不同的类型标示对应不同的信息长度,是变长的。

对于这条封包,意思就是通过遥信,向ioa处的地址写入1.

将流量包内所有的asdu的ioa都提取出来,依次按bit写1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def hex2char(h):
h = h[2:]
s = ''
for i in range(len(h)//2):
n = h[i*2:i*2+2]
s += chr(int(n, 16))
return s

def get_md5(b):
import hashlib
return hashlib.md5(b).hexdigest()

l = [2, 3, 6, 7, 10, 11, 13, 14, 19, 20, 22, 26, 27, 30, 31, 32, 34, 36, 37, 38, 39, 40, 42, 46, 47, 50, 53, 54, 58, 64, 66, 70, 71, 72]
bl = list('~' + '0' * 8 * 9)
for i in range(1, 73):
if i in l:
bl[i] = '1'
bs = ''.join(bl)[1:]
hn = hex(int(bs, 2))
print(hn)
sn = hex2char(hn)
print(sn)
md5 = get_md5(sn.encode())
print('flag{%s}' % md5)

注意到最后的是72,所以猜测可能是18来索引的bit,而不是常用的07

脚本输出:

1
2
3
0x666c34675f464c4147
fl4g_FLAG
flag{1f363c8468013726578830465d4739fe}