随机数题,LFSR变形,记录一下。
题目源码:
from secret import secret
for b in secret: assert(b == '0' or b == '1')
assert(len(secret) == 128)
# a 01 string with length 128
# your flag is flag{md5(secret).hexdigest()}
def string2bits(s):
return [int(b) for b in s]
def bits2string(bs):
s = [str(b) for b in bs]
return ''.join(s)
def lfsr(state, mask):
assert(len(state) == 128)
assert(len(mask) == 128)
output = 0
for i in range(128):
output = output ^ (state[i] & mask[i])
return output
if __name__ == '__main__':
initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
mask = string2bits(secret)
for i in range(256):
state = initState[i:]
output = lfsr(state, mask)
initState += [output]
outputState = bits2string(initState[128:])
print('outputState =', outputState)
#
# outputState = 1010100001001011101000000100100001101011010100101011010101011010100100001110010010110111010111110000000000011011001110100011000111110100110011011011100111000000001100001000001011010011011010110110111100110101001110001001001000001110111011110001111001111111
#
分析一下题目逻辑。初识化数组 initState
,即为LFSR(线性反馈移位寄存器)的初始状态,mask
是flag转二进制之后的数组。
最主要的操作就是进行256轮LFSR计算,这地方和简单LFSR有点不同
lfsr
函数,输入两个长度为128数组state, mask
,输出output
值为 o u t = ∑ s t a t e i × m a s k i m o d 2 out=\sum{state_i \times mask_i} \mod 2 out=∑statei×maskimod2- 注意到每轮
state
数组取值会向右移动一个位置,同时initState
长度会增长1,即数组尾部追加了output
值
关键的关系式
o
u
t
=
∑
s
t
a
t
e
i
×
m
a
s
k
i
m
o
d
2
out=\sum{state_i \times mask_i} \mod 2
out=∑statei×maskimod2
可改写为矩阵乘法形式
o
u
t
=
S
t
a
t
e
×
M
a
s
k
m
o
d
2
out=State \times Mask \mod 2
out=State×Maskmod2
State是
1
×
128
1\times128
1×128 向量,Mask是
128
×
1
128 \times 1
128×1 向量
256轮循环最终输出 initState
数组后256个元素,命名为 outputState
,其中
o
u
t
p
u
t
S
t
a
t
e
0...127
×
M
a
s
k
=
o
u
t
p
u
t
S
t
a
t
e
128
m
o
d
2
o
u
t
p
u
t
S
t
a
t
e
1...128
×
M
a
s
k
=
o
u
t
p
u
t
S
t
a
t
e
129
m
o
d
2
⋯
o
u
t
p
u
t
S
t
a
t
e
127...254
×
M
a
s
k
=
o
u
t
p
u
t
S
t
a
t
e
255
m
o
d
2
outputState_{0...127} \times Mask = outputState_{128} \mod 2 \\ outputState_{1...128} \times Mask = outputState_{129} \mod 2 \\ \cdots \\ outputState_{127...254} \times Mask = outputState_{255} \mod 2
outputState0...127×Mask=outputState128mod2outputState1...128×Mask=outputState129mod2⋯outputState127...254×Mask=outputState255mod2
尝试模2条件下线性方程组求解。
求解有点问题,最后是把initState组在outputState前面一起解方程组,得到正解
最终exp:
#sage
def string2bits(s):
return [int(b) for b in s]
if __name__ == '__main__':
initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
outputState = string2bits('1010100001001011101000000100100001101011010100101011010101011010100100001110010010110111010111110000000000011011001110100011000111110100110011011011100111000000001100001000001011010011011010110110111100110101001110001001001000001110111011110001111001111111')
states = initState + outputState
ms = MatrixSpace(GF(2), 128, 128)
mv = []
for i in range(128):
mv += states[i : i + 128]
m= ms(mv)
vs = MatrixSpace(GF(2), 128, 1)
vv = outputState[0:128]
v = vs(vv)
secret = m.inverse() * v
M=secret.str().replace('\n','').replace('[','').replace(']','')