【攻防世界】REVERSE新手练习区 - maze

maze - wp

分析题目附件:

先拖入Exeinfo PE中:
在这里插入图片描述
ELF文件,64位。

拖入ida64,找main函数按F5(Fn+F5)查看伪代码:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rsi
  signed __int64 v4; // rbx
  signed int v5; // eax
  char v6; // bp
  char v7; // al
  const char *v8; // rdi
  __int64 v10; // [rsp+0h] [rbp-28h]

  v10 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 ) //输入字符串s1长度为24,并且前5个字符为 "nctf{" , 最后一个字符为125= '}' ,所以中间数据为填充部分
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v4 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v5 = *(&s1 + v4);
      v6 = 0;
      if ( v5 > 78 )
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 79 ) //79='O',表示左移
        {
          v7 = sub_400650((char *)&v10 + 4, v3); v10--,表示位置的列数-1,v7判断是否越界
          goto LABEL_14;
        }
        if ( v5 == 111 ) // 111='o',表示右移
        {
          v7 = sub_400660((char *)&v10 + 4, v3); //v10++,表示位置的列数+1,
          goto LABEL_14;
        }
      }
      else
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 46 ) // 46='.',表示上移
        {
          v7 = sub_400670(&v10, v3); //v10--,表示位置的行数-1
          goto LABEL_14;
        }
        if ( v5 == 48 ) // 48='0',表示下移
        {
          v7 = sub_400680(&v10, v3); //v10++, 表示位置的行数+1
LABEL_14:
          v6 = v7;  //赋值给v6,判断走迷宫时,是否越界
          goto LABEL_15;
        }
      }
LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) ) //判断该位置的字符是' ', '#'或者'*',如果是'*',则返回再次寻路
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 ) //判断是否越界
          break;
LABEL_20:
        v8 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 ) //'#'是迷宫出口,判断是否到达'#'处,没有到达,继续循环,进行移动
    goto LABEL_20;
  v8 = "Congratulations!";
LABEL_21:
  puts(v8);
  return 0LL;
}

分析伪代码发现v5的ASCII码值为79,111,46,48时分别执行四个函数

v5=79

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

  v1 = (*a1)--; // 横坐标-1 向左移动
  return v1 > 0; // 判断是否超出边界
}

v5=111

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

  v1 = *a1 + 1; // 横坐标+1 向右移动
  *a1 = v1;
  return v1 < 8;
}

v5=46

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

  v1 = (*a1)--; // 纵坐标-1 向上移动
  return v1 > 0;
}

v5=48

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

  v1 = *a1 + 1; // 纵坐标+1 向下移动
  *a1 = v1;
  return v1 < 8;
}

迷宫终点判断:

__int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
{
  __int64 result; // rax

  result = *(unsigned __int8 *)(a1 + a2 + 8LL * a3); //a1是迷宫,a2是列,a3是行。通过行列计算迷宫对应位置的字符
  LOBYTE(result) = (_DWORD)result == 32 || (_DWORD)result == 35; //如果是' '或者'#‘返回TRUE,是'*’返回FALSE
  return result;
}

综合以上分析,’O’ ‘o’ ‘.’ ‘0’ 时分别表示左 右 上 下的移动。

另外我们还发现了类似迷宫的字符串asc_601060:

 .data:0000000000601060 asc_601060      db '  *******   *  **** * ****  * ***  *#  *** *** ***     *********',0

共有64位,猜测可能是8x8的迷宫,将字符串分隔:

  ******
*   *  *
*** * **
**  * **
*  *#  *
** *** *
**     *
********

对应的走迷宫方式位:

o  0   oo   00  O   000   oooo    ..   OO
左 下 左左 下下 右 下下下 左左左左 上上 右右

合起来就是:o0oo00O000oooo…OO
则 flag = nctf{o0oo00O000oooo…OO} 。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值