攻防世界--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轴。

扫描二维码关注公众号,回复: 7154222 查看本文章

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}

猜你喜欢

转载自www.cnblogs.com/Mayfly-nymph/p/11444758.html