这比赛没学到啥有意义的新知识。逆向有两道题是常规题,付出一定时间大家都能做出来,还有一题全场零解,还没给提示,赛后也没wp。misc很有意思,可惜我以后不走工控安全这条路。
virus
走四次迷宫
dddddddddsssssaaaaaaaaawww
sdsdsdsdsdsdsddwdwdwdwdwdwdw
aaaaaaaaasssssssddddddddd
wwwwwdddddddddsssss
不过flag的格式有点升级
意思是-和-之间的字符数,也就是走迷宫的步数。
那个判断数字是在v14=0,也就是还没扫描到-的时候,进行判断的,是数字的话就存储,直到出现了-。
后面check flag的时候,会根据先后的数字依次进行check。
根据规定的步数,因此只能有一种走法:
flag{4312-wwwwwdddddddddsssss-aaaaaaaaasssssssddddddddd-dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw}
fu!k.pyc
uncompyle6拿到源码:
# 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
整理下:
# 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。
所以就是一个数独。
网上找到轮子,改改就能跑:
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
主要流程就是一方发送ASDU,这个是包含数据的。
另一方发送类似于已接受序列号的东西。
IEC104协议的帧格式有三种(I帧、U帧、S帧),基本格式如下图所示:
I帧为信息帧,用于传输数据,长度大于6个字节,为长帧;
S帧为确认帧,用于确认接收的I帧,长度为6个字节,为短帧;
U帧为控制帧,用于控制启动/停止/测试,长度为6个字节,为短帧;
我们只许看后面跟着asdu的I帧:
主要数据如下:
上图:
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:
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,所以猜测可能是1~8来索引的bit,而不是常用的0~7
脚本输出:
0x666c34675f464c4147
fl4g_FLAG
flag{1f363c8468013726578830465d4739fe}