• 【攻防世界】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是往左右走,'*'不能走,'#'是目标

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

    原来这题这么简单的吗囧

  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/cdcq/p/14158536.html
Copyright © 2020-2023  润新知