2022DASCTF X SU 三月春季挑战赛 easyre

2022/4/30 6:12:52

本文主要是介绍2022DASCTF X SU 三月春季挑战赛 easyre,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

2022DASCTF X SU 三月春季挑战赛 easyre

前奏

查壳

image-20220430011715508

查壳,asp壳,esp定律脱之,修复可以看我的上一篇文章

main函数

main函数的反汇编代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned __int8 Dest[50]; // [esp+1Ch] [ebp-74h] BYREF
  char Str[50]; // [esp+4Eh] [ebp-42h] BYREF
  __time32_t Time; // [esp+80h] [ebp-10h] BYREF
  int v7; // [esp+84h] [ebp-Ch]
  int v8; // [esp+88h] [ebp-8h]
  struct tm *v9; // [esp+8Ch] [ebp-4h]

  sub_40DCF0();
  time(&Time);
  v9 = gmtime(&Time);
  sub_47C7D0((int)&dword_487F00, Str);
  if ( strlen(Str) != 42 )
  {
    sub_47BAB0((int)&dword_488140, aWrong);
    exit(0);
  }
  if ( Str[0] != 'D' || Str[1] != 'A' || Str[2] != 'S' || Str[3] != 'C' || Str[4] != 'T' || Str[5] != 'F' )
  {
    sub_47BAB0((int)&dword_488140, aWrong);
    exit(0);
  }
  mbscpy(Dest, (const unsigned __int8 *)Str);
  v8 = v9->tm_year + 1900;
  v7 = 0;
  sub_4019BE(Str);
  sub_401771((char *)Dest);
  system(Command);
  return 0;
}

Str是我们的输入

sub_47BAB0是printf

sub_47C7D0是scanf

修复后的代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned __int8 Dest[50]; // [esp+1Ch] [ebp-74h] BYREF
  char Str[50]; // [esp+4Eh] [ebp-42h] BYREF
  __time32_t Time; // [esp+80h] [ebp-10h] BYREF
  int v7; // [esp+84h] [ebp-Ch]
  int v8; // [esp+88h] [ebp-8h]
  struct tm *v9; // [esp+8Ch] [ebp-4h]

  sub_40DCF0();
  time(&Time);
  v9 = gmtime(&Time);
  scanf(&dword_487F00, Str);
  if ( strlen(Str) != 42 )
  {
    printf_0(&dword_488140, aWrong);
    exit(0);
  }
  if ( Str[0] != 'D' || Str[1] != 'A' || Str[2] != 'S' || Str[3] != 'C' || Str[4] != 'T' || Str[5] != 'F' )
  {
    printf_0(&dword_488140, aWrong);
    exit(0);
  }
  mbscpy(Dest, Str);
  v8 = v9->tm_year + 1900;
  v7 = 0;
  sub_4019BE(Str);
  sub_401771(Dest);
  system(Command);
  return 0;
}

可以分析得出,我们输入的内容需要首先满足Str[0] != 'D' || Str[1] != 'A' || Str[2] != 'S' || Str[3] != 'C' || Str[4] != 'T' || Str[5] != 'F' = 42这两个条件

所以可以我们可以构造如下的满足条件的输入

DASCTFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

image-20220430012638467

然后根据代码,程序会进入下面两个函数

image-20220430012811894

  sub_4019BE(Str);
  sub_401771(Dest);

sub_4019BE(Str)

代码

size_t __cdecl sub_4019BE(char *Str)
{
  size_t result; // eax
  char v2[84]; // [esp+1Ch] [ebp-7Ch] BYREF
  char *v3; // [esp+70h] [ebp-28h]
  size_t Size; // [esp+74h] [ebp-24h]
  int v5; // [esp+78h] [ebp-20h]
  int v6; // [esp+7Ch] [ebp-1Ch]
  int v7; // [esp+84h] [ebp-14h]
  size_t v8; // [esp+88h] [ebp-10h]
  int i; // [esp+8Ch] [ebp-Ch]

  strcpy(&v2[59], "26St9k3bNYWAadAhJJjDCRVx");
  v5 = 0;
  v6 = 0;
  Size = 138 * strlen(Str) / 0x64 + 1;
  strcpy(v2, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
  v3 = malloc(Size);
  v8 = 0;
  memset(v3, 0, Size);
  while ( v8 < strlen(Str) )
  {
    v7 = Str[v8];
    for ( i = Size - 1; ; --i )
    {
      v7 += v3[i] << 8;
      v3[i] = v7 % 58;
      v7 /= 58;
      if ( !v7 )
        break;
    }
    for ( i = 0; !v3[i]; ++i )
      ;
    ++v8;
  }
  for ( i = 0; !v3[i]; ++i )
    ;
  while ( 1 )
  {
    result = Size - 1;
    if ( (Size - 1) < i )
      break;
    Str[i] = v2[v3[i]];
    ++i;
  }
  return result;
}

根据strcpy(v2, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");这一段,可以发现是base58

strcpy(&v2[59], "26St9k3bNYWAadAhJJjDCRVx");中的v2进行解码,可以发现是个fake flag

image-20220430013218651

那就不管他,看sub_401771(Dest);

sub_401771(Dest)

代码

int __cdecl sub_401771(char *Str)
{
  int v2[50]; // [esp+1Ch] [ebp-DCh] BYREF
  int v3; // [esp+E4h] [ebp-14h]
  int j; // [esp+E8h] [ebp-10h]
  int i; // [esp+ECh] [ebp-Ch]

  v3 = strlen(Str);
  sub_401500();
  sub_40152B();
  sub_401593();
  sub_401619(Str, v3);
  for ( i = 0; i < v3; ++i )
    byte_492A60[i] = (LOBYTE(dword_492940[i]) ^ Str[i]) + 71;
  memset(v2, 0, sizeof(v2));
  v2[0] = -61;
  v2[1] = -128;
  v2[2] = -43;
  v2[3] = -14;
  v2[4] = -101;
  v2[5] = 48;
  v2[6] = 11;
  v2[7] = -76;
  v2[8] = 85;
  v2[9] = -34;
  v2[10] = 34;
  v2[11] = -125;
  v2[12] = 47;
  v2[13] = -105;
  v2[14] = -72;
  v2[15] = 32;
  v2[16] = 29;
  v2[17] = 116;
  v2[18] = -47;
  v2[19] = 1;
  v2[20] = 115;
  v2[21] = 26;
  v2[22] = -78;
  v2[23] = -56;
  v2[24] = -59;
  v2[25] = 116;
  v2[26] = -64;
  v2[27] = 91;
  v2[28] = -9;
  v2[29] = 15;
  v2[30] = -45;
  v2[31] = 1;
  v2[32] = 85;
  v2[33] = -78;
  v2[34] = -92;
  v2[35] = -82;
  v2[36] = 123;
  v2[37] = -84;
  v2[38] = 92;
  v2[39] = 86;
  v2[40] = -68;
  v2[41] = 35;
  for ( j = 0; j <= 41; ++j )
  {
    if ( v2[j] != byte_492A60[j] )
      exit(0);
  }
  return printf_0(&dword_488140, aRight);
}

根据最后的

if ( v2[j] != byte_492A60[j] )
      exit(0);

这个代码,倒推需要我们input的flag

可以知道需要我们输入的flag的验证逻辑是

flag = (byte_492A60[j]-71)^LOBYTE(dword_492940[i])

根据byte_492A60[i] = (LOBYTE(dword_492940[i]) ^ Str[i]) + 71;这段代码,可以知道我们需要LOBYTE(dword_492940[i])的数值

这里我直接使用了动态分析(静态分析太麻烦)

动态调试

image-20220430013855322

image-20220430013918574

先输入我们上一把得到的过第一层校验的字符串DASCTFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

程序此时已经断在了我们需要的地方

image-20220430014052604

此时我们就可以去拿dword_492940的值了

image-20220430014223610

以BYTE的格式(因为前文有提示说是BYTE)

unsigned char dword_492940[171] = {
    0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 
    0x6B, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 
    0x85, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 
    0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 
    0x1D, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0xD2, 0xFF, 0xFF, 0xFF, 
    0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 
    0xC6, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 
    0x7B, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 
    0x10, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

因为LOBYTE(dword_492940[i])的要求,所以我们需要低字节

image-20220430014820181

#include<stdio.h>
int main(){
unsigned char dword_492940[171] = {
    0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 
    0x6B, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 
    0x85, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 
    0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 
    0x1D, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0xD2, 0xFF, 0xFF, 0xFF, 
    0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 
    0xC6, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 
    0x7B, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 
    0x10, 0x00, 0x00, 0x00, 0xA1
};
	for(int i = 0;i < 171;i=i+4){
		printf("%d,",dword_492940[i]);
	}
}

输出

56,120,221,232,0,175,191,58,107,251,184,12,133,53,92,173,230,0,224,138,29,189,70,210,43,0,21,36,198,173,161,201,123,18,40,0,5,0,114,62,16,161,0

我们现在已知byte_492A60LOBYTE(dword_492940[])

再加上flag的逻辑是

flag = (byte_492A60[i]-71)^LOBYTE(dword_492940[i])

接下来就可以写逆向脚本了

#include<stdio.h>
int main(){
int v1[43] = {56,120,221,232,0,175,191,58,107,251,184,12,133,53,92,173,230,0,224,138,29,189,70,210,43,0,21,36,198,173,161,201,123,18,40,0,5,0,114,62,16,161,43,0};
int v2[41];
	v2[0] = -61;
  v2[1] = -128;
  v2[2] = -43;
  v2[3] = -14;
  v2[4] = -101;
  v2[5] = 48;
  v2[6] = 11;
  v2[7] = -76;
  v2[8] = 85;
  v2[9] = -34;
  v2[10] = 34;
  v2[11] = -125;
  v2[12] = 47;
  v2[13] = -105;
  v2[14] = -72;
  v2[15] = 32;
  v2[16] = 29;
  v2[17] = 116;
  v2[18] = -47;
  v2[19] = 1;
  v2[20] = 115;
  v2[21] = 26;
  v2[22] = -78;
  v2[23] = -56;
  v2[24] = -59;
  v2[25] = 116;
  v2[26] = -64;
  v2[27] = 91;
  v2[28] = -9;
  v2[29] = 15;
  v2[30] = -45;
  v2[31] = 1;
  v2[32] = 85;
  v2[33] = -78;
  v2[34] = -92;
  v2[35] = -82;
  v2[36] = 123;
  v2[37] = -84;
  v2[38] = 92;
  v2[39] = 86;
  v2[40] = -68;
  v2[41] = 35;
char flag[42];
	for (int i =0;i <43 ;i++)
	{
		flag[i] = (v2[i]-71)^v1[i];
		printf("%c",flag[i]);
	}
}

image-20220430015909968

DASCTF{Welc0me-t0-j01n-SU-l0ve-suyug1eg1e}


这篇关于2022DASCTF X SU 三月春季挑战赛 easyre的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程