攻防世界Reverse-maze

文章目录

  • 收集信息
  • 静态分析
    • shift + F12查看字符串窗口
    • F5查看伪代码
    • 来看重点
    • 画图获取flag

今天在云演平台上看reverse模块最后一节讲的是迷宫问题,觉得挺有意思。去攻防世界看了看,Reverse模块新手练习区的最后一题就是迷宫问题(maze),所以拿来练练手。

收集信息

将附件下载下来之后,用 Exeinfo PE 分析,可见不是exe可执行文件,而是ELF。且此文件是64位,加壳与否信息未知,我们用IDA Pro64位进行静态分析。
攻防世界Reverse-maze_第1张图片

静态分析

shift + F12查看字符串窗口

首先查看字符串窗口,发现最底下一串字符是由 * ,# 以及空格组成的,不难猜测出这应该就是迷宫了。其次,Congratulations代表恭喜,这里面是不是有 flag 的信息呢?我们点进去看看。
攻防世界Reverse-maze_第2张图片

F5查看伪代码

攻防世界Reverse-maze_第3张图片
发现背后是 main 函数,F5查看伪代码

_int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v3; // rbx
  int v4; // eax
  char v5; // bp
  char v6; // al
  const char *v7; // rdi
  unsigned int v9; // [rsp+0h] [rbp-28h] BYREF
  int v10[9]; // [rsp+4h] [rbp-24h] BYREF

  v10[0] = 0;
  v9 = 0;
  puts("Input flag:");
  scanf("%s", &s1);
  if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 )
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v3 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v4 = *(&s1 + v3);
      v5 = 0;
      if ( v4 > 78 )
      {
        if ( (unsigned __int8)v4 == 79 )
        {
          v6 = sub_400650(v10);
          goto LABEL_14;
        }
        if ( (unsigned __int8)v4 == 111 )
        {
          v6 = sub_400660(v10);
          goto LABEL_14;
        }
      }
      else
      {
        if ( (unsigned __int8)v4 == 46 )
        {
          v6 = sub_400670(&v9);
          goto LABEL_14;
        }
        if ( (unsigned __int8)v4 == 48 )
        {
          v6 = sub_400680(&v9);
LABEL_14:
          v5 = v6;
          goto LABEL_15;
        }
      }
LABEL_15:
      if ( !(unsigned __int8)sub_400690(asc_601060, (unsigned int)v10[0], v9) )
        goto LABEL_22;
      if ( ++v3 >= strlen(&s1) - 1 )
      {
        if ( v5 )
          break;
LABEL_20:
        v7 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( asc_601060[8 * v9 + v10[0]] != 35 )
    goto LABEL_20;
  v7 = "Congratulations!";
LABEL_21:
  puts(v7);
  return 0LL;
}

来看重点

 puts("Input flag:");
 scanf("%s", &s1);
 if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 ){
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }

我们输入的字符串为 s1,当此字符串的长度不为24或者 s1的开头五个字符不为 “ nctf{ ” 或者**最后一个字符不为 “ } ”**时(对照ascii码表,125对应字符 } ),跳转到 LABEL_22,并输出 Wrong flag! 这意味着,最终的 flag 的基本格式为 nctf{18个字符}

其次,循环中肉眼可见的四个判断语句
攻防世界Reverse-maze_第4张图片
同样对照ascii码表,可得这几个字符分别为 :O、o、. 、0,不难猜测出这就是我们来控制上下左右走出迷宫的四个方向符了,来查看其对应的操作。

• sub_400650

bool __fastcall sub_400650(_DWORD *a1)
{
  int v1; // eax

  v1 = (*a1)--;
  return v1 > 0;
}

• sub_400660

bool __fastcall sub_400660(int *a1)
{
  int v1; // eax

  v1 = *a1 + 1;
  *a1 = v1;
  return v1 < 8;
}

之后的sub_400670和sub_400650一样,sub_400680和sub_400660,分别执行减一加一的操作,这也验证了我们的猜想是代表走迷宫的上下左右移动。但我们仍然不知道哪个代表 x 轴的移动,哪个代表 y 轴的移动。同时两个函数中还包含着一个关键性的信息,return v1 > 0;return v1 < 8;猜测是代表迷宫的大小为 8*8

所以究竟谁是 x 轴谁是 y 轴,还有起点在哪儿呢?继续观察上述代码,O和o对应的函数参数为 v10,而 . 和0对应的是 v9,回到参数定义的位置

unsigned int v9; // [rsp+0h] [rbp-28h] BYREF
int v10[9]; // [rsp+4h] [rbp-24h] BYREF

这边我没琢磨懂,看了亿眼别人的wp,发现他是这么说的:攻防世界 maze_别害怕我在的博客-CSDN博客_maze攻防世界

加4的就是 x 轴,不加4 的就是 y 轴。

…还是不太明白QAQ,不过个人感觉无非就是两种情况,都试一下问题应该也不大。同时回到main函数的汇编代码段,可见起点是(0,0)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Im1zjR1E-1652352589475)(攻防世界Reverse-maze/image-20220512173846318.png)]

画图获取flag

这样所有逻辑都理清了,即

flag 的基本格式为 nctf{18个字符}

地图是 8*8,将字符串分为此规格即可

O、o、. 、0 代表控制上下左右走出迷宫的四个方向符

O、o分别代表 x 轴左、右移动

. 、0分别代表 y 轴上、下移动

然后就是画图走迷宫了,可以手画也可以代码。这边量不大我就手画了
攻防世界Reverse-maze_第5张图片
内容以及同步更新至 lbw的小窝

你可能感兴趣的:(CTF,CTF,reverse)