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

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

在这里插入图片描述

先看文件信息,没有加壳

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

读入字符串

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;
}

主函数

在这里插入图片描述

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可以去掉

在这里插入图片描述

转到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 <stdlib.h>
#include <stdio.h>
#include <string.h>
 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;
}

运行结果

在这里插入图片描述

得到flag: flag{757515121f3d478}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ofo300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值