BUUCTF Reverse/[网鼎杯 2020 青龙组]singal

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第1张图片

先看文件信息,没有加壳

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第2张图片

运行,又是字符串比较的题目

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第3张图片

IDA32位打开,打开string窗口,跟随跳转

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第4张图片

读入字符串

size_t __cdecl read(char *Str)
{
  size_t result; // eax

  printf("string:");
  scanf("%s", Str);
  result = strlen(Str);
  if ( result != 15 )
  {
    puts("WRONG!\n");
    exit(0);
  }
  return result;
}

主函数

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第5张图片

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4[117]; // [esp+18h] [ebp-1D4h] BYREF

  __main();
  qmemcpy(v4, &unk_403040, 0x1C8u);
  vm_operad(v4, 114);
  puts("good,The answer format is:flag {}");
  return 0;
}

重点就是== vm_operad==里面对字符串进行变换了

int __cdecl vm_operad(int *a1, int a2)
{
  int result; // eax
  char Str[200]; // [esp+13h] [ebp-E5h] BYREF
  char v4; // [esp+DBh] [ebp-1Dh]
  int v5; // [esp+DCh] [ebp-1Ch]
  int v6; // [esp+E0h] [ebp-18h]
  int v7; // [esp+E4h] [ebp-14h]
  int v8; // [esp+E8h] [ebp-10h]
  int v9; // [esp+ECh] [ebp-Ch]

  v9 = 0;
  v8 = 0;
  v7 = 0;
  v6 = 0;
  v5 = 0;
  while ( 1 )
  {
    result = v9;
    if ( v9 >= a2 )
      return result;
    switch ( a1[v9] )
    {
      case 1:
        Str[v6 + 100] = v4;
        ++v9;
        ++v6;
        ++v8;
        break;
      case 2:
        v4 = a1[v9 + 1] + Str[v8];
        v9 += 2;
        break;
      case 3:
        v4 = Str[v8] - LOBYTE(a1[v9 + 1]);
        v9 += 2;
        break;
      case 4:
        v4 = a1[v9 + 1] ^ Str[v8];
        v9 += 2;
        break;
      case 5:
        v4 = a1[v9 + 1] * Str[v8];
        v9 += 2;
        break;
      case 6:
        ++v9;
        break;
      case 7:
        if ( Str[v7 + 100] != a1[v9 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
        ++v7;
        v9 += 2;
        break;
      case 8:
        Str[v5] = v4;
        ++v9;
        ++v5;
        break;
      case 10:
        read(Str);
        ++v9;
        break;
      case 11:
        v4 = Str[v8] - 1;
        ++v9;
        break;
      case 12:
        v4 = Str[v8] + 1;
        ++v9;
        break;
      default:
        continue;
    }
  }
}

unk_40340里的值,这里0可以去掉

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第6张图片

转到hex窗口,复制出来批量替换一下,得到

0x0A,0x04,0x10,0x08, 0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08, 
0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B, 
0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B, 
0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08, 
0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 
0x41,0x08,0x0C,0x01, 0x07,0x22,0x07,0x3F, 0x07,0x34,0x07,0x32, 0x07,0x72,0x07,0x33, 
0x07,0x18,0x07,0xA7,0xFF,0xFF,0xFF, 0x07,0x31,0x07,0xF1,0xFF,0xFF,0xFF, 
0x07,0x28,0x07,0x84,0xFF,0xFF,0xFF, 0x07,0xC1,0xFF,0xFF,0xFF,0x07,0x1E, 0x07,0x7A 

看这个case7,以及这个case1,这个是将每个v4存储到v6+100的下标中,然后与a1[v9+1]进行比较,如果不同则退出,说明这里的a1[v9+1]存储的就是输入字符串变化后的值

 case 7:
        if ( Str[v7 + 100] != a1[v9 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
 case 1:
        Str[v6 + 100] = v4;
        ++v9;
        ++v6;
        ++v8;
        break;

而要当case1才会将变化后的值存储,说明每个1后面的一位数就是变换后的字符,得到

v[15] = {0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a};   //v4的值

然后直接暴力破解flag,改一些代码,写出脚本

#include 
#include 
#include 
 int v9 = 0;
  int v8 = 0;
 int v7 = 0;
 int v6 = 0;
 int v5 = 0;
 int v4 = 0;
 int last_v9 = 0,last_v8 = 0,last_v7 = 0,last_v6 = 0 ,last_v5 = 0,last_v4 = 0;

int  f(int a1[],int k,int v[])
{
    v4 = k;
    while(1)
    {
        switch ( a1[v9] )
       {
      case 1:
        if(v[v6] == v4)
        {
            printf("k = %d,v6 = %d\n",k,v6);
            ++v9;
            ++v6;
            ++v8;
            last_v9 = v9;
            last_v8 = v8;
            //last_v7 = v7;
            last_v6 = v6;
            //last_v5 = v5;
            return 1;
        }
        else
        {

            v9 = last_v9;           //找不到则返回上一个v9
            v8 = last_v8;
           // v7 = last_v7;
            v6 = last_v6;
           // v5 = last_v5;
           return 0;
        }

        break;
      case 2:

        v4 = a1[v9 + 1] + v4;
        v9 += 2;

        break;
      case 3:
        v4 = v4 - a1[v9 + 1];
        v9 += 2;

        break;
      case 4:
        v4 = a1[v9 + 1] ^ v4;
        v9 += 2;

        break;
      case 5:
        v4 = a1[v9 + 1] * v4;
        v9 += 2;

        break;
      case 6:
        ++v9;

        break;
      /*case 7:
        if ( Str[v7 + 100] != a1[v9 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
        ++v7;
        v9 += 2;
        break;
      /*case 8:               //这里把v4的值赋给了Str[v5],上面也有用到,所以上面的Str[v8]直接代换成v4就行
        Str[v5] = v4;
        ++v9;
        ++v5;
        break;*/
      /*case 10:            //可以不用读取
        read(Str);
        ++v9;
        break;*/
      case 11:
        v4 = v4 - 1;
        ++v9;

        break;
      case 12:
        v4 = v4 + 1;
        ++v9;

        break;
      default:
        v9++;
        break;
     }
  }
}
int main()
{
    int v[16] = {0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a};   //v4的值

   int a1[] = {0x04,0x10,0x08,0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08,
              0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B,
              0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B,
              0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08,
              0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02,
              0x41,0x08,0x0C,0x01}; //0x07后面的值都是变换后的flag,可以不用管
   int i,j,k = 0;
   /*int a1[] = {0x04,0x10,0x08, 0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08,
              0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B,
              0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B,
              0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08,
              0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02,
              0x41,0x08,0x0C,0x01, 0x07,0x22,0x07,0x3F, 0x07,0x34,0x07,0x32, 0x07,0x72,0x07,0x33,
              0x07,0x18,0x07,0xA7,0xFF,0xFF,0xFF, 0x07,0x31,0x07,0xF1,0xFF,0xFF,0xFF, 0x07,0x28,0x07,
              0x84,0xFF,0xFF,0xFF, 0x07,0xC1,0xFF,0xFF,0xFF,0x07,0x1E, 0x07,0x7A,0};*/


   int flag[15] = {0};

   for(i = 0 ; i < 15 ; i++)
   {
       for(k = 33 ; k <= 'z'; k ++)   //暴力破解flag
       {
           if(f(a1,k,v))
           {
               flag[i] = k;
               break;
           }
       }
   }
   printf("flag{");
   for(i = 0 ; i < 15 ; i++)
   {
       printf("%c",flag[i]);
   }
   printf("}\n");
   return 0;
}

运行结果

BUUCTF Reverse/[网鼎杯 2020 青龙组]singal_第7张图片

得到flag: flag{757515121f3d478}

你可能感兴趣的:(#,BUUCTF,Reverse)