首页
社区
课程
招聘
[原创] 南冥神功 writeup
发表于: 2021-5-11 20:03 4610

[原创] 南冥神功 writeup

2021-5-11 20:03
4610

先拖到IDA里分析,当看到字符S后边跟了一堆01的时候就猜到是迷宫了,结合main函数里边的逻辑基本就可以判断是走迷宫了。这里我把main函数加了一些注释可以很清晰看出来迷宫的规则,迷宫是一个9*10的二维数组,S(0x53)是起点,0是路,1是墙。走过的路会被置为1,然后再最后程序会判断数组内所有的值,只要所有的值都为1就成功了。代码逻辑如下:

迷宫如下:

根据这个迷宫的行走规则可以规划出如下路线:

最终flag的每一位可以走两步,计算的公式如下所示:

最终写出了如下计算flag的程序:

最终编译运行即可得到flag

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char pinput; // al
  int index_input; // esi
  int index_key; // ecx
  int check2; // edx
  int v8; // eax
  unsigned int pos_x; // ecx
  int check1; // eax
  signed int v11; // edx
  int v12; // eax
  char *pmaze; // eax
  char (*v14)[10]; // eax
  int v15; // edx
  char (*v16)[10]; // ecx
  int v17; // eax
  int v18; // eax
  int v19; // eax
  int v20; // [esp+1Ch] [ebp-60h]
  unsigned int pos_y; // [esp+20h] [ebp-5Ch]
  unsigned int v22; // [esp+24h] [ebp-58h]
  char pkey; // [esp+2Bh] [ebp-51h]
  int keylength; // [esp+2Ch] [ebp-50h]
  char input[76]; // [esp+30h] [ebp-4Ch]
 
  sub_40AD70();
  sub_4AF840((int)&dword_4B8860, "Input your code: ");
  sub_4B0AB0((int)&dword_4B8680, input);
  if ( strlen(input) <= 48 )
  {
    pinput = input[0];
    if ( input[0] )
    {
      index_input = 0;
      pos_y = 0;
      v22 = 0;
      keylength = keylen;
      pkey = key[0];
LABEL_4:
      if ( keylength > 0 )
      {
        index_key = 0;
        if ( pkey == pinput )
        {
LABEL_11:
          check2 = (index_input + index_key / 6) % 6;
          v8 = index_key + index_input;
          pos_x = v22;
          v20 = check2;
          check1 = 5 - v8 % 6;
          v11 = 0;
          while ( 1 )
          {
            switch ( check1 )
            {
              case 1:                           // 向右走
                ++pos_x;
                break;
              case 2:                           // 偶数行向右下走,奇数行向下走
                v17 = (pos_y++ & 1) == 0;
                pos_x += v17;
                break;
              case 3:                           // 奇数行向左下走,偶数行向下走
                v12 = (pos_y++ & 1) != 0;
                pos_x -= v12;
                break;
              case 4:                           // 向左走
                --pos_x;
                break;
              case 5:                           // 奇数行向左上走,偶数行向上走
                v19 = (pos_y-- & 1) != 0;
                pos_x -= v19;
                break;
              default:                          // 偶数行向右上走,奇数行向上走
                v18 = (pos_y-- & 1) == 0;
                pos_x += v18;
                break;
            }
            if ( pos_x > 9 )
              break;
            if ( pos_y > 8 )
              break;
            pmaze = &maze[pos_y][pos_x];
            if ( *pmaze )                       // 判断是否撞墙, 0是路,1是墙
              break;
            *pmaze = 1;
            if ( v11 == 1 )
            {
              ++index_input;
              v22 = pos_x;
              pinput = input[index_input];
              if ( pinput )
                goto LABEL_4;
              goto LABEL_19;
            }
            v11 = 1;
            check1 = v20;
          }
        }
        else
        {
          while ( keylength != ++index_key )
          {
            if ( key[index_key] == pinput )
              goto LABEL_11;
          }
        }
      }
    }
    else
    {
LABEL_19:                                       // 遍历迷宫数组,判断所有位置的值是否都为1
      v14 = maze;
      v15 = 0;
      do
      {
        v16 = v14 + 1;
        do
        {
          v15 += *(_BYTE *)v14 < 1u;
          v14 = (char (*)[10])((char *)v14 + 1);
        }
        while ( v16 != v14 );
      }
      while ( &End != (_UNKNOWN *)v16 );
      if ( !v15 )
      {
        sub_4ABF30(&dword_4B8860, "Good job!", 9);
        sub_4AD980(&dword_4B8860);
        return 0;
      }
    }
  }
  sub_4ABF30(&dword_4B8860, "Try again...", 12);
  sub_4AD980(&dword_4B8860);
  return 0;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char pinput; // al
  int index_input; // esi
  int index_key; // ecx
  int check2; // edx
  int v8; // eax
  unsigned int pos_x; // ecx
  int check1; // eax
  signed int v11; // edx
  int v12; // eax
  char *pmaze; // eax
  char (*v14)[10]; // eax
  int v15; // edx
  char (*v16)[10]; // ecx
  int v17; // eax
  int v18; // eax
  int v19; // eax
  int v20; // [esp+1Ch] [ebp-60h]
  unsigned int pos_y; // [esp+20h] [ebp-5Ch]
  unsigned int v22; // [esp+24h] [ebp-58h]
  char pkey; // [esp+2Bh] [ebp-51h]
  int keylength; // [esp+2Ch] [ebp-50h]
  char input[76]; // [esp+30h] [ebp-4Ch]
 
  sub_40AD70();
  sub_4AF840((int)&dword_4B8860, "Input your code: ");
  sub_4B0AB0((int)&dword_4B8680, input);
  if ( strlen(input) <= 48 )
  {
    pinput = input[0];
    if ( input[0] )
    {
      index_input = 0;
      pos_y = 0;
      v22 = 0;
      keylength = keylen;
      pkey = key[0];
LABEL_4:
      if ( keylength > 0 )
      {
        index_key = 0;
        if ( pkey == pinput )
        {
LABEL_11:
          check2 = (index_input + index_key / 6) % 6;
          v8 = index_key + index_input;
          pos_x = v22;
          v20 = check2;
          check1 = 5 - v8 % 6;
          v11 = 0;
          while ( 1 )
          {
            switch ( check1 )
            {
              case 1:                           // 向右走
                ++pos_x;
                break;
              case 2:                           // 偶数行向右下走,奇数行向下走
                v17 = (pos_y++ & 1) == 0;
                pos_x += v17;
                break;
              case 3:                           // 奇数行向左下走,偶数行向下走
                v12 = (pos_y++ & 1) != 0;
                pos_x -= v12;
                break;
              case 4:                           // 向左走
                --pos_x;
                break;
              case 5:                           // 奇数行向左上走,偶数行向上走
                v19 = (pos_y-- & 1) != 0;
                pos_x -= v19;
                break;
              default:                          // 偶数行向右上走,奇数行向上走
                v18 = (pos_y-- & 1) == 0;
                pos_x += v18;
                break;
            }
            if ( pos_x > 9 )
              break;
            if ( pos_y > 8 )
              break;
            pmaze = &maze[pos_y][pos_x];
            if ( *pmaze )                       // 判断是否撞墙, 0是路,1是墙
              break;
            *pmaze = 1;
            if ( v11 == 1 )
            {
              ++index_input;
              v22 = pos_x;
              pinput = input[index_input];
              if ( pinput )
                goto LABEL_4;
              goto LABEL_19;
            }
            v11 = 1;
            check1 = v20;
          }
        }
        else
        {
          while ( keylength != ++index_key )
          {
            if ( key[index_key] == pinput )
              goto LABEL_11;
          }
        }
      }

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//