0x01

拿到题目,放到IDA中静态分析,发现main函数中就是关键代码,如图:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rsi
  signed __int64 v4; // rbx
  signed int v5; // eax
  char v6; // bp
  char v7; // al
  const char *v8; // rdi
  __int64 v10; // [rsp+0h] [rbp-28h]

  v10 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v4 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v5 = *(&s1 + v4);							
      v6 = 0;
      if ( v5 > 78 )
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 79 )		
        {
          v7 = sub_400650((_DWORD *)&v10 + 1);	
          goto LABEL_14;
        }
        if ( v5 == 111 )					
        {
          v7 = sub_400660((int *)&v10 + 1);
          goto LABEL_14;
        }
      }
      else									//对行进行操作
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 46 )	//45对应'.'
        {
          v7 = sub_400670(&v10, v3);		//对i行进行操作,向上代表'.'
          goto LABEL_14;
        }
        if ( v5 == 48 )						//48对应0
        {
          v7 = sub_400680(&v10, v3);		//对i行进行操作,向下代表0
LABEL_14:
          v6 = v7;
          goto LABEL_15;
        }
      }
LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 )
          break;
LABEL_20:
        v8 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )
    goto LABEL_20;
  v8 = "Congratulations!";
LABEL_21:
  puts(v8);
  return 0LL;
}

那么这道题其实就是分析代码,然后得到flag

0x02

一、

接下来我们来看看代码

if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )

这句的意思是在对我们输入的字符进行比较,所以通过这里我们知道falg的前5位是nctf{ 第24位为},所以这里我们就需要对{}中的内容进行分析

二、

while ( 1 )
    {
      v5 = *(&s1 + v4);							//表示从输入的第五位开始
      v6 = 0;
      if ( v5 > 78 )							//对列进行操作
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 79 )		//79对应'O'
        {
          v7 = sub_400650((_DWORD *)&v10 + 1);	//对j列进行操作,向左对应'O'
          goto LABEL_14;
        }

这段代码就是说如果我们要向左走,那么就对应一个’O’字母

三、

 if ( v5 == 111 )							//111 就是'o'
        {
          v7 = sub_400660((int *)&v10 + 1);	//对j列进行操作,向右代表'o'
          goto LABEL_14;
        }

这段代码就是表明,向左运动一次,则代表一个字母’o’

四、

else										//对行进行操作
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 46 )	//45对应'.'
        {
          v7 = sub_400670(&v10, v3);		//对i行进行操作,向上代表'.'
          goto LABEL_14;
        }
        if ( v5 == 48 )						//48对应0
        {
          v7 = sub_400680(&v10, v3);		//对i行进行操作,向下代表0
LABEL_14:

这里就是和上面对应的对行的操作,向上向下分别对应不同的值

五、

LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 )
          break;

这段代码就是要画出这个迷宫的样子应进行的操作

那么这段代码的意思就是,构造一个8*8的矩阵,然后,用

’*******   *  **** * ****  * ***  *#  *** *** ***     *********‘

填充矩阵。

那么这个矩阵就需要我们把它画出来

六、

 if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 ) //35代表#
    goto LABEL_20;
  v8 = "Congratulations!";

这段代码就是说如果最后v10的值等于35(即#)则成功,所以这里,我们最后通过移动v8的位置,要让v8最后处于矩阵中#的位置。

0x03

通过上面的代码分析,我们知道了,这应该是个迷宫,我们通过迷宫的形状,找出应该走的路径,然后将走的路径替换为相应的值,最后得到的值即为我们的flag,那么下面我们应该做的第一步就是,画出这个迷宫!

画迷宫:

import numpy as np

q='nctf{'
h='}'
asc='  *******   *  **** * ****  * ***  *#  *** *** ***     *********'
mg=np.array(list(asc))
print(str(mg.reshape(int(len(asc)/8),8)).replace('\'',''))

结果:

[[    * * * * * *]
 [*       *     *]
 [* * *   *   * *]
 [* *     *   * *]
 [*     * #     *]
 [* *   * * *   *]
 [* *           *]
 [* * * * * * * *]]

所以我们如何能走到#呢?那么我们得到路径为下:

右下右右下下左下下下右右右右上上左左

然后我们将‘右’替换为‘O’,将‘左’替换为‘o’,将‘上’替换为‘.’,将下替换为0,即可得到flag

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

运行结果:

nctf{o0oo00O000oooo..OO}

版权声明:本文为Jleixin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Jleixin/p/13029104.html