BUUCTF-RE-[ACTF新生赛2020]rome

没想到我会被这种题目难到,这是为什么呢?我认为是因为我对凯撒移位的不够了解,以及对取模运算的认识不够,因此作此记录

程序的加密逻辑很简单,分别对输入的字符进行区分大小写的移位操作
而重点便在于这里,以下面的程序为例:

  new_char = (original_char - 51) % 26 + 65;

这是当字符为大写时要进行的移位条件,我们将新字符减去65可以得到新字符在字母中的映射顺序。这个时候考虑到取模运算的周期性
我们可以得到下列逻辑:

  (new_char - 65) + 26*k = original_char -51

至于k取多少则取决于其边界条件,由于我们希望大写字母偏移后还是大写字母,所以我们设定当(new_char-65)<97时,添加一个26
实际上取模运算就是这么简单,重点在于其周期性,只要判断好k的值,便可以成功逆向得到原字符,下面我们写出逆向脚本:

#include<stdio.h>

int main(){
    char key[17] = "Qsw3sj_lz4_Ujw@l";
    char flag[17];
    for(int i=0;i<17;i++){
        if(key[i]>='A'&&key[i]<='Z'){
            flag[i] = (key[i]-65+51);
            if(flag[i]<65) flag[i]+=26;
        }else if(key[i]>='a'&&key[i]<='z'){
            flag[i] = (key[i]-97+79);
            if(flag[i]<97) flag[i]+=26;
        }else{
            flag[i] = key[i];
        }
    }
    printf("%s",flag);
}

难道只是这样了嘛?我们还可以用更加暴力的手段:

#include <stdio.h>
 
int main()
{
    char v12[] = "Qsw3sj_lz4_Ujw@l";
 
    for (int i = 0;i < 17;i++)
    {
        for (int j = 32;j <= 126;j++)
        {
            int x = j;
            if(x > '@' && x <= 'Z')
            {
                x = (x - 51) % 26 + 65;
            }
            if(x > '`' && x <= 'z')
            {
                x = (x - 79) % 26 + 97;
            }
            if(x == v12[i])
            {
                printf("%c", j);
            }
        }
    }
}
posted @ 2025-02-21 21:35  Ylin07  阅读(28)  评论(0)    收藏  举报