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!

posted @ 2020-09-24 14:56  jane_315  阅读(390)  评论(0编辑  收藏  举报