逆向攻防世界CTF系列56-easy_Maze

逆向攻防世界CTF系列56-easy_Maze

64位无壳,看题目就知道是迷宫问题了

c 复制代码
int __fastcall main(int argc, const char **argv, const char **envp){
  __int64 v3; // rax
  int v5[7][7]; // [rsp+0h] [rbp-270h] BYREF
  int v6[104]; // [rsp+D0h] [rbp-1A0h] BYREF

  v6[52] = 1;
  v6[53] = 1;
  v6[54] = -1;
  v6[55] = 1;
  v6[56] = -1;
  v6[57] = 1;
  v6[58] = -1;
  v6[59] = 0;
  v6[60] = 0;
  v6[61] = 0;
  v6[62] = 0;
  v6[63] = 1;
  v6[64] = -1;
  v6[65] = 0;
  v6[66] = 0;
  v6[67] = 1;
  v6[68] = 0;
  v6[69] = 0;
  v6[70] = 1;
  v6[71] = 0;
  v6[72] = -1;
  v6[73] = -1;
  v6[74] = 0;
  v6[75] = 1;
  v6[76] = 0;
  v6[77] = 1;
  v6[78] = -1;
  v6[79] = 0;
  v6[80] = -1;
  memset(&v6[81], 0, 20);
  v6[86] = 1;
  v6[87] = -1;
  v6[88] = -1;
  v6[89] = 1;
  v6[90] = -1;
  v6[91] = 0;
  v6[92] = -1;
  v6[93] = 2;
  v6[94] = 1;
  v6[95] = -1;
  v6[96] = 0;
  v6[97] = 0;
  v6[98] = -1;
  v6[99] = 1;
  v6[100] = 0;
  memset(v6, 0, 196);
  memset(v5, 0, sizeof(v5));
  Step_0((int (*)[7])&v6[52], 7, (int (*)[7])v6);
  Step_1((int (*)[7])v6, 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(v5, 7);
  system("pause");
  return 0;
}

先看step0

c 复制代码
__int64 __fastcall Step_0(int (*a1)[7], int a2, int (*a3)[7]){
  for ( i = 0; ; ++i ){
    result = i;
    if ( (int)i >= a2) break;
    for ( j = 0; j < a2; ++j ) (*a3)[7 * i + j] = (*a1)[7 * j + a2 - i - 1];
  }
  return result;
}

(*a3)[7 * i + j] = (*a1)[7 * j + a2 - i - 1];简单模拟下就会发现这是翻转迷宫

看Step1:

c 复制代码
__int64 __fastcall Step_1(int (*a1)[7], int a2, int (*a3)[7]){
  int v5[7]; // [rsp+20h] [rbp-D0h] BYREF
  int v6; // [rsp+E4h] [rbp-Ch]
  int j; // [rsp+E8h] [rbp-8h]
  int i; // [rsp+ECh] [rbp-4h]

  v6 = getA(a1, a2);
  if ( !v6 ) return 0LL;
  getAStart(a1, a2, (int (*)[7])v5);
  for ( i = 0; i < a2; ++i ){
    for ( j = 0; j < a2; ++j )
      (*a3)[7 * i + j] = v5[7 * i + j] / v6;
  }
  return 1LL;
}

突然想到Please help me out!前Step0和1肯定是执行完了,可能只是初始化,并不用看那么细,我们还是大致看看

看Step2

c 复制代码
__int64 __fastcall Step_2(int (*a1)[7]){
  int v1; // eax
  __int64 v2; // rax
  __int64 v3; // 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 > 100 )
    {
      if ( v7 == 115 ){
        ++v10;
      }
      else
      {
        if ( v7 != 119 )
          goto LABEL_14;
        --v10;
      }
    }
    else if ( v7 == 97 ){
      --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);
    return 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>>);
    return 0LL;
  }
}

看出来终点是6,6,output里输出flag

熟悉的aswd:

动态调试step2

注意鼠标放在v5上会显示数据,跟进去取数据会有坑

走一遍答案:UNCTF{ssddwdwdddssaasasaaassddddwdds}

第二种方法GDB动态调试,首先看汇编代码,v5给了eax寄存器,那么有确定的内存位置就可以直接打印内存了,如果不知道v5放在哪里的话是没办法打印内存的。这里v5给了rax和rdi,所以两个都可以查。

根据上图的汇编地址,断点断在564793D24AB0即可:(这是别人的图,我自己找不到断掉,知道用./80dw命令显示rax寄存器即可,w是双字,d是整数打印。)

方法GDB动态调试,首先看汇编代码,v5给了eax寄存器,那么有确定的内存位置就可以直接打印内存了,如果不知道v5放在哪里的话是没办法打印内存的。这里v5给了rax和rdi,所以两个都可以查。

根据上图的汇编地址,断点断在564793D24AB0即可:(这是别人的图,我自己找不到断掉,知道用./80dw命令显示rax寄存器即可,w是双字,d是整数打印。)

相关推荐
厂太_STAB_丝针1 小时前
【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】
c语言·单片机·嵌入式硬件
利刃大大3 小时前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
charlie1145141913 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(协议层封装)
c语言·驱动开发·单片机·学习·教程·oled
*TQK*3 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点
Rachela_z3 小时前
代码随想录算法训练营第十四天| 二叉树2
数据结构·算法
细嗅蔷薇@3 小时前
迪杰斯特拉(Dijkstra)算法
数据结构·算法
追求源于热爱!3 小时前
记5(一元逻辑回归+线性分类器+多元逻辑回归
算法·机器学习·逻辑回归
ElseWhereR4 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
Smark.4 小时前
Gurobi基础语法之 addConstr, addConstrs, addQConstr, addMQConstr
算法
*TQK*4 小时前
ZZNUOJ(C/C++)基础练习1031——1040(详解版)
c语言·c++·编程知识点