参考: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+'}')