[De1CTF2019]Babylfsr

目录

1.题目

2.分析

3.解题

4.参考


1.题目

#task.py:

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)

#output:
'''
001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010
'''

2.分析

题目考点:LFSR

题目没有给出mask和key,但是给出了一段较长的01输出序列

001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010
length = 504

而我们知道每连续的256个bit能够决定下一个bit的值,只要能够凑齐256个方程组,我们就能够求出mask,进而求出key值,所以我们可以考虑进行爆破求解,求出多个key值,然后根据断言进行选择

断言:

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

解方程组的问题可以转化为矩阵求逆的问题。把 lfsr 的状态一行一行地写在矩阵上,形成的矩阵记为 M. 把 lsfr 每次所生成的结果也拼成一个向量,记为 T. 那么掩码向量 v 使得

Mv = T
v = TM_inv
#M_inv 是M的逆矩阵,利用sagemath进行求解

3.解题

爆破mask向量

#please run the code in sagemath
import itertools

def test(padding):
    s = [int(x) for x in '001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010'] + padding

    M = matrix(GF(2), 256, 256)
    T = vector(GF(2), 256)

    for i in range(len(s) - 256):
        M[i] = s[i : i + 256]
        T[i] = s[i+256]
    try:
        v = M.inverse() * T
        print(hex(int(''.join(map(str, (v))), base=2)))
    except:
        return
    

for x in itertools.product([0, 1], repeat = 8):
    test(list(x))

然后完成了初步的爆破之后,我们可以利用猜测得到的输出信息(512位),以及得到的mask,进

一步求解出不确定的key,然后根据断言选择

#sagemath is needed

import itertools, hashlib, numpy as np

def bin2int(a):#将01数组转化为十进制数
    return reduce(lambda x,y: x*2+y, a)

def bitAnd(a, b):#计算两个01数组中相同的1的个数
    assert len(a) == len(b)
    return list(map(lambda x,y: int(x)&int(y), a, b))
    
def test(padding):
    s = [int(x) for x in '001010010111101000001101101111010000001111011001101111011000100001100011111000010001100101110110011000001100111010111110000000111011000110111110001110111000010100110010011111100011010111101101101001110000010111011110010110010011101101010010100101011111011001111010000000001011000011000100000101111010001100000011010011010111001010010101101000110011001110111010000011010101111011110100011110011010000001100100101000010110100100100011001000101010001100000010000100111001110110101000000101011100000001100010'] + padding

    M = matrix(GF(2), 256, 256)#定义矩阵M
    T = vector(GF(2), 256)#定义向量v,用于解出掩码

    for i in range(len(s) - 256):
        M[i] = s[i : i + 256]#矩阵赋值
        T[i] = s[i+256]#向量赋值
    try:
        mask = M.inverse() * T#获得掩码,凭借sagemath对矩阵的逆的求解功能进行运算
    except:
        return

    suf = []
    for i in range(256):#逐位破解
        if bitAnd([0] + suf + s[0:255 - i], mask).count(1) % 2 == s[255 - i]:
            suf = [0] + suf
        else:
            suf = [1] + suf

    key = hex(bin2int(suf))[2:]
    sha = hashlib.sha256(key.encode()).hexdigest()
    
    if sha[:4] == '1224':#验算
        print('de1ctf{' + sha + '}')
    

for x in itertools.product([0, 1], repeat = 8):#生成8个位置为0或1的数组
    test(list(x))

得到flag:

de1ctf{1224473d5e349dbf2946353444d727d8fa91da3275ed3ac0dedeb7e6a9ad8619}

4.参考

文章1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值