美文网首页
easytree ---- 2018.10月安恒

easytree ---- 2018.10月安恒

作者: Adam_0 | 来源:发表于2019-01-30 19:29 被阅读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

    相关文章

      网友评论

          本文标题:easytree ---- 2018.10月安恒

          本文链接:https://www.haomeiwen.com/subject/xkncsqtx.html