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伪代码分析
分析,可以看出主要函数就是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}!!!!