玄机靶场:2024铁人三项决赛CTF RE - mapmap 解题笔记
2024铁人三项决赛CTF RE - mapmap 解题笔记题目信息题目名称mapmap题目描述命令行的迷宫题目类型REVERSE逆向赛事2024年第一届长城杯信息安全铁人三项赛线下决赛初步分析拿到题目附件后file命令确认是一个 Linux ELF 可执行文件。运行程序发现它接受键盘输入输入w/a/s/d四个方向键来控制移动输入错误路径时程序输出false走到终点则输出 flag。题目描述命令行的迷宫已经给出了明确提示这是一道迷宫类逆向题核心是找到从起点到终点的正确路径。逆向分析加载进 IDA 分析主逻辑程序结构相对清晰迷宫参数迷宫大小39×39坐标范围 0~38起点(0, 0)终点(38, 38)路径长度恰好 140 步移动规则wy 坐标减 1向上sy 坐标加 1向下ax 坐标减 1向左dx 坐标加 1向右校验逻辑程序在每次输入后实时校验当前路径是否合法走到墙壁或越界时输出false。这个特性非常关键——可以利用程序本身作为迷宫验证器通过与程序交互来探测哪些方向可以走。直接静态分析的困难迷宫的地图数据在程序中以较为复杂的方式存储直接从二进制中提取地图并不直观。考虑到程序提供了实时反馈走错就输出false更高效的方案是利用程序的这一特性进行动态爆破。解题思路动态爆破 DFS核心思路是对程序做一处 patch让它在输出false时不退出而是继续接受输入然后编写脚本通过 DFS深度优先搜索枚举所有可能的路径每走一步就调用程序验证以此探测出完整的迷宫路径。Patch 方案找到程序中输出false后的跳转指令将其修改为 NOP 或改变跳转方向使程序在遇到错误路径时不终止而是继续等待输入。这样脚本就可以持续与程序交互。DFS 爆破脚本逻辑importsubprocessdeftest_opt(data):returnsubprocess.run(./mapmap_p,inputdata.encode(),capture_outputTrue).stdoutdefis_wrong(output):returnbfalseinoutputdefget_enums(inp):# 限制连续反向移动优化搜索效率iflen(inp)0:return[w,a,s,d]last_cinp[-1]iflast_cw:return[w,a,d]eliflast_ca:return[w,a,s]eliflast_cs:return[a,s,d]eliflast_cd:return[w,s,d]ansx,y0,0vis[[0]*39for_inrange(39)]defdfs(depth):globalx,y,ans,visifdepth140:ifx38andy38:print(ans)exit(1)returnfordinget_enums(ans):nx,nyx,yifdw:ny-1elifda:nx-1elifds:ny1elifdd:nx1ifnx0ornx38orny0orny38:continueifvis[nx][ny]:continueansdifnotis_wrong(test_opt(ans)):vis[nx][ny]1oldx,oldyx,y x,ynx,ny dfs(depth1)x,yoldx,oldy vis[nx][ny]0ansans[:-1]vis[0][0]1dfs(0)关键优化禁止连续走回头路比如上一步走了w下一步不允许走s大幅减少无效搜索分支显著加快爆破速度。运行结果脚本运行后DFS 成功找到从 (0,0) 到 (38,38) 的合法路径将该路径字符串输入程序程序输出 flag。Flagflag{f205f28a97000b7a21a5df3f9264d796}总结本题是经典的迷宫类逆向题但迷宫规模较大39×39路径长度140步直接静态分析地图数据成本较高。解题的巧妙之处在于充分利用程序本身提供的实时反馈机制将逆向分析地图转化为与程序交互的动态爆破问题思路转换后难度大幅降低。这类题目的通用解法可以总结为当迷宫数据难以直接提取时优先考虑是否能通过程序的输出反馈来驱动路径搜索。结合 DFS/BFS 以及合理的剪枝策略如禁止回头、记录已访问节点通常能在可接受的时间内找到答案。另外patch 程序使其不在错误时退出是本题的关键前提需要对程序的控制流有基本的理解定位到错误分支的跳转指令并进行修改。