题目:BUUCTF SimpleRev
查壳,没壳,64位
ida打开一通分析
main():
while ( 1 )
{
while ( 1 )
{
printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ");
v4 = getchar();
if ( v4 != 100 && v4 != 68 )// d/D
break;
Decry();
}
if ( v4 == 113 || v4 == 81 )// q/Q
Exit("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv);
puts("Input fault format!");
v3 = getchar();
putchar(v3);
}
很好懂,主要看Decry
Decry():
v11 = __readfsqword(0x28u);
*(_QWORD *)src = 'SLCDN';
v7 = 0LL;
v8 = 0;
v9[0] = 'wodah';
v9[1] = '\0';
v10 = 0;
text = join(key3, (const char *)v9); // text = key3 + v9
strcpy(key, key1);
strcat(key, src); // key = key1 + src
input_not_return_cnt = 0;
key_p = 0;
getchar();
key_len = strlen(key);
for ( i = 0; i < key_len; ++i )
{
if ( key[key_p % key_len] > 64 && key[key_p % key_len] <= 90 )// key 大写字母->小写
key[i] = key[key_p % key_len] + 32;
++key_p;
}
printf("Please input your flag:");
while ( 1 ) // 此时key_p = key_len
{
input = getchar();
if ( input == 10 ) // 换行
break;
if ( input == 32 ) // 空格
{
++input_not_return_cnt;
}
else
{
if ( input <= 96 || input > 122 )
{
if ( input > 64 && input <= 90 ) // 大写字母
{
str2[input_not_return_cnt] = (input - 39 - key[key_p % key_len] + 97) % 26 + 97;
++key_p;
}
}
else // 小写字母
{
str2[input_not_return_cnt] = (input - 39 - key[key_p % key_len] + 97) % 26 + 97;
++key_p;
}
if ( !(key_p % key_len) )
putchar(32); // v3是key长度的倍数时输出空格
++input_not_return_cnt;
}
key1和key3双击找到
v9和src显示的是整形,右键选择char得到字符串,需要翻转一下,可能是大端小端的问题,卡了我很久()
可以看到加密算法与位置有关,不好分析,但可能的选择很少,只有大小写字母,于是枚举
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
string text = "killshadow";
string key = "adsfkndcls";
char str2[104];
char input;
int input_not_return_cnt = 0;
int key_len = key.size();
int key_p = key_len;
void trans()
{
while ( 1 ) // 此时key_p = key_len
{
input = getchar();
if ( input == 10 ) // 换行
break;
if ( input == 32 ) // 空格
{
++input_not_return_cnt;
}
else
{
if ( input <= 96 || input > 122 )
{
if ( input > 64 && input <= 90 ) // 大写字母
{
str2[input_not_return_cnt] = (input - 39 - key[key_p % key_len] + 97) % 26 + 97;
++key_p;
}
}
else // 小写字母
{
str2[input_not_return_cnt] = (input - 39 - key[key_p % key_len] + 97) % 26 + 97;
++key_p;
}
if ( !(key_p % key_len) )
putchar(32); // v3是key长度的倍数时输出空格
++input_not_return_cnt;
}
}
cout << "#"<< str2 << "#" << endl;
}
int main()
{
for (int i = 0; i < 10; i++)
{
// for (int j = 0; j < 27; j++)
// {
// char put = 'a' + j;
// if (text[i] == (put - 39 - key[i % key_len] + 97) % 26 + 97)
// {
// cout << put;
// break;
// }
// }
for (int j = 0; j < 27; j++)
{
char put = 'A' + j;
if (text[i] == (put - 39 - key[i % key_len] + 97) % 26 + 97)
{
cout << put;
break;
}
}
}
//trans();
return 0;
}
虽然输入允许空格,但加空格会变复杂,我选择先不加看看能不能出(
写了大小写两块,发现都有合法的,不知道是不是我哪里看漏了
efxkwoxzti
KLDQCUDFZO
但是只有大写是正确的flag