下载附件打开后,发现是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!