前言:该篇文章会介绍一个在ctf当中reverse方向中常见的一种迷宫题,我从攻防世界中选取了一道比较有代表性的题目,逐一讲解,并且每个思路都相当清晰透彻,借此分享,相信看完之后对于迷宫类型的题目会有更深的理解。
例题1:攻防世界-reverse_re3 第一步 首先看有无壳,直接丢到exeinfope—发现是elf文件是linux的可执行程序
第二步 反手丢进ida看到main 直接F5反编译看一手
第三步 一个一个函数来,sub_11B4双击点开好像没啥东西,看看sub_940
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 __int64 sub_940() { int v0; // eax int v2; // [rsp+8h] [rbp-218h] int v3; // [rsp+Ch] [rbp-214h] char v4[520]; // [rsp+10h] [rbp-210h] BYREF unsigned __int64 v5; // [rsp+218h] [rbp-8h] v5 = __readfsqword(0x28u); v3 = 0; memset(v4, 0, 0x200uLL); _isoc99_scanf(&unk_1278, v4, v4); while ( 1 ) { do { v2 = 0; sub_86C(); v0 = v4[v3]; if ( v0 == 'd' ) //原题是ascii码可以对着ascii按"r" 快捷键转成字符 { v2 = sub_E23(); } else if ( v0 > 'd' ) //wasd很明显就是游戏里常见的移动键呗 { if ( v0 == 's' ) { v2 = sub_C5A(); } else if ( v0 == 'w' ) { v2 = sub_A92(); } } else { if ( v0 == 27 ) return 0xFFFFFFFFLL; if ( v0 == 'a' ) v2 = sub_FEC(); } ++v3; } while ( v2 != 1 ); if ( dword_202AB0 == 2 ) break; ++dword_202AB0; } puts("success! the flag is flag{md5(your input)}" ); return 1LL; }
这里留个心眼,flag是要输入的md5值
接下来分析wasd到底是怎么走的(像这种题大概率就是迷宫图,所以要明白它是怎么运动的)
先打开sub_E23康康
第四步 千万不要给这几个变量绕晕了
dword_202020:其实就是题目给的地图,可以双击进去看看(shift+e 提取数据)
dword_202AB0:代表哪个迷宫,此题有3个迷宫(至于为什么后文会提及)
dword_202AB4:代表行(因为15*,说明可能是一行15个数字,大胆猜测!)
dword_202AB8:代表列
225:地图尺寸15*15
这里我转换了一下不容易混淆
第五步 第一个if!=14 是因为跟下标有关系,一行15个数字下标最大是14,我们这个函数是”d“的操作也就是向右移,所以是如果下标等于14的话就不能再”d“了 第二个if 判断当前位置右移的数字是不是1,如果是将该位置标志为3,之前的位置标志为1,其实就是暗示我们1是可以走的,而3其实是我们的起点,如果不理解后面看看迷宫就明白了, 第三个if如果右移后是4就返回1,说明4就是我们的终点
再看看上下移动的函数(下图是”s“的函数,也就是下移)——有一些题目上下移动不是单纯的往上或者往下 而是斜向下或者斜向上噢
第六步 每次加15说明每次加一行
注意:这里分析的是右移”d“和下移”s“的函数至于”w“ ”a“都是差不多的,这里就不过多赘述了
再回到sub_940函数
第七步 这里的dword_202AB0==2 我们在前面提到它可能是标识哪一个迷宫的,这里说==2的话就break,否则就++,说明这里会循环3次,说明会有3个迷宫,接下来我们来看看这个稍微的迷宫长什么样。
双击点开前文提到的dword_202020
第八步 这密密麻麻的数字就是它的数据啦,现在按shift+e提取数据,然后导出来
这里有个大大大坑,就是dword类型的数据是4位一组,只取第一位作为数值,也就是说100010000111 最终会变成110 ,后3位是填充的,接下来就是怎么转换成一个迷宫了,网上一堆wp却几乎没有人提到如何去把这份原始数据转换成迷宫,下面我提供了一个python脚本针对这道题目,只要运行即可得到迷宫的样子,
一开始数据是这样的,先利用记事本的功能替换掉 ,和空格 以及前面的括号等等
之后利用一下py脚本即可完成转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 input_string = input ("请输入需要处理的字符串:" ) output_string = input_string.replace("\n" , "" ) ZeK1D = output_string.replace(" " , "" ) def extract_chars (input_string ): chunks = [input_string[i:i+4 ] for i in range (0 , len (input_string), 4 )] first_chars = [chunk[0 ] for chunk in chunks if chunk] output= '' .join(first_chars) print (output) extract_chars(ZeK1D)
之后可以将输出结果复制到word 改格式会好看一点
第九步 之后再按每15行为一个迷宫分成3个小迷宫,以3为起点4为终点进行运动,之后再md5加密即可得到flag
第一个迷宫
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
第二个迷宫
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0]
[1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0]
[1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
第三个迷宫
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]
行动轨迹为:ddsssddddsssdssdddddsssddddsssaassssdddsddssddwddssssssdddssssdddss
经过md5编码后flag是flag{aeea66fcac7fa80ed8f79f38ad5bb953}
总结: 逆向遇到迷宫题的思路大概分2点
1.弄清楚移动的方式
2.分析迷宫图的尺寸
3.手动走迷宫或写脚本走迷宫(建议BFS算法)
例题2 查壳,放ida
注意flag是md5(留个心眼),然后去动态调试找flag,这个createmap非常显眼
先下个断点,然后开始调试
任意输入一些,然后去search map
这里的快捷键有ctrl+T,查找下一个text
找到后shift+E提取数据,然后放入我们的脚本文件
修改脚本中行列参数,运行脚本得到16*16的二维列表
将二维列表复制到【二.(一) 】中的**<脚本二:获得迷宫路径>**中
分析check()函数得到起点坐标为(15, 1),且本题未给出确切终点而是在main函数中给出了路径长为54
并且用aswd键位移动
这里附上最终代码
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 from collections import dequestr = [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] s = 0 row = 16 col = 16 maze = []for i in range (row): tmp = [] for j in range (col): tmp.append(str [s]) s += 1 maze.append(tmp) print (maze) path_len = 54 +1 def bfs (start, end, barrier ): directions = [(0 , 1 ), (1 , 0 ), (0 , -1 ), (-1 , 0 )] for i in range (len (maze)): for j in range (len (maze[i])): if (maze[i][j] == start): start = (i, j) if (maze[i][j] == end): end = (i, j) queue = deque() queue.append((start, [start])) visited = set () visited.add(start) while queue: position, path = queue.popleft() if position == end: return path elif len (path) == path_len: return path for d in directions: next_position = (position[0 ] + d[0 ], position[1 ] + d[1 ]) if 0 <= next_position[0 ] < len (maze) and 0 <= next_position[1 ] < len (maze[0 ]) and \ maze[next_position[0 ]][next_position[1 ]] != barrier and next_position not in visited: queue.append((next_position, path + [next_position])) visited.add(next_position) return None if __name__ == '__main__' : maze[15 ][1 ]='S' path = bfs('S' , 'E' , 1 ) print ("移动路径坐标:" , path) print ("移动路径方位:" , end='' ) for i in range (1 , len (path)): x1, y1, x2, y2 = path[i - 1 ][0 ], path[i - 1 ][1 ], path[i][0 ], path[i][1 ] if (x1 > x2): print ("w" , end='' ) elif (x1 < x2): print ("s" , end='' ) elif (y1 > y2): print ("a" , end='' ) elif (y1 < y2): print ("d" , end='' )
exp 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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # str为ida中使用快捷键[shift+e]提取到的数据, 如果提取的是string literal则加上引号视作字符串,如果是C array(decimal)则加上中括号视作列表 str = [ 1, 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1, 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1, 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1, 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0, 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 0 , 1, 1 , 0 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1, 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 0, 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1, 1 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 1, 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0, 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1, 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0, 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1, 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1, 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0, 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0, 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 0, 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1, 0 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0, 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0, 1 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1, 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1, 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, 1 , 1 , 1 , 1 , 1 ]#待输入的迷宫数组 s = 0 # s用作索引访问str, 供下面tmp列表取值 # 分析题目后设置迷宫的行列 row = 16 # 设置二维迷宫行数 col = 16 # 设置二维迷宫列数 maze = []for i in range(row): tmp = [] for j in range(col): tmp.append(str[s]) s += 1 maze.append(tmp) # 凑一行添加一行到迷宫中 print(maze)
2) 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 from collections import deque maze = [] path_len = 0x7fffffff def bfs (start, end, barrier ): directions = [(0 , 1 ), (1 , 0 ), (0 , -1 ), (-1 , 0 )] for i in range (len (maze)): for j in range (len (maze[i])): if (maze[i][j] == start): start = (i, j) if (maze[i][j] == end): end = (i, j) queue = deque() queue.append((start, [start])) visited = set () visited.add(start) while queue: position, path = queue.popleft() if position == end: return path elif len (path) == path_len: return path for d in directions: next_position = (position[0 ] + d[0 ], position[1 ] + d[1 ]) if 0 <= next_position[0 ] < len (maze) and 0 <= next_position[1 ] < len (maze[0 ]) and \ maze[next_position[0 ]][next_position[1 ]] != barrier and next_position not in visited: queue.append((next_position, path + [next_position])) visited.add(next_position) return None if __name__ == '__main__' : path = bfs('S' , 'E' , 1 ) print ("移动路径坐标:" , path) print ("移动路径方位:" , end='' ) for i in range (1 , len (path)): x1, y1, x2, y2 = path[i - 1 ][0 ], path[i - 1 ][1 ], path[i][0 ], path[i][1 ] if (x1 > x2): print ("w" , end='' ) elif (x1 < x2): print ("s" , end='' ) elif (y1 > y2): print ("a" , end='' ) elif (y1 < y2): print ("d" , end='' )
wsad可以根据题目要求更改键位
3) 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 maze = usedmap= sti=0 stj=1 edi=24 edj=23 flag='' def dfs(x,y): global flag if x==edi and y==edj: print(flag) return if maze==0 and usedmap==0: usedmap=1 flag+='s' dfs(x+1,y) flag=flag usedmap=0 if maze==0 and usedmap==0: usedmap=1 flag+='w' dfs(x-1,y) flag=flag usedmap=0 if maze==0 and usedmap==0: usedmap=1 flag+='d' dfs(x,y+1) flag=flag usedmap=0 if maze==0 and usedmap==0: usedmap=1 flag+='a' dfs(x,y-1) flag=flag usedmap=0 dfs(sti,stj) ''' for i in range(len(maze)): for j in range(len(maze)): print(maze,end='') print() '''
例题3 doublegame
运行
ctrl F搜索gameover出现的地方,然后x查找调用函数
(key非预期)发现有个可疑的数据,是key=13371337
key正常
发现key ^0x1DC4=13376013
静态分析发现,sub_14001136B函数是第二关,将去第二关路上的 if的字节码全部修改为相反的, 然后patch,重新调试 (记得备份)
或者找到迷宫,
先拿出迷宫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 maze=''' strcpy(Buffer, "000000000000000000000"); strcpy(v4, "0 0 0 0 0 0 0"); strcpy(&v4[22], "0 0 0 00000 00000 0 0"); strcpy(v5, "0 0 0 0"); strcpy(&v5[22], "0 000 000 0 000 0 0 0"); strcpy(v6, "0 0 0 0 0 0 0 0"); strcpy(&v6[22], "0 0 0 00000 000 000 0"); strcpy(v7, "0 0 0 0 0 0 "); strcpy(&v7[22], "0 000 0 0 000 0 0 0 0"); strcpy(v8, "0 0 0 0 0 0 0 0 0"); strcpy(&v8[22], "0 00000 000 000 0 0 0"); strcpy(v9, "0 0 0 0 0"); strcpy(&v9[22], "000 0 0 0 000 0 0 0 0"); strcpy(v10, "0 0 0 0 0 0 * 0 0 0 0"); strcpy(&v10[22], "0 0000000 0 000 00000"); strcpy(v11, "@ 0 0 0 0"); strcpy(&v11[22], "0 0 0 0 0 00000000000"); strcpy(v12, "0 0 0 0 0"); strcpy(&v12[22], "000 0 00000 0 000 000"); strcpy(v13, "0 0 0 0 0"); strcpy(&v13[22], "000000000000000000000");''' maze=[(i[-24:-3]) for i in maze.split('\n')] for i in maze: print(i)
然后运行脚本
exp 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 maze =''' strcpy(Buffer, "000000000000000000000" ); strcpy (v4, "0 0 0 0 0 0 0" ); strcpy (&v4[22 ], "0 0 0 00000 00000 0 0" ); strcpy (v5, "0 0 0 0" ); strcpy (&v5[22 ], "0 000 000 0 000 0 0 0" ); strcpy (v6, "0 0 0 0 0 0 0 0" ); strcpy (&v6[22 ], "0 0 0 00000 000 000 0" ); strcpy (v7, "0 0 0 0 0 0 " ); strcpy (&v7[22 ], "0 000 0 0 000 0 0 0 0" ); strcpy (v8, "0 0 0 0 0 0 0 0 0" ); strcpy (&v8[22 ], "0 00000 000 000 0 0 0" ); strcpy (v9, "0 0 0 0 0" ); strcpy (&v9[22 ], "000 0 0 0 000 0 0 0 0" ); strcpy (v10, "0 0 0 0 0 0 * 0 0 0 0" ); strcpy (&v10[22 ], "0 0000000 0 000 00000" ); strcpy (v11, "@ 0 0 0 0" ); strcpy (&v11[22 ], "0 0 0 0 0 00000000000" ); strcpy (v12, "0 0 0 0 0" ); strcpy (&v12[22 ], "000 0 00000 0 000 000" ); strcpy (v13, "0 0 0 0 0" ); strcpy (&v13[22 ], "000000000000000000000" );'''maze =[(i[-24 :-3 ]) for i in maze.split('\n')]for i in maze: print (i)from hashlib import md5def finda(d): x ,y=d[0 ],d[1 ]-1 return (x,y,'a')def findw(d): x ,y=d[0 ]-1 ,d[1 ] return (x,y,'w')def finds(d): x ,y=d[0 ]+1 ,d[1 ] return (x,y,'s')def findd(d): x ,y=d[0 ],d[1 ]+1 return (x,y,'d')def find0(d,row,column): if d[0 ]==0 : t =[finda(d),findd(d),finds(d)] elif d[0 ]==row-1 : t =[findw(d),finda(d),findd(d)] elif d[1 ]==0 : t =[findw(d),findd(d),finds(d)] elif d[1 ]==column-1 : t =[findw(d),finda(d),finds(d)] else : t=[findw(d),finda(d),finds(d),findd(d)] tmp =[] for x,y,r in t: if maze[x][y]==' 'or maze[x][y]=='*' : tmp .append((x,y,r)) return tmpdef get(o,O,row,column):#起点,终点,行,列 SUM =[] Road = [('', o)] while True: road =[] for (r_pre,d) in Road: if d==O:#终点 SUM .append((len(r_pre),r_pre,)) print (r_pre.encode()) print ('NSSCTF{'+md5(r_pre.encode()).hexdigest()+'13371337 '+'}') exit () next =find0(d,row,column) for x,y,r in next: if len(r_pre)>=1 : if 'ws'in r_pre[-1 ]+r or 'sw' in r_pre[-1 ]+r: continue if 'ad' in r_pre[-1 ] + r or 'da' in r_pre[-1 ] + r: continue road .append((r_pre+r,(x,y))) Road =roadrow ,column=21 ,21 get ((15 ,0 ),(7 ,20 ),row,column)