今天做这道题做的很爽,于是想拿出来写一写我的思路
首先用IDA打开,查看main函数
首先就是程序会判断你是否会进入这个游戏,容易看出Decry()函数是重要的,点击进入
各种初始变量的申明先留着,直接查看后面的部分
图中的join函数,点进去发现其实就是把两个字符串合成一个
所以上面做的事情是合成了初始的key和flag(!!注意这里是小端存储!!)
接着看下一part
这里也很容易理解,其实就是把key字符串全部从大写变为小写
到这里
text=killshadow
key=adsfkndcls
到下面就是叫你输入flag了
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar();
if ( v1 == 10 )
break;
if ( v1 == 32 )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )
{
if ( v1 > 64 && v1 <= 90 )
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
}
else
{
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;
一整个while循环,先把你输入的字符进行一系列处理后 ,再弄到str2上,最后如果str2与text相同,则输入正确
再观察核心代码
发现除了ascii码为32的字符外,无论你输入什么字符,都会进行
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
这个操作
但这是取余操作,没办法有效逆推,只能爆破
我这里假设输入的全部都是大写字母,如果有某个大写字母符合上述条件,则生成flag的一个字符
下面附上脚本~~
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int main(){
string key = "adsfkndcls";
string text = "killshadow";
char res[10];
for(int i=0;i<10;i++){
for(int j=65;j<=90;j++){
if(text[i]==(j-39-key[i]+97)%26+97){
res[i]=j;
break;
}
}
}
cout<<res<<endl;
system("pause");
return 0;
}
最后得到flag{KLDQCUDFZO}