【SWPUCTF】老鼠走迷宫
收获
Python逆向
迷宫题的处理方法
- 将迷宫中的 “1” 去掉,只关注 “0” 的上下左右
- 利用走迷宫脚本
在线 MD5 加密,如果字符串结尾有回车符之类的,可能会导致结果不一样
思路
拖入 Exeinfo PE,由 PyInstaller 可知为 Python 逆向
使用 pyinstxtractor.py
进行解包:
在解包后的文件夹中发现无后缀名的 5 文件,且 Exeinfo PE 无法识别该文件的类型
在 WinHex 中与 struct 文件对比后发现,文件 5 缺失了第一行的十六进制数据
将 struct 文件的第一行拷贝到 5 文件的第一行进行修复
修复后 Exeinfo PE 可识别为 .pyc 文件
在虚拟机的 python 3.8 下反编译:
将代码复制出来:
import random, msvcrt
row, col = (12, 12)
i, j = (0, 0)
maze = [
[1, 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, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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, 0, 1]]
print('Mice walk in a maze: wasd to move,q to quit')
print("flag is the shortest path's md5,example:if the shortest path is wasdsdw,the flag is md5('wasdsdw')")
i, j = (0, 1)
n = 0
while 1:
if i == row * 2:
if j == col * 2 - 1:
print('ohhhh!!!!you did it')
break
print('your position:({},{})'.format(i, j))
inp = msvcrt.getch()
n += 1
ti, tj = i, j
if b'a' == inp and i > 0:
tj -= 1
else:
if b'w' == inp and j > 0:
ti -= 1
else:
if b's' == inp and j < row * 2:
ti += 1
else:
if b'd' == inp and i < col * 2:
tj += 1
else:
if b'q' == inp:
exit('bye!!')
else:
print('What???')
continue
if maze[ti][tj] == 1:
print(random.choice(['no wayy!!', "it's wall", 'nop']))
continue
elif maze[ti][tj] == 0:
print(random.choice(['nice!!', 'yeah!!', 'Go on']))
i, j = ti, tj
根据代码逻辑,i, j = (0, 1)
代表初始位置在 (0, 1),即迷宫的左上角那个 0 的地方,1 代表墙壁,只能顺着 0 的地方走
后面的代码就是控制每一步的移动,上下左右分别用 “wsad” 代替
因此不需要运行后面的代码,只需要自己得出最终路径即可
这里可以将迷宫中的 "1"
去掉,只需要关注 "0"
的上下左右即可:
[ , 0, , , , , , , , , , , , , , , , , , , , , , , ],
[ , 0, , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, , 0, ],
[ , 0, , 0, , , , , , , , , , , , , , 0, , , , 0, , 0, ],
[ , 0, , 0, 0, 0, 0, 0, , 0, 0, 0, , 0, 0, 0, 0, 0, , 0, 0, 0, , 0, ],
[ , 0, , , , , , 0, , 0, , 0, , 0, , , , , , 0, , , , 0, ],
[ , 0, 0, 0, , 0, 0, 0, , 0, , 0, , 0, , 0, , 0, 0, 0, , 0, 0, 0, ],
[ , , , 0, , , , , , 0, , 0, , 0, , 0, , 0, , , , , , 0, ],
[ , 0, , 0, 0, 0, , 0, 0, 0, , 0, 0, 0, , 0, , 0, 0, 0, 0, 0, , 0, ],
[ , 0, , , , 0, , 0, , , , , , , , 0, , , , , , 0, , 0, ],
[ , 0, 0, 0, 0, 0, , 0, 0, 0, 0, 0, , 0, 0, 0, 0, 0, , 0, , 0, 0, 0, ],
[ , 0, , , , , , , , 0, , 0, , 0, , , , 0, , 0, , , , 0, ],
[ , 0, , 0, 0, 0, 0, 0, , 0, , 0, , 0, 0, 0, , 0, 0, 0, , 0, 0, 0, ],
[ , 0, , 0, , , , 0, , , , 0, , 0, , 0, , , , 0, , 0, , , ],
[ , 0, 0, 0, , 0, , 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, , 0, , 0, ],
[ , , , , , 0, , 0, , 0, , , , 0, , , , 0, , 0, , 0, , 0, ],
[ , 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, , 0, , 0, ],
[ , 0, , 0, , 0, , 0, , 0, , 0, , , , 0, , , , , , 0, , 0, ],
[ , 0, , 0, , 0, 0, 0, , 0, , 0, , 0, 0, 0, , 0, 0, 0, , 0, 0, 0, ],
[ , 0, , 0, , , , , , 0, , 0, , 0, , , , 0, , 0, , , , 0, ],
[ , 0, , 0, 0, 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, ],
[ , 0, , , , 0, , , , , , 0, , , , 0, , 0, , , , 0, , 0, ],
[ , 0, , 0, 0, 0, , 0, 0, 0, , 0, , 0, 0, 0, , 0, , 0, , 0, , 0, ],
[ , 0, , 0, , , , 0, , 0, , 0, , 0, , , , 0, , 0, , 0, , 0, ],
[ , 0, 0, 0, 0, 0, 0, 0, , 0, 0, 0, , 0, 0, 0, 0, 0, 0, 0, , 0, 0, 0, ],
[ , , , , , , , , , , , , , , , , , , , , , , , 0, ]
走一遍即可得出路径:sssssddssddssaaaassssddwwddddssssssaawwaassssddssaassddddwwddssddwwwwwwwwaawwddwwwwaaaawwddwwwwddssssddwwwwddddwwddddssaassaassddddssddssaassssssddsssssss
将路径进行 MD5 加密后的结果就是 flag (用在线工具时,留意回车字符,有时会导致结果不一样)
脚本
maze = [
[1, 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, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 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, 0, 1]]
usedmap = [[0 for i in range(len(maze[0]))] for i in range(len(maze))]
# 生成与迷宫相同规格的全0列表,用来记录已经走过的位置
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[x + 1][y] == 0 and usedmap[x + 1][y] == 0: # 可以往下走
usedmap[x][y] = 1 # 将现在所处的点标记,因为不能再走,否则会兜圈子
flag += 's' # 向下走,记录路径
dfs(x + 1, y) # 从下一个位置开始走
flag = flag[:-1]
usedmap[x][y] = 0 # 遇到死胡同,回退到标记的地方
if maze[x - 1][y] == 0 and usedmap[x - 1][y] == 0: # 可以往上走
usedmap[x][y] = 1 # 将现在所处的点标记,因为不能再走,否则会兜圈子
flag += 'w' # 向上走,记录路径
dfs(x - 1, y) # 从下一个位置开始走
flag = flag[:-1]
usedmap[x][y] = 0 # 遇到死胡同,回退到标记的地方
if maze[x][y + 1] == 0 and usedmap[x][y + 1] == 0: # 可以往右走
usedmap[x][y] = 1 # 将现在所处的点标记,因为不能再走,否则会兜圈子
flag += 'd' # 向右走,记录路径
dfs(x, y + 1) # 从下一个位置开始走
flag = flag[:-1]
usedmap[x][y] = 0 # 遇到死胡同,回退到标记的地方
if maze[x][y - 1] == 0 and usedmap[x][y - 1] == 0: # 可以往左走
usedmap[x][y] = 1 # 将现在所处的点标记,因为不能再走,否则会兜圈子
flag += 'a' # 向左走,记录路径
dfs(x, y - 1) # 从下一个位置开始走
flag = flag[:-1]
usedmap[x][y] = 0 # 遇到死胡同,回退到标记的地方
dfs(sti, stj)
结果
NSSCTF{69193150b15c87d39252d974bc323217}
评论