也没个后缀,强行加个exe后缀还运行不了
废话不多说,64位IDA走起
只有输入d或D才能进入Decry()函数,否则退出,现在进入函数
大概意思是先把key1和scr复制到key中然后对key进行一番操作,然后输入flag到str2中,对str2进行一番操作后跟text进行比较,比较正确则输出congratulation
因此需要关注的几个点是key1,scr,key3,v9(进入join函数可以看到text由key3和v9链接而成)并且这四个量已经给出(选中后按R转成字符串即可),但事实上正确的scr和v9是转换之后字符串的倒序(与bugku中的Easy_RE完全一致),根据之前看的汇编知识大概推测这和编译器从内存中读取数据的顺序有关(一个是小端存储一个是大端读取https://baijiahao.baidu.com/s?id=1609459208102387514),那就暂且认为凡是需要手动转成字符串的字符串都按照倒序处理(最起码现在碰到的都是,晕)
那么,上脚本
char key[] = "ADSFKNDCLS";
char text[] = "killshadow";
char a;
char final[10];
int i, v5;
int v3 = 0, v2 = 0;
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;
}
cout << key << endl;
其实就是把大写字母变成小写,对key处理完后继续下一步
撇去v1等对结果无影响的部分,可以看到对str2操作完成后跟text进行比较,操作过程已知且text已知,因此根据核心操作过程对text进行逆操作即可
值得注意的是取模操作,如a/b=c······d,进行你操作时c(我们可称之为放大倍数)是未知的,因此需要使用循环对放大倍数从0进行尝试,直到有符合要求的结果,但经过实践发现对于text全部字符而言这个c并不是一致的,比如第一个字符的c为0,第二个字符的c为1,第三个为3,都有可能,但从比较过程来看,text全是字母,因此可用条件语句筛选出符合条件的情况,即他的ASCII码>=65&&<=90或>=97&&<=122
使用两层循环,第一层表示放大倍数,第二层表示对text的是个字符依次进行操作,上脚本
for (i = 0;i < 5;i++)//放大取模倍数
{
v3 = 10;
for (v2 = 0;v2 < 10;v2++)//十个字符
{
a = text[v2] - 97 + i * 26 - 97 + key[v3++ % v5] + 39;
if (a >= 65 && a <= 90)
final[v2] = a;
}
}
cout << final;
脚本中只判断大写字母是因为在源代码中末尾有+97,即加上后全为小写字母,那么反操作后全为大写字母,筛去不必要结果
第四行就是flag啦(这乱码是咋回事?)