BUUCTF [CISCN2018]oldstreamgame
lfsr题目
flag = "flag{xxxxxxxxxxxxxxxx}"
assert flag.startswith("flag{")
assert flag.endswith("}")
assert len(flag)==14
def lfsr(R,mask):
output = (R << 1) & 0xffffffff
i=(R&mask)&0xffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
R=int(flag[5:-1],16)
mask = 0b10100100000010000000100010010100
f=open("key","w")
for i in range(100):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
f.write(chr(tmp))
f.close()
当然这里可以选择直接爆破 但是既然是lfsr就应该练习一下逆向
题目虽然做了100轮 每轮8个lfsr 但我们只需要32个就可以逆向求解flag了
取文件前32位:00100000111111011110111011111000
题目fwrite的是每次lfsr产生的lastbit值 而经过32次刚好就是原来的plaintext完整加密一次
我们根据lfsr线性反馈性质直接写出逆向decode:(最开始没 &mask ...)
mask = 0b10100100000010000000100010010100
s = "00100000111111011110111011111000"
"""
已知32次lfsr每次的lastbit
其实32次做完lastbit组合成了最终的加密结果
要还原初始R
"""
# 0x926201d7
flag = 0b00100000111111011110111011111000
ori = ""
def decode():
global mask,flag,ori
i = (flag>>1)&(0xffffffff)
i &= mask
lowbit = flag&1
lastbit = 0
flag >>= 1
# lastbit:在假设先前最高位为0条件下的反馈值
while i!=0:
lastbit ^= (i&1)
i = i>>1
if lastbit == lowbit:
ori += '0'
pass
else:
ori += '1'
flag |= 1<<31
for i in range(32):
decode()
print(flag)
print(bin(flag))
print(hex(flag))
print(ori)
print(hex(int(ori,2)))
然后就能得到flag的hex结果
补:
用更清晰点的思路:
写一写式子发现就是从flag32 lastbit1 ... lastbit31 开始往回推
每次处理就是取当前前31位作为后31位 首位是未知的flag 初始填"0" lfsr算算看lastbit对不对的上来判断要不要改成"1"
s = "20FDEEF8A4C9F4083F331DA8238AE5ED083DF0CB0E7A83355696345DF44D7C186C1F459BCE135F1DB6C76775D5DCBAB7A783E48A203C19CA25C22F60AE62B37DE8E40578E3A7787EB429730D95C9E1944288EB3E2E747D8216A4785507A137B413CD690C"
tmp = []
for i in range(len(s)//2):
tmp.append(int(s[i*2 : i*2+2],16))
mask = 0b10100100000010000000100010010100
s = "00100000111111011110111011111000"
def lfsr(R,mask):
R = int(R,2)
i=(R&mask)&0xffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
return lastbit
m = ""
flag = s
for i in range(31,-1,-1):
lastbit = int(s[i])
flag = "0"+flag[:-1]
pd = lfsr(flag,mask)
if(pd==lastbit):
m+="0"
else:
flag = "1"+flag[1:]
m+="1"
print(hex(int(flag,2)))
print(m)
print(hex(int(m[::-1],2)))