[De1CTF2019]Babylfsr(B-M算法)

 参考:ctfwiki

根据B-M算法的介绍,我们至少需要知道2n长度的序列,则可以推测出初始化seed

题目源码:

import hashlib
from secret import KEY,FLAG,MASK

assert(FLAG=="de1ctf{"+hashlib.sha256(hex(KEY)[2:].rstrip('L')).hexdigest()+"}")
assert(FLAG[7:11]=='1224')

LENGTH = 256

assert(KEY.bit_length()==LENGTH)
assert(MASK.bit_length()==LENGTH)

def pad(m):
    pad_length = 8 - len(m)
    return pad_length*'0'+m

class lfsr():
    def __init__(self, init, mask, length):
        self.init = init
        self.mask = mask
        self.lengthmask = 2**(length+1)-1

    def next(self):
        nextdata = (self.init << 1) & self.lengthmask    
        i = self.init & self.mask & self.lengthmask   
        output = 0
        while i != 0:
            output ^= (i & 1)            
            i = i >> 1
        nextdata ^= output               
        self.init = nextdata
        return output                     


if __name__=="__main__":
    l = lfsr(KEY,MASK,LENGTH)
    r = ''
    for i in range(63):
        b = 0
        for j in range(8):
            b = (b<<1)+l.next()
        r += pad(bin(b)[2:])           
    with open('output','w') as f:
        f.write(r)

题目给出的r只有504位,根据B-M算法我们想要得到256位的初始化seed至少需要知道512位序列

不足的8个二进制位可以通过爆破得到,通过筛选得到符合条件的mask

 图片摘自ctfwiki

根据上图,构造矩阵X和S,通过矩阵运算得到C,也就是mask,然后通过判定条件

assert(FLAG[7:11]=='1224')

确定符合条件的mask值并得到flag

已知mask和lfsr之后的输出序列,且输出序列至少和flag等长的话,可以恢复初始化seed

和之前做过的三道题类似,已知mask和输出序列怎么逆推seed可参考我之前的博客我之前的博客https://blog.csdn.net/m0_62506844/article/details/124378089?spm=1001.2014.3001.5502

参考合天网安实验室的wp,注意在sagemath里^^才是异或,^是求幂!

import hashlib
from tqdm import tqdm
r='001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010'
 
def get_key(mask,key):
    R = ""
    index = 0
    key = key[255] + key[:256]
    while index < 256:
        tmp = 0
        for i in range(256):
            if mask >> i & 1:
                tmp = (tmp^^int(key[255-i]))               
        R = str(tmp) + R
        index += 1
        key = key[255] + str(tmp) + key[1:255]
    return int(R,2)
 
def get_int(x):
    m=''
    for i in range(256):
        m += str(x[i])
    return (int(m,2))
 
 
sm=[]
for i in tqdm(range(2**8)):#爆破后8位
    a=[]
    may=r+bin(i)[2:].zfill(8)
    for j in may:
        a.append(int(j))      #将后8位添加到已知序列的后面
    X = []
    for i in range(256):
        for j in range(256):
            if a[i+j]==1:
                X.append(1)
            else:
                X.append(0)
    S=a[256:512]
    MS1=MatrixSpace(GF(2),256,256)
    MS2=MatrixSpace(GF(2),1,256)
    X=MS1(X)
    S=MS2(S)
    try:
        inv=X.inverse()
    except:
        continue
    mask=S*inv
    sm.append(hex(get_key(get_int(mask[0]),r[:256])))
print(sm)
 
 
for i in range(len(sm)):
    FLAG = hashlib.sha256(sm[i][2:].encode()).hexdigest()
    if FLAG[:4]=='1224':
        print('flag{'+FLAG+'}')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Paintrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值