迷宫

mian

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int v4; // [rsp+4h] [rbp-Ch]

  sub_11B4(a1, a2, a3);
  do
    v4 = sub_940();
  while ( v4 != 1 && v4 != -1 );
  return 0;
}

sub_11B4 把当前迷宫编号初始化为 0

unsigned __int64 sub_11B4()
{
  unsigned __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  dword_202AB0 = 0;
  return __readfsqword(0x28u) ^ v1;
}

迷宫方向函数

__int64 sub_940()
{
  int v0; // eax
  int v2; // [rsp+8h] [rbp-218h]
  int v3; // [rsp+Ch] [rbp-214h]
  _BYTE v4[520]; // [rsp+10h] [rbp-210h] BYREF
  unsigned __int64 v5; // [rsp+218h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v3 = 0;
  memset(v4, 0, 0x200u);
  _isoc99_scanf(&unk_1278, v4, v4);
  while ( 1 )
  {
    do
    {
      v2 = 0;
      sub_86C();
      v0 = (char)v4[v3];
      if ( v0 == 100 )
      {
        v2 = sub_E23();
      }
      else if ( v0 > 100 )
      {
        if ( v0 == 115 )
        {
          v2 = sub_C5A();
        }
        else if ( v0 == 'w' )
        {
          v2 = sub_A92();
        }
      }
      else
      {
        if ( v0 == 27 )
          return 0xFFFFFFFFLL;
        if ( v0 == 97 )
          v2 = sub_FEC();
      }
      ++v3;
    }
    while ( v2 != 1 );
    if ( dword_202AB0 == 2 )
      break;
    ++dword_202AB0;
  }
  puts("success! the flag is flag{md5(your input)}");
  return 1;
}

迷宫生成

unsigned __int64 sub_86C()
{
  int i; // [rsp+0h] [rbp-10h]
  int j; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  for ( i = 0; i <= 14; ++i )
  {
    for ( j = 0; j <= 14; ++j )
    {
      if ( dword_202020[225 * dword_202AB0 + 15 * i + j] == 3 )
      {
        dword_202AB4 = i;
        dword_202AB8 = j;
        break;
      }
    }
  }
  return __readfsqword(0x28u) ^ v3;
}

获取人物当前坐标

unsigned __int64 sub_86C()
{
  int i;
  int j;

  for ( i = 0; i <= 14; ++i )
  {
    for ( j = 0; j <= 14; ++j )
    {
      if ( dword_202020[225 * dword_202AB0 + 15 * i + j] == 3 )
      {
        dword_202AB4 = i;
        dword_202AB8 = j;
        break;
      }
    }
  }
}

函数遍历当前迷宫 找到值为 3 的位置

dword_202AB4 当前行
dword_202AB8 当前列

地图中各数值含义为

0 墙
1 可通行道路
3 当前人物位置
4 终点

向右移动

__int64 sub_E23()
{
  if ( dword_202AB8 != 14 )
  {
    if ( dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] == 1 )
    {
      dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] = 3;
      dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
    }
    else if ( dword_202020[225 * dword_202AB0 + 1 + 15 * dword_202AB4 + dword_202AB8] == 4 )
    {
      return 1;
    }
  }
  return 0;
}

当前列不是最右边时 检查右侧格子

右侧坐标为

row * 15 + col + 1

如果右侧是 1 就把右侧改成 3 当前格改成 1 完成移动

如果右侧是 4 说明到达终点 返回 1

因此该函数对应

d 向右

向左移动

__int64 sub_FEC()
{
  if ( dword_202AB8 )
  {
    if ( dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] == 1 )
    {
      dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] = 3;
      dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
    }
    else if ( dword_202020[225 * dword_202AB0 - 1 + 15 * dword_202AB4 + dword_202AB8] == 4 )
    {
      return 1;
    }
  }
  return 0;
}

左侧坐标为

row * 15 + col - 1

所以该函数对应

a 向左

向上移动

__int64 sub_A92()
{
  if ( dword_202AB4 )
  {
    if ( dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] == 1 )
    {
      dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] = 3;
      dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
    }
    else if ( dword_202020[225 * dword_202AB0 - 15 + 15 * dword_202AB4 + dword_202AB8] == 4 )
    {
      return 1;
    }
  }
  return 0;
}

上一行需要减去一行的宽度 15

row * 15 + col - 15

所以该函数对应

w 向上

向下移动

__int64 sub_C5A()
{
  if ( dword_202AB4 != 14 )
  {
    if ( dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] == 1 )
    {
      dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] = 3;
      dword_202020[225 * dword_202AB0 + 15 * dword_202AB4 + dword_202AB8] = 1;
    }
    else if ( dword_202020[225 * dword_202AB0 + 15 + 15 * dword_202AB4 + dword_202AB8] == 4 )
    {
      return 1;
    }
  }
  return 0;
}

下一行需要增加一行的宽度 15

row * 15 + col + 15

所以该函数对应

s 向下

最终方向关系为

w 上
s 下
a 左
d 右

主校验函数

v0 = (char)v4[v3];

if ( v0 == 'd' )
  v2 = sub_E23();
else if ( v0 == 's' )
  v2 = sub_C5A();
else if ( v0 == 'w' )
  v2 = sub_A92();
else if ( v0 == 'a' )
  v2 = sub_FEC();

程序逐字节读取输入 根据 wasd 控制人物移动 每次移动函数返回 1 就表示当前迷宫到达终点

if ( dword_202AB0 == 2 )
  break;

++dword_202AB0;

当第一张迷宫完成后

dword_202AB0 由 0 变成 1

当第二张迷宫完成后

dword_202AB0 由 1 变成 2

当第三张迷宫完成时 当前编号已经是 2 所以直接跳出循环 这也说明题目一共有三张迷宫 根据数据将每 225 个整数切成一张 15 × 15 的地图

第一张迷宫

.....##########
.....#S..######
.....###.######
.....###.######
.....###.....##
.....#######.##
.....#######.##
.....#######..#
.....########.#
.....########E#
...............
...............
...............
...............
...............

最短路径

ddsssddddsssdss

第二张迷宫

..#############
..#S.....######
..#..###.######
..######.######
..#..###.....##
..#..#######.##
..#..#######.##
..#..#####....#
..#..#####.##.#
..#..#####.####
..#......#.#..#
..#...........#
..###########E#
...............
...............

最短路径

dddddsssddddsssaassssddds

第三张迷宫

###############
#S..###########
###.#...#######
###...#.#######
####..#.#######
#..#.##.#######
##...##.#######
#######.#######
#######....####
##########.####
##########.####
##########.####
##########....#
#############.#
#############E#

最短路径

ddssddwddssssssdddssssdddss

三张迷宫需要连续通关 所以把三段路径拼接

ddsssddddsssdss
dddddsssddddsssaassssddds
ddssddwddssssssdddssssdddss

得到完整输入

ddsssddddsssdssdddddsssddddsssaassssdddsddssddwddssssssdddssssdddss

exp

import hashlib

path = (
    "ddsssddddsssdss"
    "dddddsssddddsssaassssddds"
    "ddssddwddssssssdddssssdddss"
)

print(f"flag{{{hashlib.md5(path.encode()).hexdigest()}}}")

一把梭了

image