南邮CTF RE5——MAZE

链接:https://pan.baidu.com/s/174v4vI4760V-QnD4yW7Z5A 密码:ml6n

MAZE拖进winhex发现是elf文件,ida64打开,调出main函数,反编译:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  signed __int64 v3; // rbx@4
  signed int v4; // eax@5
  bool v5; // bp@5
  bool v6; // al@8
  const char *v7; // rdi@19
  __int64 v9; // [sp+0h] [bp-28h]@1

  v9 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 )
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);
  }
  v3 = 5LL;
  if ( strlen(&s1) - 1 > 5 )
  {
    while ( 1 )
    {
      v4 = *(&s1 + v3);
      v5 = 0;
      if ( v4 > 78 )
      {
        v4 = (unsigned __int8)v4;
        if ( (unsigned __int8)v4 == 'O' )
        {
          v6 = sub_400650((_DWORD *)&v9 + 1);    //v6为v9的下一个字节 
          goto LABEL_14;
        }
        if ( v4 == 'o' )
        {
          v6 = sub_400660((int *)&v9 + 1);    //v6为v9的下一个字节
          goto LABEL_14;
        }
      }
      else
      {
        v4 = (unsigned __int8)v4;
        if ( (unsigned __int8)v4 == '.' )
        {
          v6 = sub_400670(&v9);         //v6为v9的本字节
          goto LABEL_14;
        }
        if ( v4 == '0' )
        {
          v6 = sub_400680((int *)&v9);    //v6为v9
LABEL_14:
          v5 = v6;
          goto LABEL_15;
        }
      }
LABEL_15:
      if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v9), v9) )
        goto LABEL_22;
      if ( ++v3 >= strlen(&s1) - 1 )
      {
        if ( v5 )
          break;
LABEL_20:
        v7 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( *(&asc_601060[8 * (signed int)v9] + SHIDWORD(v9)) != 35 )          ///v9为行数
    goto LABEL_20;
  v7 = "Congratulations!";
LABEL_21:
  puts(v7);
  return 0LL;
}

/////////SHIDWORD///////////////////查了一下IDA的宏定义 #define HIDWORD(x) (((_DWORD)&(x)+1))

太长了,简单看了一下,对输入的字符串限制了24的长度,保证以“nctf{”开头,“}”结尾。换成graph view:

输入图片说明

可以看到他根据判断是否为'.','0','o','O'来决定进行什么操作

bool __fastcall sub_400650(_DWORD *a1)//(_DWORD *)&v9 + 1
{
//为O(0x4f)的时候   

  int v1; // eax@1

  v1 = (*a1)--;
  return v1 > 0;
}

bool __fastcall sub_400660(int *a1)//(int *)&v9 + 1
{
///为o的时候
  int v1; // eax@1

  v1 = *a1 + 1;
  *a1 = v1;
  return v1 < 8;
}

bool __fastcall sub_400670(_DWORD *a1)//&v9
{
//为.的时候
  int v1; // eax@1

  v1 = (*a1)--;
  return v1 > 0;
}

bool __fastcall sub_400680(int *a1)//(int *)&v9
{
//为0(0x30)的时候
  int v1; // eax@1

  v1 = *a1 + 1;
  *a1 = v1;
  return v1 < 8;
}


输入图片说明

猜测8个字节为一行,v9表示竖向,v9的下一个字节为横向,O为左移一位,o为右移一位,.为上移一位,0为下移一位。根据下图,判断出偏移为601060的地方放着我们要比较的东西,他依次把数据交给寄存器EDI,调用函数:

sub_400690 proc near
movsxd  rax, esi
add     rax, rdi
movsxd  rcx, edx
movzx   eax, byte ptr [rax+rcx*8]
cmp     eax, 20h
setz    cl
cmp     eax, 23h
setz    al
or      al, cl
retn
sub_400690 endp

MAZE这个题目就是迷宫了,上面的函数说明了在将EDI中的数与20h和23h比较,不符合就GG,来看看我们需要走的那个迷宫,就是地址为0000000000601060的HEX:

输入图片说明

整理一下得到8X8的矩阵:

输入图片说明

按照函数规则走一下

输入图片说明

将走的线路换成上诉的四个字符,得到o0oo00O000oooo..OO即为flag

猜你喜欢

转载自my.oschina.net/u/3763247/blog/1805781
今日推荐