收获

  • Python逆向

  • 迷宫题的处理方法

    1. 将迷宫中的 “1” 去掉,只关注 “0” 的上下左右
    2. 利用走迷宫脚本
  • 在线 MD5 加密,如果字符串结尾有回车符之类的,可能会导致结果不一样


【SWPUCTF】老鼠走迷宫


思路

拖入 Exeinfo PE,由 PyInstaller 可知为 Python 逆向

SWPUCTF-老鼠走迷宫1.png

使用 pyinstxtractor.py 进行解包:

SWPUCTF-老鼠走迷宫2.png

在解包后的文件夹中发现无后缀名的 5 文件,且 Exeinfo PE 无法识别该文件的类型

SWPUCTF-老鼠走迷宫3.png

在 WinHex 中与 struct 文件对比后发现,文件 5 缺失了第一行的十六进制数据
将 struct 文件的第一行拷贝到 5 文件的第一行进行修复
修复后 Exeinfo PE 可识别为 .pyc 文件

在虚拟机的 python 3.8 下反编译:

SWPUCTF-老鼠走迷宫4.png

将代码复制出来:

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}

SWPUCTF-老鼠走迷宫5.png