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=2,y=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传入首地址