BUUCTF刷题

BUUCTF刷题

1.不一样的flag

IDA32打开文件,并找到main函数,F5进入伪代码界面,从头分析

void main()
{
  char v0; // [sp+17h] [bp-35h]@1
  int v1; // [sp+30h] [bp-1Ch]@1
  int v2; // [sp+34h] [bp-18h]@1
  signed int v3; // [sp+38h] [bp-14h]@2
  signed int i; // [sp+3Ch] [bp-10h]@14
  int v5; // [sp+40h] [bp-Ch]@20

  __main();
  v1 = 0;
  v2 = 0;
  qmemcpy(&v0, _data_start__, 0x19u);           // _data_start__为*11110100001010000101111#
  while ( 1 )
  {
    puts("you can choose one action to execute");//开始输入flag
    puts("1 up");
    puts("2 down");
    puts("3 left");
    printf("4 right\n:");
    scanf("%d", &v3);
    if ( v3 == 2 )
    {
      ++v1;
    }
    else if ( v3 > 2 )
    {
      if ( v3 == 3 )
      {
        --v2;
      }
      else
      {
        if ( v3 != 4 )
LABEL_13:
          exit(1);
        ++v2;
      }
    }
    else
    {
      if ( v3 != 1 )
        goto LABEL_13;
      --v1;
    }
      /这部分都是一些指令,上下左右然后对V1,v2进行相关的加减修改
      //输入1--- v1-1 up
      //输入2--- v1+1 down
      //输入3--- v2-1 left
      //输入4--- v2+1 right
      
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(&v1 + i) < 0 || *(&v1 + i) > 4 )
        exit(1);
    }
    if ( *((_BYTE *)&v5 + 5 * v1 + v2 - 41) == '1' )// 如果最后结果是字符‘1’就退出
      exit(1);
    if ( *((_BYTE *)&v5 + 5 * v1 + v2 - 41) == '#' )// 如果最后是‘#’则输出puts
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

里出来了,但是感觉缺点啥,看看大佬的wp,发现这是一道迷宫题,最后的flag就是你输入的”上下左右“,只要根据地图走就行

地图就是一开始的_data_start__。将其3个为一组,得到地图:

*1111
01000
01010
00010
1111#
    '*'就是起点,'#'就是出口,只能走0,遇到'1'程序就停止,遇到'#'程序输出一句话
   		// puts("\nok, the order you enter is the flag!");
    当”走出迷宫“后,输入的字符就包括222441144222

最后flag就是flag{222441144222}

2.simpleRev

常规操作一波,查壳,看环境,IDA打开 F5伪代码分析
BUUCTF刷题

分析,可以看出主要函数就是Dercy();跟进分析----》

__int64 Decry()
{
  char v1; // [sp+Fh] [bp-51h]@19
  int v2; // [sp+10h] [bp-50h]@1
  signed int v3; // [sp+14h] [bp-4Ch]@1
  signed int i; // [sp+18h] [bp-48h]@1
  signed int v5; // [sp+1Ch] [bp-44h]@1
  char src[8]; // [sp+20h] [bp-40h]@1
  __int64 v7; // [sp+28h] [bp-38h]@1
  int v8; // [sp+30h] [bp-30h]@1
  __int64 v9; // [sp+40h] [bp-20h]@1
  __int64 v10; // [sp+48h] [bp-18h]@1
  int v11; // [sp+50h] [bp-10h]@1
  __int64 v12; // [sp+58h] [bp-8h]@1

  v12 = *MK_FP(__FS__, 40LL);
  *(_QWORD *)src = 'SLCDN';		//注意小端存储,真正的src=NDCLS
  v7 = 0LL;
  v8 = 0;
  v9 = 'wodah';					//这也是小端存储,V9=hadow
  v10 = 0LL;
  v11 = 0;
  text = join(key3, (const char *)&v9);         // join--将两个字符串接起来,key3="kills";v9="hadow"
  strcpy(key, key1);                            // key=key1;key1为”ADSFK“
  strcat(key, src);                             // 将key和src字符串连接起来,key就为ADSFKNDCLS
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > '@' && key[v3 % v5] <= 'Z' )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }                                             // 对key进行加密操作,即大小写转化
  printf("Please input your flag:", src);
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == '\n' )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )              // v1在A~Z之间
          str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )	//最后经过处理得到的str2和text文本一样即通过,所以text就是最终加密文本,脚本需对text处理得出flag
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return *MK_FP(__FS__, 40LL) ^ v12;
}
整理:
    加密后flag---text = killshadows
    加密中使用的字符串(经大小写转换)---key = adsfkndcls
    输入的字符---v1
    最终得到的处理过的flag---Str2

脚本如下:

#include<stdio.h>
#include<windows.h>
#include<string.h>
/*
 加密后flag---text = killshadows
    加密中使用的字符串(经大小写转换)---key = adsfkndcls
    输入的字符---v1
    最终得到的处理过的flag---Str2
*/
int main(){
    char text[]={"killshadows"};
    char key[]="adsfkndcls";
    char str[50];
    int i;
    char a;
    int v3=strlen(text);
    int v2;
    int v5=strlen(key);
    int j;
    for(i=0;i<v3-1;i++){
        //这里用来试26取余的乘数
        for(j=0;;j++){
            str[i] = text[i] - 97 + 26*j + 39 -97 + key[i];
            if(str[i]>64 && str[i]<91)
                break;
        }
    }
    printf("%s",str);
    system("pause");
    return 0;
}
flag{KLDQCUDFZO}!!!!
上一篇:对多频外差的改进-校正伽马误差


下一篇:使用 git 提交报错:error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity