XSCTF ctf_crypto 最后的谜题

下载附件得到一个py文件,打开后如下

可以看到脚本的主要内容就是对flag使用了encrypt函数进行加密

尝试解读一下脚本的内容,其中random.getrandbits(n) 的作用是生成小于2^n随机数

m1=flag[4:-1] 说明加密的密文是取了flag的第5位字符到倒数第2位

key.find( )的作用是查看字符是key中的第几位(从0开始),也就是返回字符的检索值,例如key.find(‘q’)=0

在第二个for循环里,根据k%2是否等于0,对tmp进行了乘a或加b的运算,由于不确定k的值,所以无法确认具体的运算过程。

这里我没有选择去假设或爆破a、b的值,可以发现,k在“for _ in range(len(m))”的循环之后,k的值会被初始化为kt,当k的初始值不变时,对tmp进行的运算过程也不变。

这里,记tmp0=key.find(m[0]),tmp1=key.find(m[1]) (m就是密文m1)

题目说明了flag是以“hsctf{”开头的(就是assert后面的语句),而m1是从flag的第5个字符开始取的,也就是m1的前2位是“f{”,即m[0]就是’f’, m[1]是’{’

所以tmp0=13,tmp1=62

同时明文的前2位是“Wh”,分别对应了key[27]和key[15],也就是说经过for _ in range(len(m))运算之后(为了区分初始状态,前面加个f):

ftmp0%len(key)=27,ftmp1%len(key)=15,这里已知len(key)=67

刚才说过,tmp到ftmp的运算过程是不变的,那么根据四则运算的法则,计算ftmp1-ftmp0的过程中,“+b”可以被约掉,“*a”可以被提取出来

也就是说ftmp1-ftmp0 =(tmp1-tmp0)*a^n = 49*a^n

又因为ftmp0%67=27,ftmp1%67=15,并且由于ftmp1>ftmp0,那么可以得到(ftmp1-ftmp0)%67 =15-27+67 = 55

即(49*a^n)%67=55,可以得到 (a^n)%67=23

有了这一个关系,就可以计算tmp2了

m[2]是’c’,对应key[21],即ftmp2%67=21,(ftmp2-ftmp1)%67=key.find(m[2])- key.find(m[1])=21-15=6

得到(tmp2-tmp1)*a^n%67=6,为了直观表示tmp2是怎么求解的,可以用67的倍数加上余数来代替取余

即(tmp2-62)*(67x+23)%67=6,等价于23*(tmp2-tmp1)%67=key.find(m[2])- key.find(m[1]),这里要判断一下正负,因为余数是正的,所以如果key.find(m[2])- key.find(m[1])<0,就加上67

得到这一个关系就是解密脚本的核心了,可以得到脚本如下:

key = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890{}_#&'
m='WhcuU0o4Vc0VUasJc08W04uJ0qd2IJpVJ02V04p'
m1='{'
for i in range(2,39):
    x=key.find(m[i])
    y=key.find(m[i-1])
    for ftmp in range(0,67):
        if x-y>=0:
            if 23*(ftmp-key.find(m1[i-2])+67)%67==x-y:
                m1 += key[ftmp]
        else:
            if 23*(ftmp-key.find(m1[i-2])+67)%67==x-y+67:
                m1+= key[ftmp]
print('hsctf'+m1+'}')

最终得到输出结果:hsctf{th3_l4st_s3c5et_0f_4he_un1ve2se_1s_42}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值