[afctf][crypto]有趣的题目

slove

核心是使用明文字符串自身的元素生成一个“伪随机字符串”与自身异或生成密文。

伪随机字符串的生成规则由i + space < len(plainText) - 1判断

ord(plainText[i + space]),ord(plainText[space])的space的移动由明文对应字符的ascii字符奇偶性决定。

**大部分情况下,明文的顺序应该是递增的,且是从10开始的偶数,pseudo_array可以证明这一点

明文长度28字节。

爆破2^28,应至少存在一个bit序列等于当前密文的每字节最后1bit组成的序列。

知道这个bit序列后就知道了space的移动情况,进而可以获得“伪随机字符串”是明文的哪些项的置换。

根据flag的固定格式afctf可以提前获得某些明文部分。经测试至少知道前2个字符即可解密


def encrypt(plainText):
    space = 10
    cipherText = ""
    try:
        for i in range(len(plainText)):
            if i + space < len(plainText) - 1:
                cipherText += chr(ord(plainText[i]) ^ ord(plainText[i + space]))
            else:
                cipherText += chr(ord(plainText[i]) ^ ord(plainText[space]))
            if ord(plainText[i]) % 2 == 0:
                space += 1
            else:
                space -= 1
    except:
        return '1'
    return cipherText

def brute():
    for x in range(2**28):
        print(x)
        last_bit=bin(x)[2:].zfill(28)
        assert len(last_bit)==28
        tostr=''
        for each in last_bit:
            tostr+=chr(int(each,2))
        
        tmp=encrypt(tostr)
        

        tmp2=''
        for each in tmp:
            tmp2+=bin(ord(each))[-1]
        if tmp2=='1010000101101011111111101000':
            print('found',last_bit)
cipherText = "15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206"
tmp=''
for each in bytes.fromhex(cipherText):
    tmp+=bin(each)[-1]
print(tmp) #1010000101101011111111101000
brute()

# found 1010011010010101111111101001

part2

# 10,9,10,9,10,11,10,9,10,9,10,11,10,11,10,11,10, 9, 8, 7, 6, 5, 4, 3, 4, 3, 4, 5     sapce
# 0 ,1,2 ,3,4 ,5 ,6 ,7, 8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27    index
# 10,10,12,12,14,16,16,16,18,18,20,22,22,24,24,26,26,26,26,26,26,26,26,26,4,3,4,5,  real index
# b'\x15\x12\r\x1a\n\x08\x10\x01\n\x03\x1d>1\x00\r\x1d\x17\r\x17;\r\x17;\x0c\x07\x06\x02\x06'
cipherText = "15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206"
print(bytes.fromhex(cipherText))
cipher=bytes.fromhex(cipherText)

space=[10,9,10,9,10,11,10,9,10,9,10,11,10,11,10,11,10, 9, 8, 7, 6, 5, 4, 3, 4, 3, 4, 5 ]
pseudo_array=[10,10,12,12,14,16,16,16,18,18,20,22,22,24,24,26,26,26,26,26,26,26,26,26,4,3,4,5,]
origin=[0 ,1,2 ,3,4 ,5 ,6 ,7, 8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]
for a,b in zip(pseudo_array,origin):
    print('%2d'%a,end=',')
print()
for a,b in zip(pseudo_array,origin):
    print('%2d'%b,end=',')
    


w=['ww']*28
know='afctf'
w[:len(know)]=know
# print(w,len(w))
while 'ww' in w:
    for p,o in zip(pseudo_array,origin):
        if w[o] !='ww':
            w[p]=chr(ord(w[o])^cipher[o])
        if w[p] !='ww':
            w[o]=chr(ord(w[p])^cipher[o])
        
            
print(''.join(w))
# afctf{cryptanalysis_is_hard} 

**跑了12分钟才跑出来,算法还得优化下

优化后还需要5分钟 

还有一种思路是从正向约束,直接约束出结果,但是代码不好实现 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值