easytree ---- 2018.10月安恒

2019-01-30  本文已影响0人  Adam_0
首先,用upxshell去壳。 upxshell去壳.png

再用ida打开,shift+F12查找关键字,F5分析主函数。

 int __cdecl main(int argc, const char **argv, const char **envp)
{
  const char *v3; // eax@4
  int v5; // [sp+14h] [bp-2Ch]@1
  __int16 v6; // [sp+1Ah] [bp-26h]@4
  _BYTE v7[3]; // [sp+29h] [bp-17h]@1
  int v8; // [sp+38h] [bp-8h]@4
  int *v9; // [sp+3Ch] [bp-4h]@1

  __main();
  v5 = 0;
  v9 = &v5;
  welcome();
  gets(v7);
  if ( strlen(v7) != 15 )
  {
      printf("Nah... ur a fake reverser!");
      exit(0);
  }
  v8 = createBinTree((int)v7, 15);     // 创建完美二叉树
  preOrderTraverse(v8, v9, (int)&v6);  // 前序遍历
  v3 = (const char *)enc((char *)&v6); // 猜测 base64加密
  if ( !strncmp(v3, "aWNuZXJyc2VhZXRydmVl", 0x14u) )
  {
       puts("well done bro!");
       printf("ur really know something about tree!");
  }
  else
  {
       printf("Nah.. ur an idiot!");
  }
  return 0;
}

将 “aWNuZXJyc2VhZXRydmVl” base64解密 “icnerrseaetrvee”。

接下来分析 createBinTree 函数:

为每个节点创建12个字节,前面四个存自己的值,中间四个存左孩子的地址,最后四个存右孩子的地址。

  v13 = 1;
  v12 = 0;
  v11 = 0;
  v7 = malloc(4 * a2);
  while ( v12 < a2 )
  {
    v6 = (signed int)floor(pow(2.0, (long double)(v13 - 1)));
    v10 = 0;
    for ( i = 0; i < v6; ++i )
    {
        v5 = v12 + i;
        if ( v12 + i >= a2 )
            break;
        v8 = 0;
        if ( *(_BYTE *)(v5 + a1) != 35 )  // 结尾
        {
            v8 = malloc(12u);            // 创建12个字节
            *(_BYTE *)v8 = *(_BYTE *)(v5 + a1);
            v8[1] = 0;
            v8[2] = 0;
            v7[v5] = v8;
        }
        if ( v12 > 0 )
        {
            v4 = v7[v11 + v10];
            if ( i & 1 )                //  左右孩子
            {
              *(_DWORD *)(v4 + 8) = v8;
              ++v10;
            }
            else
            {
              *(_DWORD *)(v4 + 4) = v8;
            }
        }
    }
    v11 = v12;
    v12 += v6;
    ++v13;
  }
  v2 = *v7;
  free(v7);
  return v2;
  }

在分析 preOrderTraverse 函数:

这个是二叉树的遍历,遍历又分:前序遍厉,中序遍历,后序遍历。这个是前序遍历。

int __cdecl preOrderTraverse(int a1, _DWORD *a2, int a3)
{
  int v3; // eax@2
  int result; // eax@2

  if ( a1 )
  {
    v3 = (*a2)++;
    *(_BYTE *)(a3 + v3) = *(_BYTE *)a1;
    preOrderTraverse(*(_DWORD *)(a1 + 4), a2, a3);
    result = preOrderTraverse(*(_DWORD *)(a1 + 8), a2, a3);
  }
  return result;
}

将得到的字符串“icnerrseaetrvee”根据所创建的二叉树结构和前序遍历得到树的结构

二叉树结构.png

得到flag : icanreversetree

注:

1.树与二叉树以及二叉树的遍历:(参考大佬文章)(https://blog.csdn.net/johnny901114/article/details/80574803

上一篇下一篇

猜你喜欢

热点阅读