ScreenShot_2026-04-01_172540_855.png
做一题,这题编码逻辑有坑,注意!
ScreenShot_2026-04-02_222332_183.png
32位,放ida,看定位到主要代码
ScreenShot_2026-04-02_222421_471.png

看看这段代码,输入ACTF{只是提示我们接下来输入的就是flag
后面把我们的输入进行加密,加密之后和硬编码字符串进行对比,正确就输出You are correct!
所以只需要把硬编码的字符串解密就好了

ScreenShot_2026-04-02_223028_046.png
硬编码字符串: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个字符