love----bugku

1.下载文件,看到是一个程序,直接ida打开,这里用32位,不然看不了反编译。(我电脑是缺少文件打开程序不了,所以我们就跳过查看程序,直接进入分析)
2.使用shift+F12查看字符串,


反编译代码如下:

int __cdecl sub_4156E0()
{
  size_t v0; // eax@6
  const char *v1; // eax@6
  size_t v2; // eax@9
  char v4; // [sp+Ch] [bp-17Ch]@1
  size_t v5; // [sp+10h] [bp-178h]@3
  size_t j; // [sp+DCh] [bp-ACh]@6
  size_t i; // [sp+E8h] [bp-A0h]@1
  char Str1[108]; // [sp+F4h] [bp-94h]@5
  char Str; // [sp+160h] [bp-28h]@6
  char v10; // [sp+17Ch] [bp-Ch]@6
  unsigned int v11; // [sp+184h] [bp-4h]@1
  int v12; // [sp+188h] [bp+0h]@1      ###定义各种变量的类型

  memset(&v4, -858993460, 0x17Cu);
  v11 = (unsigned int)&v12 ^ __security_cookie;
  for ( i = 0; (signed int)i < 100; ++i )
  {
    v5 = i;
    if ( i >= 0x64 )
      sub_411154();
    Str1[v5] = 0;
  }
  sub_41132F("please enter the flag:");
  sub_411375("%20s", &Str);
  v0 = j_strlen(&Str);
  v1 = (const char *)sub_4110BE(&Str, v0, &v10);        ###再这里我们明确,用户的输入经过sub_4110BE这个函数的操作,进行了加密
  strncpy(Str1, v1, 0x28u);          ###将v1用户输入复制给str1
  sub_411127();
  i = j_strlen(Str1);
  for ( j = 0; (signed int)j < (signed int)i; ++j )      ##此处我们看到j比用户输入的i长度小的时候,会遍历用户输入的str1,循环一次之后使用j之前+1
    Str1[j] += j;                ##用书输入的str1中的j位等于j+1
  v2 = j_strlen(Str1);            ###将str1的长度给v2
  strncmp(Str1, "e3nifIH9b_C@n@dH", v2);      ##比较str1和"e3nifIH9b_C@n@dH"比较,并且对比str1的长度,如果相同则输出flag,不同则错误
  if ( sub_411127() )
    sub_41132F("wrong flag!\n");
  else
    sub_41132F("rigth flag!\n");
  sub_41126C();
  sub_411280();
  return sub_411127();
}


加密函数的内容:

int __cdecl sub_411AB0(int a1, unsigned int a2, int a3)
{
  int v4; // [sp+Ch] [bp-100h]@1
  int v5; // [sp+D4h] [bp-38h]@7
  int i; // [sp+E0h] [bp-2Ch]@7
  unsigned int v7; // [sp+ECh] [bp-20h]@1
  void *Dst; // [sp+F8h] [bp-14h]@1
  int v9; // [sp+104h] [bp-8h]@1      ##也是初始定义了一些变量值,我们要注意a2是用户的输入

  memset(&v4, -858993460, 0x100u);
  v9 = 0;
  Dst = 0;
  v7 = 0;
  if ( a1 && a2 )
  {
    v7 = a2 / 3;
    if ( (signed int)(a2 / 3) % 3 )
      ++v7;
    v7 *= 4;
    *(_DWORD *)a3 = v7;
    malloc(v7 + 1);
    Dst = (void *)sub_411127();
    if ( Dst )
    {
      j_memset(Dst, 0, v7 + 1);
      v9 = a1;
      v7 = a2;
      i = 0;
      v5 = 0;
      while ( (signed int)v7 > 0 )
      {
        byte_41A144[2] = 0;
        byte_41A144[1] = 0;
        byte_41A144[0] = 0;
        for ( i = 0; i < 3 && (signed int)v7 >= 1; ++i )
        {
          byte_41A144[i] = *(_BYTE *)v9;
          --v7;
          ++v9;
        }
        if ( !i )
          break;
        v4 = i;
        if ( i == 1 )
        {
          *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
          *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
          *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
          *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
        }
        else
        {
          if ( v4 == 2 )
          {
            *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
            *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
            *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
            *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
          }
          else
          {
            if ( v4 == 3 )
            {
              *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
              *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
              *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
              *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[byte_41A144[2] & 0x3F];
            }
          }
        }
      }
      *((_BYTE *)Dst + v5) = 0;
    }
  }
  return sub_411127();
}



我们看到此处结果是经过了base64解密了的,也就是说我们输入的东西,经过加密函数操作,变成e3nifIH9b_C@n@dH,进行比较,如果相同,那么输出flag正确,用户的输入再经过base64解码就是flag了。所以接下来我们需要写一个脚本模拟这个情况,前提是我们要看懂加密函数才能正确写出脚本。我此时太菜,看不懂加密函数,所以只要看别人的脚本。才懂得加密函数大概就是用户原来的输入假入是bc,bc再ascii码62和63,因为b在0位置,所以63+0再转ascii,同理63代表c,在位置1,所以63+1等于64为d,依次类推,这就是加密函数的作用,结果就得e3nifIH9b_C@n@dH,所以我们脚本要反其道而行:



解码得出flag

posted @ 2021-02-27 22:42  网抑云黑胶SVIP用户  阅读(127)  评论(0编辑  收藏  举报