首页
社区
课程
招聘
[原创]KCTF2021 第二题 南冥神功 writeup
发表于: 2021-5-11 15:58 4373

[原创]KCTF2021 第二题 南冥神功 writeup

2021-5-11 15:58
4373

拖进IDA中,直接看到main中所有逻辑,good

可以看出是个走迷宫的题:在9*10的迷宫内,1为墙,0为路,'S'是起点,一共有6(0-5)种前进方式,走过的路会变成墙。
成功条件是走过所有的路。

先把路径跑出来,果断dfs

跑出路径,输出操作方式
opt: 1 2 3 4 3 2 1 2 3 4 3 2 1 1 0 1 2 1 0 0 5 0 5 4 3 4 5 0 5 0 1 2 1 0 1 2 1 2 3 4 3 2 2 3 2 1

每个输入字符可以生成两个操作方式v10v20,且无后继影响,暴力解

Flag: GJ0V4LA4VKEVQZSVCNGJ00N

sub_40AD70();
  sub_4AF840((int)&dword_4B8860, "Input your code: ");
  sub_4B0AB0((int)&dword_4B8680, v25);
  if ( strlen(v25) <= 48 )
  {
    v3 = v25[0];
    if ( v25[0] )
    {
      v4 = 0;
      v21 = 0;
      v22 = 0;
      v24 = dword_4B7020;
      v23 = byte_4B7040[0];
LABEL_4:
      if ( v24 > 0 )
      {
        v5 = 0;
        if ( v23 == v3 )
        {
LABEL_11:
          v7 = (v4 + v5 / 6) % 6;
          v8 = v5 + v4;
          v9 = v22;
          v20 = v7;
          v10 = 5 - v8 % 6;
          for ( i = 0; ; i = 1 )
          {
            switch ( v10 )  // 地图上的操作,走到下一个位置
            {
              case 1:
                ++v9;
                break;
              case 2:
                v17 = (v21++ & 1) == 0;
                v9 += v17;
                break;
              case 3:
                v12 = (v21++ & 1) != 0;
                v9 -= v12;
                break;
              case 4:
                --v9;
                break;
              case 5:
                v19 = (v21-- & 1) != 0;
                v9 -= v19;
                break;
              default:
                v18 = (v21-- & 1) == 0;
                v9 += v18;
                break;
            }
            if ( v9 > 9 )
              break;
            if ( v21 > 8 )
              break;
            v13 = &aS_1[10 * v21 + v9];
            if ( *v13 )
              break;
            *v13 = 1;    // 根据行列取地图位置,为0设置为1
            if ( i == 1 )
            {
              ++v4;
              v22 = v9;
              v3 = v25[v4];
              if ( v3 )
                goto LABEL_4;
              goto LABEL_19;
            }
            v10 = v20;
          }
        }
        else
        {
          while ( v24 != ++v5 )
          {
            if ( byte_4B7040[v5] == v3 )
              goto LABEL_11;
          }
        }
      }
    }
    else
    {
LABEL_19:
      // v15 统计地图上0的个数
      v14 = aS_1;
      v15 = 0;
      do
      {
        v16 = v14 + 10;
        do
          v15 += *v14++ == 0;
        while ( v16 != v14 );
      }
      while ( &unk_4B70DA != (_UNKNOWN *)v16 );
      // 地图上不可有0
      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;
}
sub_40AD70();
  sub_4AF840((int)&dword_4B8860, "Input your code: ");
  sub_4B0AB0((int)&dword_4B8680, v25);
  if ( strlen(v25) <= 48 )
  {
    v3 = v25[0];
    if ( v25[0] )
    {
      v4 = 0;
      v21 = 0;
      v22 = 0;
      v24 = dword_4B7020;
      v23 = byte_4B7040[0];
LABEL_4:
      if ( v24 > 0 )
      {
        v5 = 0;
        if ( v23 == v3 )
        {
LABEL_11:
          v7 = (v4 + v5 / 6) % 6;
          v8 = v5 + v4;
          v9 = v22;
          v20 = v7;
          v10 = 5 - v8 % 6;
          for ( i = 0; ; i = 1 )
          {
            switch ( v10 )  // 地图上的操作,走到下一个位置
            {
              case 1:
                ++v9;
                break;
              case 2:
                v17 = (v21++ & 1) == 0;
                v9 += v17;
                break;
              case 3:
                v12 = (v21++ & 1) != 0;
                v9 -= v12;
                break;
              case 4:
                --v9;
                break;
              case 5:
                v19 = (v21-- & 1) != 0;
                v9 -= v19;
                break;
              default:
                v18 = (v21-- & 1) == 0;
                v9 += v18;
                break;
            }
            if ( v9 > 9 )
              break;
            if ( v21 > 8 )
              break;
            v13 = &aS_1[10 * v21 + v9];
            if ( *v13 )
              break;
            *v13 = 1;    // 根据行列取地图位置,为0设置为1
            if ( i == 1 )
            {
              ++v4;
              v22 = v9;
              v3 = v25[v4];
              if ( v3 )
                goto LABEL_4;
              goto LABEL_19;
            }
            v10 = v20;
          }
        }
        else
        {
          while ( v24 != ++v5 )
          {
            if ( byte_4B7040[v5] == v3 )
              goto LABEL_11;
          }
        }
      }
    }
    else
    {
LABEL_19:
      // v15 统计地图上0的个数
      v14 = aS_1;
      v15 = 0;
      do
      {
        v16 = v14 + 10;
        do
          v15 += *v14++ == 0;
        while ( v16 != v14 );
      }
      while ( &unk_4B70DA != (_UNKNOWN *)v16 );
      // 地图上不可有0
      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;
}
"S010010011",
"1100100100",
"0010111110",
"0110100100",
"0010010011",
"1101110101",
"0011110101",
"0110010101",
"0001001100"
"S010010011",
"1100100100",
"0010111110",
"0110100100",
"0010010011",
"1101110101",
"0011110101",
"0110010101",
"0001001100"
#include <iostream>
#include <stdio.h>
#include <string>
#include <stack>
#include <vector>
using namespace std;
 
string mp[] = {"S010010011",
               "1100100100",
               "0010111110",
               "0110100100",
               "0010010011",
               "1101110101",
               "0011110101",
               "0110010101",
               "0001001100"};
 
int sum = 0;
stack<int> st;
 
void print()
{
    stack<int> s;
    while (!st.empty())
    {
        s.push(st.top());
        st.pop();
    }
    cout << "opt: ";
    while (!s.empty())
    {
        cout << s.top() << " ";
        st.push(s.top());
        s.pop();
    }
    cout << endl;
}
 
bool opt(int o, int &x, int &y)
{
    if (o > 5)
    {
        printf("error o");
        return false;
    }
 
    switch (o)
    {
    case 1:
        ++x;
        break;
    case 2:
        x += (y++ & 1) == 0;
        break;
    case 3:
        x -= (y++ & 1) != 0;
        break;
    case 4:
        --x;
        break;
    case 5:
        x -= (y-- & 1) != 0;
        break;
    default:
        x += (y-- & 1) == 0;
        break;
    }
    if(x > 9 || x < 0 || y < 0 || y >= 9)
    {
        return false;
    }
    return mp[y][x] == '0';
}
 
bool dfs(int x, int y)
{
    if (sum == 0)
    {
        print();
        return true;
    }
    for (int i = 0; i < 6; i++)
    {
        int xt = x;
        int yt = y;
        if (opt(i, x, y))
        {
            st.push(i);
            sum--;
            mp[y][x] = '1';
            if (dfs(x, y)) return true;
            mp[y][x] = '0';
            sum++;
            st.pop();
        }
        x = xt;
        y = yt;
    }
    return false;
}
 
int main()
{
    for (int i = 0; i < 9; i++)
    {
        for (char c : mp[i])
            if (c == '0')
                sum++;
    }
    dfs(0, 0);
    for (int i = 0; i < 9; i++)
    {
        for (char c : mp[i])
            printf("%c",c);
        printf("\n");
    }
    return 0;
}
#include <iostream>
#include <stdio.h>
#include <string>
#include <stack>
#include <vector>
using namespace std;
 
string mp[] = {"S010010011",
               "1100100100",
               "0010111110",
               "0110100100",
               "0010010011",
               "1101110101",
               "0011110101",
               "0110010101",
               "0001001100"};

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-5-11 16:30 被Wblank编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//