攻防世界--The_Maya_Society

萝らか妹 提交于 2019-11-30 13:33:20

测试文件: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}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!