[羊城杯 2020]easyre

[羊城杯 2020]easyre,第1张

[羊城杯 2020]easyre

用PE查壳

 用ida打开找到main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int v5; // eax
  int result; // eax
  char flag; // [rsp+20h] [rbp-60h]
  char Str1; // [rsp+50h] [rbp-30h]
  char v9; // [rsp+90h] [rbp+10h]
  char v10; // [rsp+D0h] [rbp+50h]
  char Str2[8]; // [rsp+110h] [rbp+90h]
  int v12; // [rsp+14Ch] [rbp+CCh]

  _main();
  strcpy(Str2, "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG");
  puts("Hello, please input your flag and I will tell you whether it is right or not.");
  scanf("%38s", &flag);
  if ( strlen(&flag) == 38
    && (v3 = strlen(&flag), (unsigned int)encode_one(&flag, v3, &v10, &v12) == 0)
    && (v4 = strlen(&v10), (unsigned int)encode_two(&v10, v4, &v9, &v12) == 0)
    && (v5 = strlen(&v9), (unsigned int)encode_three(&v9, v5, &Str1, &v12) == 0)
    && !strcmp(&Str1, Str2) )
  {
    puts("you are right!");
    result = 0;
  }
  else
  {
    printf("Something wrong. Keep going.");
    result = 0;
  }
  return result;
}

 看到有三层加密,动态调试可以找到v10,v12,v9,Str1的初始化值为零,也可以根据调用情况看是否被其他函数调用。

第一层加密:

int64 __fastcall encode_one(const char *flag, int a2, char *a3, int *a4)
{
  int v5; // esi
  int v6; // esi
  int v7; // esi
  int v8; // [rsp+34h] [rbp-1Ch]
  int v9; // [rsp+38h] [rbp-18h]
  char *v10; // [rsp+40h] [rbp-10h]
  int v11; // [rsp+48h] [rbp-8h]
  int i; // [rsp+4Ch] [rbp-4h]
  unsigned __int8 *v13; // [rsp+70h] [rbp+20h]
  int len; // [rsp+78h] [rbp+28h]
  int *v15; // [rsp+88h] [rbp+38h]

  v13 = (unsigned __int8 *)flag;
  len = a2;                                     // v14=strlen(flag) len=38
  v15 = a4;
  if ( !flag || !a2 )
    return 0xFFFFFFFFi64;
  v11 = 0;
  if ( a2 % 3 )
    v11 = 3 - a2 % 3;                           // v11=1
  v9 = a2 + v11;                                // v9=39
  v8 = 8 * (a2 + v11) / 6;                      // v8=52
  v10 = a3;
  for ( i = 0; i < v9; i += 3 )
  {
    *v10 = alphabet[(char)*v13 >> 2];
    if ( len + v11 - 3 == i && v11 )            // 36==i && v11
    {
      if ( v11 == 1 )
      {
        v5 = (char)cmove_bits(*v13, 6, 2);
        v10[1] = alphabet[v5 + (char)cmove_bits(v13[1], 0, 4)];
        v10[2] = alphabet[(char)cmove_bits(v13[1], 4, 2)];
        v10[3] = 61;
      }
      else if ( v11 == 2 )
      {
        v10[1] = alphabet[(char)cmove_bits(*v13, 6, 2)];
        v10[2] = 61;
        v10[3] = 61;
      }
    }
    else
    {
      v6 = (char)cmove_bits(*v13, 6, 2);
      v10[1] = alphabet[v6 + (char)cmove_bits(v13[1], 0, 4)];
      v7 = (char)cmove_bits(v13[1], 4, 2);
      v10[2] = alphabet[v7 + (char)cmove_bits(v13[2], 0, 6)];
      v10[3] = alphabet[v13[2] & 0x3F];
    }
    v10 += 4;
    v13 += 3;
  }
  if ( v15 )
    *v15 = v8;
  return 0i64;
}

alphabet的值为:

其实我一开始也没有看到这是base64加密,直到我解出了第二道、第三道的结果我才发现这是base64加密

第二道加密是简单的置换

_int64 __fastcall encode_two(const char *a1, int a2, char *V9, int *a4)
{
  char *Source; // [rsp+40h] [rbp+10h]
  char *A; // [rsp+50h] [rbp+20h]

  Source = (char *)a1;
  A = V9;
  if ( !a1 || !a2 )
    return 0xFFFFFFFFi64;
  strncpy(V9, a1 + 26, 0xDui64);
  strncpy(A + 13, Source, 0xDui64);
  strncpy(A + 26, Source + 39, 0xDui64);
  strncpy(A + 39, Source + 13, 0xDui64);
  return 0i64;
}

 第三是凯撒的加密,但是配合上了数字

_int64 __fastcall encode_three(const char *a1, int len, char *a3, int *a4)
{
  char v5; // [rsp+Fh] [rbp-11h]
  int i; // [rsp+14h] [rbp-Ch]
  char *v7; // [rsp+18h] [rbp-8h]
  const char *v8; // [rsp+30h] [rbp+10h]

  v8 = a1;
  if ( !a1 || !len )
    return 0xFFFFFFFFi64;
  v7 = a3;                                      // V7已知反推V8(v5),也就是a1
  for ( i = 0; i < len; ++i )
  {
    v5 = *v8;
    if ( *v8 <= 64 || v5 > 90 )
    {
      if ( v5 <= 96 || v5 > 122 )
      {
        if ( v5 <= 47 || v5 > 57 )
          *v7 = v5;
        else
          *v7 = (v5 - 48 + 3) % 10 + 48;
      }
      else
      {
        *v7 = (v5 - 97 + 3) % 26 + 97;
      }
    }
    else
    {
      *v7 = (v5 - 65 + 3) % 26 + 65;
    }
    ++v7;
    ++v8;
  }
  return 0i64;
}

 其实就是你过来的解密,密文为EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG

最后的str1就是密文,利用str1在encode_three解出v9,利用v9在encode_two解出v10,然后就是由v10得到flag。

第三道和第二道加密的脚本如下:

#include
#include
int main()
{
int i; 
char A[54];
char a1[54]; 
int v5[54];
int v7[54]={69,109,66,109,80,53,80,109,110,55,81,99,80,85,52,103,76,89,75,118,53,81,99,77,109,
            66,51,80,87,72,99,80,53,89,107,80,113,51,61,99,84,54,81,99,107,107,80,99,107,111,82,71}; //EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG的ascll值 
for(i=0;i<54;i++)//凯撒密码解码,加上数字 
{
 
  for(v5[i]=1;v5[i]<=126;v5[i]++)
  {
    if ( v5[i]<= 64 || v5[i] > 90 )
    {
      if ( v5[i] <= 96 || v5[i] > 122 )
      {
        if ( v5[i] <= 47 || v5[i] > 57 )
        { if(v5[i] == v7[i]) break; }
        else
          if(v7[i] == ((v5[i] - 48 + 3)%10+48)) break;
      }
      else
      {
        if(v7[i] == (v5[i] - 97 + 3) % 26 + 97) break;
      }
    }
    else
    {
      if(v7[i] == (v5[i] - 65 + 3) % 26 + 65)  break;
    }
  }
}
for(i=0;i<=53;i++)
{
	printf("%c",v5[i]); A[i]=v5[i];
}
printf("n");
strncpy(a1+26,A,13);
strncpy(a1,A+13,13);
strncpy(a1+39,A+26,13);
strncpy(a1+13,A+39,13);
for(i=0;i<=53;i++)
{
	printf("%c",a1[i]); 
}
} 

得到:

 base64解码得到:

flag{672cc4778a38e80cb362987341133ea2} 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5690906.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存