• buuctf-level4


    下载附件打开后,发现是linux下的可执行文件,使用IDA(64)打开,发现与二叉树的遍历顺序有关,如图:

     可以发现type1和type2函数即为关键的函数,进去查看发现:

    __int64 __fastcall type1(char *a1)
    {
      __int64 result; // rax
    
      if ( a1 )
      {
        type1(*((_QWORD *)a1 + 1));
        putchar(*a1);
        result = type1(*((_QWORD *)a1 + 2));
      }
      return result;
    }
    int __fastcall type2(char *a1)
    {
      int result; // eax
    
      if ( a1 )
      {
        type2(*((_QWORD *)a1 + 1));
        type2(*((_QWORD *)a1 + 2));
        result = putchar(*a1);
      }
      return result;
    }

    结合主函数我们可以知道,程序会打印出中序遍历和后序遍历的结果,已知一个二叉树的中序和后序,那么我们就可以画出这个二叉树,而flag应该就是二叉树先序遍历的结果。先把程序放到linux下运行,看看结果:

    中序:"2f0t02T{hcsiI_SwA__r7Ee}"
    后序:"20f0Th{2tsIS_icArE}e7__w"
    于是我们可以根据中序遍历与后序遍历的顺序特征来画出二叉树
    先序遍历:先根,后左,再右
    中序遍历:先左,后根,再右
    后序遍历:先左,后右,再根
    解决思路如下:

    ①根据后序(左,右,根),可以知道'w'为整个二叉树的根节点,再根据中序遍历,可以知道数的左边为‘2f0t02T{hcsiI_S’,右边集合为'A__r7Ee}'

    ②再根据后序遍历的结果,可以知道对应左边和右边的最后一位定是根节点,也就是'w'根节点的左右孩子,即左孩子'c',右孩子'_'

    ③先分别左边,对于中序遍历结果‘2f0t02T{hcsiI_S’而言,现在'c'为根节点,故节点左边集合为‘2f0t02T{h’,右边为'siI_S',此时再根据对应的后序,可以知道,对于左边,'t'为根,对于右边'i'为根,以此类推,最终可以画出这样一个二叉树,如图:

     写出次二叉树的先序遍历结果:wctf2020{This_IS_A_7reE},得到flag!

  • 相关阅读:
    线性时间将两个有序链表合成一个有序链表(constant additional space)
    C++定义指针数组
    cmd运行java编译文件
    java的方法
    Java流程控制
    用户交互-Scanner
    Java的注释
    编译型语言和解释性语言
    JDK、JRE和JVM
    MarkDown的简单使用
  • 原文地址:https://www.cnblogs.com/jane315/p/13724084.html
Copyright © 2020-2023  润新知