BUUCTF 逆向工程(reverse)之SimpleRev

用IDA打开,进入到Decry函数

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

  v12 = __readfsqword(0x28u);
  *(_QWORD *)src = 'SLCDN';
  v7 = 0LL;
  v8 = 0;
  v9 = 'wodah';
  v10 = 0LL;
  v11 = 0;
  text = (char *)join(key3, &v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:", src);
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == '\n' )
      break;
    if ( v1 == ' ' )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
          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) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v12;
}

首先是给src和v9赋值,如果你看到的是16进制的整数的话,可以用IDA自带转化转成字符串

src = 'SLCDN';
v9 = 'wodah';

在这里插入图片描述

双击key1和key3的时候,可以看到它们对应的值

key1 = 'ADSFK'
key3 = 'kills'

在这里插入图片描述
在这里插入图片描述
然后再将上面的四个字符串组合

text = (char *)join(key3, &v9);		// text = key3 + v9
strcpy(key, key1);
strcat(key, src);
// key = key1 + src

然后再将key里的大写字母转换成小写字母

for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }

接下来再看求解主要flag的过程

while (1)
	{
		v1 = getchar();
		if (v1 == '\n')
			break;
		if (v1 == ' ')
		{
			++v2;
		}
		else
		{
			if (v1 <= 96 || v1 > 122)
			{
				if (v1 > 64 && v1 <= 90)
					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))
		puts("Congratulation!\n");

上面的代码的大致意思是让你输入一行字符串,遇到回车表示输入结束

if (v1 == '\n')
	break;

输入的字符串是有空格的,即一个字符一个字符的输入。比如输入的字符串是:A B C D E,而不是:ABCDE

if (v1 == ' ')
{
	++v2;
}

而这一步是出题人故意写复杂的,大致的意思是给每个字母一定的偏移量,并且这个偏移量还和它们的位置有关

if (v1 <= 96 || v1 > 122)
{
	if (v1 > 64 && v1 <= 90)
	str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
else
{
	str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}

emmmmmmm老实说,这里我也不知道给怎么解释。就写了一下上面的伪代码

int len = key的长度或者是text的长度
for (int i = 0; i < len; i++) {
	if 输入的字符是字母的话:
		str2[i] = (v1 - 39 - key[i] + 97) % 26 + 97;
}

最后再将str2字符串的结果和text比较,如果相等就表示可以获取flag

if ( !strcmp(text, str2) )
    puts("Congratulation!\n");

所以求解flag的Python3代码为:

src = 'NDCLS'
v9 = 'hadow'
key1 = 'ADSFK'
key3 = 'kills'

text1 = key3 + v9       # 这里的text1相当于 text = key3 + v9
text2 = key1 + src      # 这里的text2相当于 key = key1 + src
text2 = text2.lower()   # 需要把大学字母变为小写字母

flag = ""
for i in range(0,len(text1)):
    for x in range(0,128):      # 这里用暴力求解
        if chr(x).isalpha():    # 这里要加上判断x是否是字符串,不然会求解出乱七八糟的答案。我就在这里卡了一段时间。。。
            temp = (x - 39 - ord(text2[i]) + 97) % 26 + 97
            # print(text1[i]+"   "+chr(temp)+"   "+chr(x))
            if text1[i] == chr(temp):   
                flag = flag + chr(x)
                break

print("flag{"+flag+"}")

最后得到的flag为:flag{KLDQCUDFZO}