Bugku 283 11月11日是个好日子 题解

Crypto 题。

作为一个萌新做过的最难的密码(

下载文件打开得到这个。

不妨先观察一下 hint,显然 hint 是某种从来没见过的编码。在百度搜索“不会吧就这”等词语可以发现 B 站的一个视频,他告诉我们存在一种阴阳怪气编码

于是我把他的链接偷了下来:Here

打开后把我们的一大堆 hint 粘贴进去得到:

他告诉我们要把 Cipher 拿去解一小会儿。

观察 Cipher 发现密码符合 base58 形式所以我们拖去 base58 解密得到:

然后编写程序给他加上若干 % 得到字符串 %4C%4A%4C%54%49%34%33%42%4B%52%4C%47%57%54%32%49%4F%51%59%57%45%33%54%45%4D%5A%4D%56%4F%55%4C%59%4C%41%5A%46%53%36%4B%59%47%4E%42%47%34%57%44%32%4E%42%58%46%55%56%32%47%48%45%3D%3D%3D%3D%3D%3D,拖去 url 解密(别人的这一步貌似都是 base16。):

等号很多,不是 base64,所以是 base32:

接下来经过若干尝试,我们发现 base64 可以解码这个东西,而且形式已经相当接近答案:

由于很接近答案的有两个大括号的形式,我们猜测这就是最后一步,开始观察 alp。

alp 里面有一个特色就是字母和数字都没有重复,但是这个 alp 缺失了四个字母 a,g,v,r,所以我们用这四个全排列替换 alp 中的 ? 再拿去解密。

仿射密码

仿射密码,是一种位移密码,工作原理百度百科写了,方程照着抄到代码里就行。

编写代码如下:

#include<bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define fir first
#define sec second
#define lowbit(i) (i&(-i))
using namespace std;
const int N=5e5+5;
const int inf=1e18;
struct edge{int to,nxt,l;};
inline int read(){
    char op=getchar();
    int w=0,s=1;
    while(op<'0'||op>'9'){
        if(op=='-') s=-1;
        op=getchar();
    }
    while(op>='0'&&op<='9'){
        w=(w<<1)+(w<<3)+op-'0';
        op=getchar();
    }
    return w*s;
}
map<char,bool> used;
char alp[N],pas[N],Try[N],ans[N];
//alp : slbn7q6u0w2pf3m9tzjx8o51yke????dhc4i
//pas : en,i5d8{unw_ad1_f2_pg_8gea}
//Input
/*
slbn7q6u0w2pf3m9tzjx8o51yke????dhc4i
en,i5d8{unw_ad1_f2_pg_8gea}
*/
void check(){
    int cnt=0,m=strlen(alp+1);
    map<char,int> f;
    map<int,char> invf;
    for(register int i=1;i<=m;i++){
        f[alp[i]]=cnt;
        invf[cnt]=alp[i];
        cnt++;
    }
    int n=strlen(pas+1);
    for(register int k=1;k<=35;k++){
        for(register int b=0;b<=35;b++){
            for(register int i=1;i<=n;i++){
                if((pas[i]>'z'||pas[i]<'a')&&(pas[i]>'9'||pas[i]<'0')){
                    ans[i]=pas[i];
                    continue;
                }
                char opt=((f[pas[i]]+b)*k+36)%36;
                ans[i]=invf[opt];
            }
            if(ans[4]=='f'&&ans[5]=='l'&&ans[6]=='a'&&ans[7]=='g'){
                printf("k=%lld b=%lld ???? = %c%c%c%c : %s",k,b,Try[1],Try[2],Try[3],Try[4],ans+1);
                exit(0);
            }
        }
    }
}
void dfs(int x){
    if(x==5){
        for(register int i=28;i<=31;i++) alp[i]=Try[i-27];
        check();
        return;
    }
    if(used['a']==false){
        Try[x]='a';
        used['a']=true;
        dfs(x+1);
        Try[x]=0;
        used['a']=false;
    }
    if(used['g']==false){
        Try[x]='g';
        used['g']=true;
        dfs(x+1);
        Try[x]=0;
        used['g']=false;
    }
    if(used['v']==false){
        Try[x]='v';
        used['v']=true;
        dfs(x+1);
        Try[x]=0;
        used['v']=false;
    }
    if(used['r']==false){
        Try[x]='r';
        used['r']=true;
        dfs(x+1);
        Try[x]=0;
        used['r']=false;
    }
}
signed main(){
    scanf("%s",alp+1);
    scanf("%s",pas+1);
    dfs(1);
}

结果:

提交结果 flag{the_day_13_s0_g0od} 正确,终。

总结学到了一种新密码。挺浪费时间的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值