查壳64位,反汇编查看,吧两个判断语句的数值按R转换成字符,可以发现主要的函数是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] BYREF
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
int v10; // [rsp+50h] [rbp-10h]
unsigned __int64 v11; // [rsp+58h] [rbp-8h]
v11 = __readfsqword(0x28u);
*(_QWORD *)src = 'SLCDN';
// 大小端存储的问题,应该认为是NDCLS
v7 = 0LL;
v8 = 0;
v9[0] = 'wodah'; // hadow
v9[1] = 0LL;
v10 = 0;
text = join(key3, (const char *)v9);
// text保存了key3和v9的值,即killshadow
strcpy(key, key1);
strcat(key, src);
// key保存了key1和src的值,即ADSFKNDCLS
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key); // v5=10
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
// 这个循环是把key数组中的小写字母转换为大写字母,循环后v3=10
}
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar(); // v1用于读取输入的flag的每一位
if ( v1 == '\n' ) // 换行和空格时执行的操作
break;
if ( v1 == ' ' ) // 跳过空格,对字母处理
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 'z' ) // 对小于a或大于z的字符处理
{
if ( v1 > 64 && v1 <= 'Z' )
// 如果是A-Z,则经过下列操作转换成小写字母
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
// 97-39=58,所以可以化简为(v1-key[v3%v5]+58)%26+97
}
}
else
// 如果是a-z之间的字母,经下列操作转换成小写字母
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v11;
}
输入的text保存了最后用于比较的字符串,所以str2数组的值应该与text相同,然后输入的flag用v1读取
所以:
#include <stdio.h>
int main()
{
char text[11]="killshadow";
char key[11]="adsfkndcls";
int v3=10,v5=10;
for(int i=0;i<10;i++)
{
for(int j=65;j<123;j++)//A到z
{
if(!((j>='a'&&j<='z')||(j>='A'&&j<='Z')))//判断是否为字母
continue;
if(text[i]==(j-key[v3%v5]+58)%26+97)//text保存的是加密后的flag
{
putchar(j);//依次输出j得到flag
v3++;
break;
}
}
}
return 0;
}
得到flag{KLDQCUDFZO}