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);
}
}
}
}