zoukankan      html  css  js  c++  java
  • 攻防世界--maze

    测试文件下载:https://adworld.xctf.org.cn/media/task/attachments/fa4c78d25eea4081864918803996e615

    1.准备

    获得信息

    1. 64位文件

    2.IDA打开

    选择main函数,反编译为C代码。

     1 __int64 __fastcall main(__int64 a1, char **a2, char **a3)
     2 {
     3   const char *v3; // rsi
     4   signed __int64 v4; // rbx
     5   signed int v5; // eax
     6   char v6; // bp
     7   char v7; // al
     8   const char *v8; // rdi
     9   __int64 v10; // [rsp+0h] [rbp-28h]
    10 
    11   v10 = 0LL;
    12   puts("Input flag:");
    13   scanf("%s", &s1, 0LL);
    14   if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )
    15   {
    16 LABEL_22:
    17     puts("Wrong flag!");
    18     exit(-1);
    19   }
    20   v4 = 5LL;
    21   if ( strlen(&s1) - 1 > 5 )
    22   {
    23     while ( 1 )
    24     {
    25       v5 = *(&s1 + v4);
    26       v6 = 0;
    27       if ( v5 > 78 )
    28       {
    29         v5 = (unsigned __int8)v5;
    30         if ( (unsigned __int8)v5 == 79 )
    31         {
    32           v7 = sub_400650((char *)&v10 + 4, v3);
    33           goto LABEL_14;
    34         }
    35         if ( v5 == 111 )
    36         {
    37           v7 = sub_400660((char *)&v10 + 4, v3);
    38           goto LABEL_14;
    39         }
    40       }
    41       else
    42       {
    43         v5 = (unsigned __int8)v5;
    44         if ( (unsigned __int8)v5 == 46 )
    45         {
    46           v7 = sub_400670(&v10, v3);
    47           goto LABEL_14;
    48         }
    49         if ( v5 == 48 )
    50         {
    51           v7 = sub_400680(&v10, v3);
    52 LABEL_14:
    53           v6 = v7;
    54           goto LABEL_15;
    55         }
    56       }
    57 LABEL_15:
    58       v3 = (const char *)HIDWORD(v10);
    59       if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
    60         goto LABEL_22;
    61       if ( ++v4 >= strlen(&s1) - 1 )
    62       {
    63         if ( v6 )
    64           break;
    65 LABEL_20:
    66         v8 = "Wrong flag!";
    67         goto LABEL_21;
    68       }
    69     }
    70   }
    71   if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )
    72     goto LABEL_20;
    73   v8 = "Congratulations!";
    74 LABEL_21:
    75   puts(v8);
    76   return 0LL;
    77 }

    打开字符串的视图,我们可以看到

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

    2.1 代码分析

     1 __int64 __fastcall main(__int64 a1, char **a2, char **a3)
     2 {
     3   signed __int64 v4; // rbx
     4   signed int v5; // eax
     5   char v6; // bp
     6   char v7; // al
     7   const char *v8; // rdi
     8   __int64 v10; // [rsp+0h] [rbp-28h]
     9 
    10   v10 = 0LL;
    11   puts("Input flag:");
    12   scanf("%s", &s1, 0LL);
    13   
    14   
    15   if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 )    //len(s1) = 24, s1开头为'nctf', 
    16   {
    17 LABEL_22:
    18     puts("Wrong flag!");
    19     exit(-1);
    20   }
    21 v4 = 5LL;                                                                        //flag总长24,已知5个长度,v4表示输入的表示方向的字符数。
    22   if ( strlen(&s1) - 1 > 5 )
    23   {
    24     while ( 1 )
    25     {
    26       v5 = *(&s1 + v4);                                                            //v5 = s1[5]
    27       v6 = 0;
    28       if ( v5 > 'N' )//v5 > 'N'
    29       {
    30         v5 = (unsigned __int8)v5;
    31         if ( (unsigned __int8)v5 == 'O' )                                                //1. 当v5 == 'O'的情况,表示左移
    32         {
    33           v7 = sub_400650((char *)&v10 + 4, v3);                                        //v10--,表示位置的列数-1,v7判断是否越界(越界返回:FALSE, 未越界返回:TRUE)
    34           goto LABEL_14;
    35         }
    36         if ( v5 == 'o' )                                                                //2. 当v5 == 'o‘的情况,表示右移
    37         {
    38           v7 = sub_400660((char *)&v10 + 4, v3);                                        //v10++,表示位置的列数+1,
    39           goto LABEL_14;
    40         }
    41       }
    42       
    43       else//v5 < 'N'
    44       {
    45         v5 = (unsigned __int8)v5;
    46         if ( (unsigned __int8)v5 == '.')                                                //3. v5 == '.'的情况, 表示上移
    47         {
    48           v7 = sub_400670(&v10, v3);                                                //v10--,表示位置的行数-1,
    49           goto LABEL_14;
    50         }
    51         if ( v5 == '0' )                                                                //4. v5=='0'的情况,表示下移
    52         {
    53           v7 = sub_400680(&v10, v3);                                                //v10++, 表示位置的行数+1
    54 LABEL_14:
    55           v6 = v7;                                                                    //赋值给v6,下面判断走迷宫时,是否越界
    56           goto LABEL_15;
    57         }
    58       }
    59       
    60       
    61 LABEL_15:
    62       if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v10), v10) )//判断该位置的字符是' ', '#'或者'*'中的哪种,如果是'*'则,返回再次寻路
    63         goto LABEL_22;
    64       if ( ++v4 >= strlen(&s1) - 1 )                                                    //因为最后以'}'结尾,所以strlen(s1) - 1。我们需要找到中间18个字符
    65       {
    66         if ( v6 )//判断是否越界(未越界退出循环)
    67           break;
    68 LABEL_20:
    69         v8 = "Wrong flag!";
    70         goto LABEL_21;
    71       }
    72     }
    73   }
    74   if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )//判断是否到达'#'处,没有到达,继续返回循环,进行移动
    75     goto LABEL_20;
    76   v8 = "Congratulations!";
    77 LABEL_21:
    78   puts(v8);
    79   return 0LL;
    80 }

    通过代码分析,能够判断出那一串字符实际上就是一个迷宫,通过'.', '0', 'O', 'o'来控制移动,V10实际上就是一个二维数组,一维表示X轴,二维表示Y轴。

    2.2 方向判断

    在汇编代码中

    .text:00000000004006B7                 mov     dword ptr [rsp+28h+var_28+4], 0
    .text:00000000004006BF                 mov     dword ptr [rsp+28h+var_28], 0

    我们能够知道,v9高位表示x轴,v9低位表示y轴,

    通过函数

    __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;
    }

    sub_400690函数中是a2+a3*8,即a3表示行,a2表示列。返回到调用函数处,即v10高位表示列,低位表示行。那么就可以判断出'O','o'表示左右,'.','0'表示上下

    2.3 迷宫表示

    通过a2+a3*8我们也能了解到这个迷宫有8行,总共64个字符,也就是8x8的迷宫,表示出来就是。

    00******
    *000*00*
    ***0*0**
    **00*0**
    *00*#00*
    **0***0*
    **00000*
    ********

    2.4 解迷宫

    起点(1,1),只能走0,要走到‘#’,找到路径右下右右下下左下下下右右右右上上左左

    写出脚本

    str = "右下右右下下左下下下右右右右上上左左"
    str = str.replace('', '.')
    str = str.replace('', '0')
    str = str.replace('', 'O')
    str = str.replace('', 'o')
    
    str = 'nctf{' + str + '}'
    
    print(str)

    3.get flag!

    nctf{oo0oo00O000oooo..OO}

  • 相关阅读:
    Java8新特性
    搜索解决方案 -- ElasticSearch入门
    插入排序
    单点登录系统CAS入门
    快速排序
    选择性排序
    冒泡排序
    springcloud入门
    消息中间件 -- RabbitMQ
    ActiveMQ中消息的重发与持久化保存
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11444758.html
Copyright © 2011-2022 走看看