这是个exe程序,reverse_3.exe,打开却被提示各种运行库缺失。。。

安装完dll文件后,打开后让我们输入flag。

随便输入字符串然后回车,显示wrong flag然后退出了。。。

先用OD载入动态调试吧,毕竟比较熟悉OD= =

根据F8步过,直到地址013A5758,此处为输入值的地方,先随意输入一串值1234567890abcdefg,回车。

接下来就是F8,来到了一处判断数据的地方。这里我打了两个断点,013A57ED013A5807。因为有循环跳转,这样,可以直接按F9来快速通过这两个断点了。

如果是按F8会跟踪一个数据,MTIzNDU2Nzg5MGFiY2RlZmc=,这个是我们输入的字符串1234567890abcdefg的base64。而接下来就是取这个MTIzNDU2Nzg5MGFiY2RlZmc=的每一位做比较了。在这个比较中,发现读取了e3nifIH9b_C@n@dH这个字符串,但是却不是直接和这个字符串做比较,应该是做了处理。

这里用IDA(此处用32-bit)打开,看看伪代码吧。可以用search --> text快速定位到关键程序位置。

F5得到伪代码:

__int64 main_0()
{
  size_t v0; // eax
  const char *v1; // eax
  size_t v2; // eax
  int v3; // edx
  __int64 v4; // ST08_8
  signed int j; // [esp+DCh] [ebp-ACh]
  signed int i; // [esp+E8h] [ebp-A0h]
  signed int v8; // [esp+E8h] [ebp-A0h]
  char Dest[108]; // [esp+F4h] [ebp-94h]
  char Str; // [esp+160h] [ebp-28h]
  char v11; // [esp+17Ch] [ebp-Ch]

  for ( i = 0; i < 100; ++i )
  {
    if ( (unsigned int)i >= 0x64 )
      j____report_rangecheckfailure();
    Dest[i] = 0;
  }
  sub_41132F("please enter the flag:");
  sub_411375("%20s", &Str);
  v0 = j_strlen(&Str);
  v1 = (const char *)sub_4110BE(&Str, v0, &v11);
  strncpy(Dest, v1, 0x28u);
  v8 = j_strlen(Dest);
  for ( j = 0; j < v8; ++j )
    Dest[j] += j;
  v2 = j_strlen(Dest);
  if ( !strncmp(Dest, Str2, v2) )
    sub_41132F("rigth flag!\n");
  else
    sub_41132F("wrong flag!\n");
  HIDWORD(v4) = v3;
  LODWORD(v4) = 0;
  return v4;
}

关键代码在这里:

v0 = j_strlen(&Str);
v1 = (const char *)sub_4110BE(&Str, v0, &v11);
strncpy(Dest, v1, 0x28u);
v8 = j_strlen(Dest);
for ( j = 0; j < v8; ++j )
  Dest[j] += j;
v2 = j_strlen(Dest);
if ( !strncmp(Dest, Str2, v2) )
  sub_41132F("rigth flag!\n");
else
  sub_41132F("wrong flag!\n");

Str2为字符串e3nifIH9b_C@n@dH

Str2Dest比较。而Dest为取v1的前长度0x28u的字符。

v1的值来自函数sub_4110BE

sub_4110BE取自sub_411AB0

void *__cdecl sub_4110BE(int a1, int a2, int a3)
{
  return sub_411AB0((char *)a1, a2, (int *)a3);
}

sub_411AB0

void *__cdecl sub_411AB0(char *a1, unsigned int a2, int *a3)
{
  int v4; // STE0_4
  int v5; // STE0_4
  int v6; // STE0_4
  int v7; // [esp+D4h] [ebp-38h]
  signed int i; // [esp+E0h] [ebp-2Ch]
  unsigned int v9; // [esp+ECh] [ebp-20h]
  int v10; // [esp+ECh] [ebp-20h]
  signed int v11; // [esp+ECh] [ebp-20h]
  void *Dst; // [esp+F8h] [ebp-14h]
  char *v13; // [esp+104h] [ebp-8h]

  if ( !a1 || !a2 )
    return 0;
  v9 = a2 / 3;
  if ( (signed int)(a2 / 3) % 3 )
    ++v9;
  v10 = 4 * v9;
  *a3 = v10;
  Dst = malloc(v10 + 1);
  if ( !Dst )
    return 0;
  j_memset(Dst, 0, v10 + 1);
  v13 = a1;
  v11 = a2;
  v7 = 0;
  while ( v11 > 0 )
  {
    byte_41A144[2] = 0;
    byte_41A144[1] = 0;
    byte_41A144[0] = 0;
    for ( i = 0; i < 3 && v11 >= 1; ++i )
    {
      byte_41A144[i] = *v13;
      --v11;
      ++v13;
    }
    if ( !i )
      break;
    switch ( i )
    {
      case 1:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v4 = v7 + 1;
        *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
        *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[64];
        *((_BYTE *)Dst + v4) = aAbcdefghijklmn[64];
        v7 = v4 + 1;
        break;
      case 2:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v5 = v7 + 1;
        *((_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];
        v7 = v5 + 1;
        break;
      case 3:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v6 = v7 + 1;
        *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
        *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
        *((_BYTE *)Dst + v6) = aAbcdefghijklmn[byte_41A144[2] & 0x3F];
        v7 = v6 + 1;
        break;
    }
  }
  *((_BYTE *)Dst + v7) = 0;
  return Dst;
}

上述代码的意思是,将输入的值,每3位变成4位。。。。其实是base64加密。

aAbcdefghijklmnABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= 字串。

所以Destv1来,v1会通过base64加密,然后对Dest做了第二次的加密,v8Dest的长度。

for ( j = 0; j < v8; ++j )
  Dest[j] += j;

所以最终我们可以写一个脚本来反求得到flag:

import base64
Str='e3nifIH9b_C@n@dH'
fla=''
for i in range(len(Str)):
    fla+=chr(ord(Str[i])-i)
print base64.b64decode(fla)

flag{i_l0ve_you}