BUUCTF SimpleRev RE

64位无壳
IDA64打开
直接定位到main函数
简单阅读可知main函数不重要
关键的是Decry这个函数
点进去看看

unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h] BYREF
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  int v10; // [rsp+50h] [rbp-10h]
  unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  *(_QWORD *)src = 0x534C43444ELL;
  v7 = 0LL;
  v8 = 0;
  v9[0] = 0x776F646168LL;
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

有点长,那我们一句句分析
R键转化出来src = 'SLCDN'; v9 = 'wodah';
由于是小端序存储,要取反所以
src='NDCLS'; v9='hadow';
接着查看join函数

char *__fastcall join(const char *a1, const char *a2)
{
  size_t v2; // rbx
  size_t v3; // rax
  char *dest; // [rsp+18h] [rbp-18h]

  v2 = strlen(a1);
  v3 = strlen(a2);
  dest = (char *)malloc(v2 + v3 + 1);
  if ( !dest )
    exit(1);
  strcpy(dest, a1);
  strcat(dest, a2);
  return dest;
}

本质上就是将两个字符串连接
经查看key3='kills'; key1='ADSFK';
text='killshadow'; key='ADSFKNDCLS';

for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }

这一段是将key大写转小写key='adsfkndcls';
接下来就是一直读入v1

  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }

意思就是只要是大小写字母就执行
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
最后str2若是和text一样则说明读入的v1flag
由于存在取余操作,不好直接求解
我们可以通过循环暴力破解

点击查看代码
text='killshadow'
key='adsfkndcls'
flag=''
for i in range(len(text)):
    for x in range(65,123):
        if text[i] == chr((x-39-ord(key[i])+97)%26+97):
            flag+=chr(x)
            break
print(flag)

flag{KLDQCUDFZO}

posted @ 2023-01-28 22:53  Tree_24  阅读(23)  评论(0编辑  收藏  举报