• 【攻防世界】maze


    IDA反汇编的结果:

    看上去确实挺草的,一堆goto和奇怪的函数,再加上题目名为迷宫,感觉很害怕

    不过其实goto的结构并不混乱,函数也很简单

    四个函数总共有两个功能:++x<8和x-->0

    四个goto其实是每次执行完函数之后就直接跳到指定位置,把函数返回值保存下来

    那么相应的,可以把v6和v9改个名,改成mark和mark2,方便观察

    (善用ida的改名和注释功能啊,不要偷懒,不改完全没法看,但是改着改着就懂了)

    分支结构清楚了之后,可以看一下循环结构,其实就是从第5个字符开始,一直到倒数第二个字符

    相当于把'nctf{'和'}'拿掉,只考虑里边包着的部分,串长24,还剩18个未知字符

    那么v4可以改成i,v5=*(&s1 + v4)可以改成ci

    接下来仔细看循环代码的细节

    可以看到,四个分治结构分别在ci等于四个值的时候进入,把4个值转成char可以发现是四个非常有趣的字符

    'o', 'O', '0', '.'

    针不辍……

    当进入字符对应的操作后,会让v10或者v10的下一个字节+1或-1(不知道为啥,点进函数前是v10,但是如果进去看一眼就变成v9了,第二个参数v3也无了==)

    那么&v10和&v10+1相当于两个计数器,把它们分别叫做cnt和cnt2

    循环代码的最后出现了一个奇怪的字符串,只由'*', ' ', '#'组成,把它称为wbwb

    那么如果wbwb[cnt+8*cnt2]=='*',就会跳转到Wrong flag,我们可以把这里的label重命名为gg

    此外,当所有内容串遍历完了之后,如果mark==0(cnt和cnt2不在0-7的范围内)或者wbwb[cnt+8*cnt2]!='#'也会gg

    那至此这个程序的意图就很明显了,通过一个长度为18的'oO0.'串,操控一个指针在字符串上移动,使得避开'*'的情况下到达'#'

    整理完后的反汇编代码是这样的:

    (这里的HIDWORD和SHIDWORD是取cnt这个64位int的高32位,其实和(int *)&cnt + 1是一样的)

    状态数看上去不是很多,可以写个搜索爆破

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 char s[110];
     6 int m=0;
     7 int q[110];
     8 int n=18;
     9 void dfs(int x,int y,int z,int w){
    10     if(w<0 || w>=m)  return ;
    11     if(s[w]=='*')  return ;
    12     if(x==n+1){
    13         if(s[w]!='#')  return ;
    14         for(int i=1;i<=n;++i){
    15             char tmp=' ';
    16             if(q[i]==1)  tmp='o';
    17             else if(q[i]==2)  tmp='O';
    18             else if(q[i]==3)  tmp='0';
    19             else  tmp='.';
    20             printf("%c",tmp);
    21         }
    22         printf("
    ");
    23         return ;
    24     }
    25     q[x]=1;
    26     dfs(x+1,y+1,z,w+1);
    27     q[x]=2;
    28     dfs(x+1,y-1,z,w-1);
    29     q[x]=3;
    30     dfs(x+1,y,z+1,w+8);
    31     q[x]=4;
    32     dfs(x+1,y,z-1,w-8);
    33 }
    34 int main(){
    35     char ch=getchar();
    36     while(ch!='
    '){
    37         s[m++]=ch;
    38         ch=getchar();
    39     }
    40     dfs(1,0,0,0);
    41     return 0;
    42 }
    View Code

    跑得很快,只有一解,这就是flag

    做完这题之后看了一下攻防世界的WP,里边说这其实就是个8*8的迷宫,cnt+-1是往上下走,cnt2+-1是往左右走,'*'不能走,'#'是目标

    现在我终于知道题面里的迷宫是指啥了

    原来这题这么简单的吗囧

  • 相关阅读:
    检查IP地址是否有效(delphi)
    Oracle 常用操作
    DBGrid中顯示行號的終極解決方案(Delphi篇)
    从零开始学Java 第24章 网络聊天室
    JavaScript的循环结构和经典题目
    html5/css3布局(一)
    html常用的基本标签
    HTML5——css基础语法
    JavaScript函数使用和DOM节点
    C语言Ⅰ|博客作业07
  • 原文地址:https://www.cnblogs.com/cdcq/p/14158536.html
Copyright © 2020-2023  润新知