逆向maze分享

maze即迷宫问题  常见的就是限制你只能输入几种字符 控制你行走的路线  只有走到规定的出口才能得到flag

那么我们如何判断遇到的是maze问题呢?

1 题目描述直接说明了  这个就不说了

2 在ida搜索字符串时发现了一些字符串/主函数一些语句提示了你

3  搜索字符串没有 但是某个函数的作用是生成迷宫的地图  这样我们也可以判断出来是maze问题

那么当我们判断出来时maze问题之后如何进行分析呢?

第一步:

找到迷宫!

迷宫可能就在字符串内  但是大部分都是动态生成 下个断点即可找到地图

(地图往往还需要二次加工)

第二步:

找到限制字符!(然后进行二次加工)

限制字符就是控制我们在迷宫中的移动的字符 只有找到了我们才可以考虑怎么走出迷宫

而分析限制字符是如何控制我们走出迷宫的 我觉得有两种方法

1 试

2 根据伪代码分析

以上两种方法没有高下优劣之分 我觉得分情况看使用哪种方法!

第三步:

分析路径  

结合限制字符是如何控制行走以及哪里是路哪里是墙

一般有两种路径

1 只有一条路走到出口即可

2 有限制条件 这时候就需要我们分析到底走哪条路了

第四步:

得出路径

下面附上两道例题根据上面的步骤解决

[HUBUCTF 2022 新生赛]help

搜索字符串发现是一个maze问题

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1   

1 0 0 0 0 0 1 1 1 1 1 1 0 1 1 1 

1 0 1 1 1 0 1 1 1 1 1 1 0 1 1 1 

1 0 1 1 1 0 1 1 0 0 0 1 0 1 1 1

1 0 1 1 1 0 1 1 0 1 0 1 0 1 1 1 

1 0 1 1 1 0 0 0 0 1 0 1 0 1 1 1

1 0 1 1 1 1 1 1 0 1 0 1 0 1 1 1

1 0 1 1 1 1 1 1 0 0 0 1 0 1 1 1

1 0 1 1 1 1 1 1 1 0 1 1 0 1 1 1

1 0  1  1  1  1  1 1  1  0 1  1 0  1 1 1 

1 0 0 0 0 1  1 0 0 0 0 1 0 0 0 1

1 1 1 1 0 1 1 1 1 0 1 1 0 1 0 1

1 1 1 1 0 1 1 1 1 0 1 1 0 1 0 1 

1 0 0 0 0 1 1 1 1 0 1 1 0 1 0 0 

1 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1

1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1

这样我们就得到了地图

然后去找限制字符  别忘了check函数!

输入的长度为54  并且要符合这个check函数的要求

我把check接受的参数s名字改为input  因为这里本来接受的就是我们的输入 
然后把 限制字符由数字形式转换为字符形式  更容易判断

int __cdecl check(char *input)
{
  int v1; // eax
  int len; // [rsp+20h] [rbp-10h]
  int y; // [rsp+24h] [rbp-Ch]
  int x; // [rsp+28h] [rbp-8h]
  int i; // [rsp+2Ch] [rbp-4h]

  len = strlen(input);
  
  x = 15;     这是我们在迷宫的初始位置
  y = 1;
  
  for ( i = 0; i < len; ++i )
  {
    v1 = input[i];
    if ( v1 == 'd' )
    {
      ++y;              输入的是d y+1
    }
    
    else if ( v1 > 'd' )
    {
      if ( v1 == 's' )
      {
        ++x;			输入的是s x+1
      }
      
      else
      {
        if ( v1 != 'w' )
          return 0;
        --x;         输入的不是w退出程序   输入的是w   x-1
      }
      
    }
    



    else
    {
      if ( v1 != 'a' )    输入的不是a退出程序   输入的是a y-1
        return 0;
      --y;
    }
    if ( map[16 * x + y] )
      return 0;
  }
  return 1;
}

数组大小为256  且这里有个16

则地图可能为16^16的大小

  if ( map[16 * x + y] )  这里是利用一维数组表示二维数组  x为行  y为列

例如,假设 x=2y=3,那么通过表达式 16 * x + y,我们可以计算出在一维数组中的位置为 16 * 2 + 3 = 35。这种映射方式使得我们可以使用一维数组来表示二维矩阵,从而方便地进行索引和访问。

限制长度为54则 红色的为正确路线

如此可知

sw  s是向后  w向前(数组下标-1 在地图中是向前移动)

ad  a向左     d向右

得出路径

即NSSCTF{MD5(wwdddwwwaaawwwwwwwwwddddssssdddssdsssssssdddwwwwddsssd)}

然后去求md5值就好了

你应该会分析了吧

那就再来一题!

攻防世界   maze

去main函数看看

现在基本确定这是一道maze题 那么我们继续往后看

发现最后的验证环节  发现了一个比较  是不是非常眼熟   进去看看

找到地图之后分析限制字符

进去看看这个函数  限制O

把传入的值赋值个v1  再-1   

下一个  限制o

将传入的值+1赋值给v1

上面这两个函数传入的参数都是v10

下面这两个传入的是v9

限制  .的

先赋值给v1 再-1

限制0的

初始位置为map[0,0]

根据上述对地图进行二次加工

这里我们知道了走到#就是成功  

#的位置为map[4,4]  我们的初始位置为map[0,0]

下面分析限制字符如何控制移动

根据上述可知以v10为参数两个字符分别是   O 和 o    而v10是控制列数

O是对输入的v10先赋值后-1

o是先+1再赋值  所以 

O是向左

o是向右移动

.和0是控制v9  那么

.是向上移动

0是向下移动

右下右右下下左下下下右右右右上上左左

nctf{o0oo00O000oooo..OO}

a1传入首地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值