攻防世界easy_Maze

本文详细介绍了如何使用ida分析main函数中的Step_0, Step_1, Step_2函数,理解其功能及输入与行走方向的关系。通过对Step_2的动态分析,利用gdb设置断点,观察maze数组的值,最终得出flag:UNCTF{ssddwdwdddssaasasaaassddddwdds}。" 103977341,1085926,Traffic Server缓存机制与管理工具详解,"['缓存技术', '网络代理', 'HTTP协议', '服务器管理', 'DNS解析']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ida进入main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  int v5[52]; // [rsp+0h] [rbp-270h] BYREF
  int v6[52]; // [rsp+D0h] [rbp-1A0h] BYREF
  int v7[7]; // [rsp+1A0h] [rbp-D0h] BYREF
  int v8; // [rsp+1BCh] [rbp-B4h]
  int v9; // [rsp+1C0h] [rbp-B0h]
  int v10; // [rsp+1C4h] [rbp-ACh]
  int v11; // [rsp+1C8h] [rbp-A8h]
  int v12; // [rsp+1CCh] [rbp-A4h]
  int v13; // [rsp+1D0h] [rbp-A0h]
  int v14; // [rsp+1D4h] [rbp-9Ch]
  int v15; // [rsp+1D8h] [rbp-98h]
  int v16; // [rsp+1DCh] [rbp-94h]
  int v17; // [rsp+1E0h] [rbp-90h]
  int v18; // [rsp+1E4h] [rbp-8Ch]
  int v19; // [rsp+1E8h] [rbp-88h]
  int v20; // [rsp+1ECh] [rbp-84h]
  int v21; // [rsp+1F0h] [rbp-80h]
  int v22; // [rsp+1F4h] [rbp-7Ch]
  int v23; // [rsp+1F8h] [rbp-78h]
  int v24; // [rsp+1FCh] [rbp-74h]
  int v25; // [rsp+200h] [rbp-70h]
  int v26; // [rsp+204h] [rbp-6Ch]
  int v27; // [rsp+208h] [rbp-68h]
  int v28; // [rsp+20Ch] [rbp-64h]
  int v29; // [rsp+210h] [rbp-60h]
  int v30; // [rsp+214h] [rbp-5Ch]
  int v31; // [rsp+218h] [rbp-58h]
  int v32; // [rsp+21Ch] [rbp-54h]
  int v33; // [rsp+220h] [rbp-50h]
  int v34; // [rsp+224h] [rbp-4Ch]
  int v35; // [rsp+228h] [rbp-48h]
  int v36; // [rsp+22Ch] [rbp-44h]
  int v37; // [rsp+230h] [rbp-40h]
  int v38; // [rsp+234h] [rbp-3Ch]
  int v39; // [rsp+238h] [rbp-38h]
  int v40; // [rsp+23Ch] [rbp-34h]
  int v41; // [rsp+240h] [rbp-30h]
  int v42; // [rsp+244h] [rbp-2Ch]
  int v43; // [rsp+248h] [rbp-28h]
  int v44; // [rsp+24Ch] [rbp-24h]
  int v45; // [rsp+250h] [rbp-20h]
  int v46; // [rsp+254h] [rbp-1Ch]
  int v47; // [rsp+258h] [rbp-18h]
  int v48; // [rsp+25Ch] [rbp-14h]
  int v49; // [rsp+260h] [rbp-10h]

  v7[0] = 1;
  v7[1] = 1;
  v7[2] = -1;
  v7[3] = 1;
  v7[4] = -1;
  v7[5] = 1;
  v7[6] = -1;
  v8 = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  v12 = 1;
  v13 = -1;
  v14 = 0;
  v15 = 0;
  v16 = 1;
  v17 = 0;
  v18 = 0;
  v19 = 1;
  v20 = 0;
  v21 = -1;
  v22 = -1;
  v23 = 0;
  v24 = 1;
  v25 = 0;
  v26 = 1;
  v27 = -1;
  v28 = 0;
  v29 = -1;
  v30 = 0;
  v31 = 0;
  v32 = 0;
  v33 = 0;
  v34 = 0;
  v35 = 1;
  v36 = -1;
  v37 = -1;
  v38 = 1;
  v39 = -1;
  v40 = 0;
  v41 = -1;
  v42 = 2;
  v43 = 1;
  v44 = -1;
  v45 = 0;
  v46 = 0;
  v47 = -1;
  v48 = 1;
  v49 = 0;
  memset(v6, 0, 0xC0uLL);
  v6[48] = 0;
  memset(v5, 0, 0xC0uLL);
  v5[48] = 0;
  Step_0((int (*)[7])v7, 7, (int (*)[7])v6);
  Step_1((int (*)[7])v6, 7, (int (*)[7])v5);
  v3 = std::operator<<<std::char_traits<char>>(&_bss_start, "Please help me out!");
  std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
  Step_2((int (*)[7])v5);
  system("pause");
  return 0;
}

可以看到这里有三个函数,Step_0,Step_1,Step_2,应该就是对已有数据的操作了。变量中v9已知;v7,maze未知,所以猜测Step_0函数负责将v9的值经过变换传递给v7,Step_1负责将v7的值变化传递给maze,最终由在Step_2处传入maze数组。
进入Step_2函数

__int64 __fastcall Step_2(int (*a1)[7])
{
  int v1; // eax
  __int64 v2; // rax
  __int64 v3; // rax
  __int64 result; // rax
  __int64 v5; // rax
  char v6[35]; // [rsp+10h] [rbp-30h] BYREF
  char v7; // [rsp+33h] [rbp-Dh] BYREF
  int v8; // [rsp+34h] [rbp-Ch]
  int v9; // [rsp+38h] [rbp-8h]
  int v10; // [rsp+3Ch] [rbp-4h]

  v10 = 0;
  v9 = 0;
  v8 = 0;
  while ( v8 <= 29 && (*a1)[7 * v10 + v9] == 1 )
  {
    std::operator>><char,std::char_traits<char>>(&std::cin, &v7);
    v1 = v8++;
    v6[v1] = v7;
    if ( v7 == 100 )
    {
      ++v9;
    }
    else if ( v7 > 'd' )
    {
      if ( v7 == 's' )
      {
        ++v10;
      }
      else
      {
        if ( v7 != 'w' )
          goto LABEL_14;
        --v10;
      }
    }
    else if ( v7 == 'a' )
    {
      --v9;
    }
    else
    {
LABEL_14:
      v2 = std::operator<<<std::char_traits<char>>(&_bss_start, "include illegal words.");
      std::ostream::operator<<(v2, &std::endl<char,std::char_traits<char>>);
    }
  }
  if ( v10 == 6 && v9 == 6 )
  {
    v3 = std::operator<<<std::char_traits<char>>(&_bss_start, "Congratulations!");
    std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
    output(v6, v8);
    result = 1LL;
  }
  else
  {
    v5 = std::operator<<<std::char_traits<char>>(&_bss_start, "Oh no!,Please try again~~");
    std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
    result = 0LL;
  }
  return result;
}

从数组(a1)[7i+j]的表示中可以看出,数组的行数为7。(7*7 的二维数组)

由while循环看出,输入最长不能超过30,且必须是”w”,”a”,”d”,”s”。

输入”w”,i–;输入”s”,i++;

输入”a”,j–;输入”d”,j++;

可以看出迷宫从左上角出发。
从最后的判断条件i6,j6可以看出,最终移动目标是右下角。、
这样就分析清楚了我们的输入与行走方向的对应关系。之后我们知道迷宫究竟是怎么样的。这由Step_0和Step_1函数决定。

我们可以继续对他们两个函数进行静态分析,写出他们的功能,求出迷宫表达式。但是因为我们是从Step_2函数的位置才开始输入的,Step_1的输出结果与我们的输入无关,是一个固定不变的值,所以我们可以用gdb进行动态分析,让他直接运行到Step_2函数处,然后直接查看maze的代码。具体操作如下:
输入命令:info functions Step,返回所有名称带有Step的函数:
在这里插入图片描述
我们给Step_2函数下一个断点:b Step_2
在这里插入图片描述
输入命令:r运行至Step函数开始位置。函数刚开始运行时,会为我们的输入分配内存空间。因为是x64系统,所以函数传递参数时会先通过寄存器传参。下图框起来的部分就是将函数参数存储到栈中的过程:
在这里插入图片描述
输入命令:print $寄存器。将输入的参数打印出来,rdi所存的参数就是maze数组的起始地址。
在这里插入图片描述
输入命令:x/80dw $1,将该片内存空间的数据打印出来,取前49个数据,这便是maze数组的元素:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
flag: UNCTF{ssddwdwdddssaasasaaassddddwdds}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值