zoukankan      html  css  js  c++  java
  • 攻防世界--The_Maya_Society

    测试文件:https://adworld.xctf.org.cn/media/task/attachments/17574fc423474b93a0e6e6a6e583e003.zip

    我们直接将Linux当前日期设置为2012-12-21,运行文件就能得到flag,不过还是要分析一下。

    1.准备

    获取信息

    • 64位文件

    2.IDA打开

    主函数main

    signed __int64 __fastcall main(__int64 a1, char **a2, char **a3)
    {
      size_t v3; // rbx
      size_t v4; // rax
      unsigned __int64 v6; // rax
      unsigned __int64 v7; // rax
      unsigned __int64 v8; // rsi
      char *v9; // rdi
      time_t timer; // [rsp+18h] [rbp-128h]
      char v11[8]; // [rsp+20h] [rbp-120h]
      char src; // [rsp+40h] [rbp-100h]
      char s; // [rsp+60h] [rbp-E0h]
      unsigned __int64 v14; // [rsp+C8h] [rbp-78h]
      char v15; // [rsp+D4h] [rbp-6Ch]
      char v16; // [rsp+DDh] [rbp-63h]
      char v17; // [rsp+E6h] [rbp-5Ah]
      char v18; // [rsp+EFh] [rbp-51h]
      char *v19; // [rsp+F8h] [rbp-48h]
      char *v20; // [rsp+100h] [rbp-40h]
      char *v21; // [rsp+108h] [rbp-38h]
      char *dest; // [rsp+110h] [rbp-30h]
      int *v23; // [rsp+118h] [rbp-28h]
      size_t v24; // [rsp+120h] [rbp-20h]
      struct tm *tp; // [rsp+128h] [rbp-18h]
    
      strcpy(v11, ".fluxfingers.net");
      timer = time(0LL);
      tp = localtime(&timer);
      strftime(&s, 99uLL, "%Y-%m-%d", tp);          // 将现在的日期放入s
      v24 = strlen(&s);                             // v24=99
      sub_B5A(&s, v24);                             // 将日期s进行MD5加密
      v23 = &dword_2030B8;                          // v23为加密后的日期的一部分
      snprintf(
        &v18,
        9uLL,
        "%02x%02x%02x%02x",
        (unsigned __int8)dword_2030B8,
        BYTE1(dword_2030B8),
        BYTE2(dword_2030B8),
        HIBYTE(dword_2030B8));
      v23 = &dword_2030C0;
      snprintf(
        &v17,
        9uLL,
        "%02x%02x%02x%02x",
        (unsigned __int8)dword_2030C0,
        BYTE1(dword_2030C0),
        BYTE2(dword_2030C0),
        HIBYTE(dword_2030C0));
      v23 = &dword_2030B4;
      snprintf(
        &v16,
        9uLL,
        "%02x%02x%02x%02x",
        (unsigned __int8)dword_2030B4,
        BYTE1(dword_2030B4),
        BYTE2(dword_2030B4),
        HIBYTE(dword_2030B4));
      v23 = &dword_2030BC;
      snprintf(
        &v15,
        9uLL,
        "%02x%02x%02x%02x",
        (unsigned __int8)dword_2030BC,
        BYTE1(dword_2030BC),
        BYTE2(dword_2030BC),
        HIBYTE(dword_2030BC));
      snprintf(&src, 33uLL, "%s%s%s%s", &v18, &v17, &v16, &v15);// src为加密后的日期
      v3 = strlen(&src);                            // v3=33
      v4 = strlen(v11);                             // v4=16
      dest = (char *)malloc(v3 + v4 + 1);
      if ( !dest )
        return 1LL;
      *dest = 0;
      strcat(dest, &src);
      strcat(dest, v11);                            // dest为MD5(s)+".fluxfingers.net"
      v21 = sub_18A4(dest);
      if ( !v21 )
        return 1LL;
      v6 = strlen(v21);
      v20 = sub_15E0((__int64)v21, v6, &v14);       // base64解密
      v7 = strlen(v21);
      v19 = sub_15E0((__int64)v21, v7, &v14);
      if ( !v20 )
        return 1LL;
      v8 = v14;
      v9 = v20;
      sub_1858((__int64)v20, v14, (__int64)v19);    // 异或0x25
      ((void (__fastcall *)(char *, unsigned __int64))v19)(v9, v8);
      return 0LL;
    }

    3.代码分析

    3.1 MD5加密

    首先,程序将获取到的时间进行了MD5码加密

      for ( i = 8 * a2 + 1; i % 512 != 448; ++i )
        ;
      v2 = i;
      i /= 8;
      dest = calloc(v2 / 8 + 64, 1uLL);
      memcpy(dest, a1, a2);                         // 将a1中的值存入dest中
      *((_BYTE *)dest + a2) = -128;
      *(_DWORD *)((char *)dest + i) = 8 * a2;
      for ( j = 0; j < i; j += 64 )
      {
        v132 = (char *)dest + j;
        v140 = dword_2030B8;
        v139 = dword_2030C0;
        v138 = dword_2030B4;
        v137 = dword_2030BC;
        for ( k = 0; k <= 0x3F; ++k )               // MD5码加密
        {
          if ( k > 0xF )
          {
            if ( k > 0x1F )
            {
              if ( k > 0x2F )
              {
                v135 = v138 ^ (v139 | ~v137);
                v134 = 7 * (_BYTE)k & 0xF;
              }
              else
              {
                v135 = v137 ^ v138 ^ v139;
                v134 = (3 * (_BYTE)k + 5) & 0xF;
              }
            }
            else
            {
              v135 = v139 & v137 | v138 & ~v137;
              v134 = (5 * (_BYTE)k + 1) & 0xF;
            }
          }
          else
          {
            v135 = v138 & v139 | v137 & ~v139;
            v134 = k;
          }
          v131 = v137;
          v137 = v138;
          v138 = v139;
          v139 += __ROL4__(*(_DWORD *)&v132[4 * v134] + *(&v3 + k) + v135 + v140, *(&v67 + k));
          v140 = v131;
        }
        dword_2030B8 += v140;
        dword_2030C0 += v139;
        dword_2030B4 += v138;
        dword_2030BC += v137;
      }
      free(dest);
    }

    3.2 连接字符串

    将加密后的时间与“.fluxfingers.net”结合

      snprintf(&src, 33uLL, "%s%s%s%s", &v18, &v17, &v16, &v15);// src为加密后的日期
      v3 = strlen(&src);                            // v3=33
      v4 = strlen(v11);                             // v4=16
      dest = (char *)malloc(v3 + v4 + 1);
      if ( !dest )
        return 1LL;
      *dest = 0;
      strcat(dest, &src);
      strcat(dest, v11);                            // dest为MD5(s)+".fluxfingers.net"

    3.3 传递处理

    将得到的字符串传入  v21 = sub_18A4(dest);处理

    char *__fastcall sub_18A4(const char *a1)
    {
      char *v2; // rax
      ns_rr v3; // [rsp+10h] [rbp-24A0h]
      ns_msg v4; // [rsp+430h] [rbp-2080h]
      char s; // [rsp+480h] [rbp-2030h]
      u_char v6; // [rsp+1480h] [rbp-1030h]
      char *dest; // [rsp+2488h] [rbp-28h]
      size_t n; // [rsp+2490h] [rbp-20h]
      char *v9; // [rsp+2498h] [rbp-18h]
      char *src; // [rsp+24A0h] [rbp-10h]
      int v11; // [rsp+24ACh] [rbp-4h]
    
      v11 = __res_query(a1, 1, 16, &v6, 4096);      // 字符串作为查询域名传入,返回消息的长度
      if ( v11 < 0 )
        return 0LL;
      ns_initparse(&v6, v11, &v4);                  // 获得控制句柄
      v11 = v4._counts[1];
      ns_parserr(&v4, ns_s_an, 0, &v3);             // 解析具体区域获取记录类型数据
      ns_sprintrr(&v4, &v3, 0LL, 0LL, &s, 0x1000uLL);// 将字段转换为演示文稿格式
      v2 = strchr(&s, 34);
      src = v2 + 1;
      if ( v2 == (char *)-1LL )
        return 0LL;
      v9 = strchr(src, 34);
      if ( !v9 )
        return 0LL;
      n = v9 - src;
      dest = (char *)malloc(v9 - src + 1);
      strncpy(dest, src, n);
      dest[n] = 0;
      return dest;
    }

    3.4 base64解密

    再对得到的字符串进行base64解密

      v6 = strlen(v21);
      v20 = sub_15E0((__int64)v21, v6, &v14);       // base64解密
      v7 = strlen(v21);
      v19 = sub_15E0((__int64)v21, v7, &v14);
    char *__fastcall sub_15E0(__int64 a1, unsigned __int64 a2, _QWORD *a3)
    {
      char *v4; // rax
      char *v5; // rax
      char *v6; // rax
      _QWORD *v7; // [rsp+8h] [rbp-158h]
      char v8; // [rsp+28h] [rbp-138h]
      unsigned __int8 v9; // [rsp+29h] [rbp-137h]
      unsigned __int8 v10; // [rsp+2Ah] [rbp-136h]
      char v11; // [rsp+2Bh] [rbp-135h]
      char v12[2]; // [rsp+2Ch] [rbp-134h]
      char v13; // [rsp+2Eh] [rbp-132h]
      char v14; // [rsp+2Fh] [rbp-131h]
      char s[61]; // [rsp+30h] [rbp-130h]
      char v16; // [rsp+6Dh] [rbp-F3h]
      char v17; // [rsp+13Fh] [rbp-21h]
      char *v18; // [rsp+140h] [rbp-20h]
      size_t size; // [rsp+148h] [rbp-18h]
      unsigned __int64 i; // [rsp+150h] [rbp-10h]
      char *v21; // [rsp+158h] [rbp-8h]
    
      v7 = a3;
      memset(s, 128, 0x100uLL);
      for ( i = 0LL; i <= 0x3F; ++i )
        s[(unsigned __int8)aAbcdefghijklmn[i]] = i; // base64解密
      v16 = 0;
      size = 0LL;
      for ( i = 0LL; i < a2; ++i )
      {
        if ( s[*(unsigned __int8 *)(a1 + i)] != -128 )
          ++size;
      }
      if ( size & 3 )
        return 0LL;
      v18 = (char *)malloc(size);
      v21 = v18;
      if ( !v18 )
        return 0LL;
      size = 0LL;
      for ( i = 0LL; i < a2; ++i )
      {
        v17 = s[*(unsigned __int8 *)(a1 + i)];
        if ( v17 != -128 )
        {
          v12[size] = *(_BYTE *)(a1 + i);
          *(&v8 + size++) = v17;
          if ( size == 4 )
          {
            v4 = v21++;
            *v4 = (v9 >> 4) | 4 * v8;
            v5 = v21++;
            *v5 = (v10 >> 2) | 16 * v9;
            v6 = v21++;
            *v6 = v11 | (v10 << 6);
            size = 0LL;
          }
        }
      }
      if ( v21 > v18 )
      {
        if ( v13 == 61 )
        {
          v21 -= 2;
        }
        else if ( v14 == 61 )
        {
          --v21;
        }
      }
      *v7 = v21 - v18;
      return v18;
    }
    View Code
    .rodata:0000000000001E80 aAbcdefghijklmn db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/%'

    3.5 异或操作

    最后对解密后的字符串进行异或0x25

    unsigned __int64 __fastcall sub_1858(__int64 a1, unsigned __int64 a2, __int64 a3)
    {
      unsigned __int64 result; // rax
      unsigned __int64 i; // [rsp+20h] [rbp-8h]
    
      for ( i = 0LL; ; ++i )
      {
        result = i;
        if ( i >= a2 )
          break;
        *(_BYTE *)(a3 + i) = *(_BYTE *)(a1 + i) ^ 0x25;
      }
      return result;
    }

    3.6 总结

    实际上就是将获得的日期date进行

    base64(sub_18A4(MD5(date)+".fluxfingers.net")).decode() ^ 0x25

    因此我们获取到正确时间即可。联系到玛雅社会,最出名的就是玛雅预言,因此我们可以判断这个时间就是2012-12-21

    4.get flag!

    flag{e3a03c6f3fe91b40eaa8e71b41f0db12}

  • 相关阅读:
    160. Intersection of Two Linked Lists
    155. Min Stack
    TensorRT caffemodel serialize序列化
    141. Linked List Cycle
    异或运算的性质及应用
    136. Single Number
    【leeetcode】125-Valid Palindrome
    c++函数参数类型-引用、指针、值
    【linux基础】linux远程登录SSH
    【leetcode】122-Best Time to Buy and Sell Stock II
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11594407.html
Copyright © 2011-2022 走看看