
做一题,这题编码逻辑有坑,注意!
32位,放ida,看定位到主要代码
看看这段代码,输入ACTF{只是提示我们接下来输入的就是flag
后面把我们的输入进行加密,加密之后和硬编码字符串进行对比,正确就输出You are correct!
所以只需要把硬编码的字符串解密就好了
硬编码字符串:Qsw3sj_lz4_Ujw@l\0
解密的时候我开始是直接根原文逆着来:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string key = "Qsw3sj_lz4_Ujw@l\0";
for (int i = 0; i <= 15; ++i)
{
if (key[i] > '@' && key[i] <= 'Z')
{
key[i] = ((key[i] - 'A') + 51) % 26 + 'A';
}
else if (key[i] > '`' && key[i] <= 'z')
{
key[i] = ((key[i] - 'a') + 79) % 26 + 'a';
}
}
cout << key;
return 0;
}结果是:Ptx3tk_ma4_Tkx@m
原本的加密逻辑是:
如果是大写字母,就ascii码-51再对26取余(假设得到x),再加上65就得到对应的新的大写字母。小写同理
我错误的逻辑是:
直接用密文的大写字母,先减去65得到对应加密得到的x,再加51,再取余
这里就和加密不一致了
应该是先加上一个26的倍数,在最终加51.
比如'A'加密:65(A)- 51 =14; 14 % 26 = 14; 14 + 65 = 'O';
我的解密:'O' - 65 = 14; 14 + 51 = 65; 65 % 26 = 13; 13 + 65 = 'N';
正确的解密:'O' -65 = 14; 14 + 0 * 26 = 14; 14 + 51 = 65(A);
这里的026就是对应的26的倍数,如果想逆着解出来就得研究什么范围应该加026,什么范围加1*26,这里我不多赘述
其实可以直接爆破,知道这是大写的26个字母,直接每个进行加密,能得到密文的就是答案字符
比如:密文是'Q', 我从'A'开始试,进行加密,发现'C'能经过一样的加密得到'Q',那'C'就是明文字符。
exp我就不写了。
还有,这题看代码逻辑,v9是'{',v14是'}',中间只有四个输入,但是由于v10,v11,v12,v13都是int类型,
所以占四个字节,所以一共可以输入16个字符