攻防世界:streamgame1(考点:LFSR)

题目:

from flag import flag
assert flag.startswith("flag{")
# 作用:判断字符串是否以指定字符或子字符串开头flag{
assert flag.endswith("}")
# 作用:判断字符串是否以指定字符或子字符串结尾},flag{},6个字节
assert len(flag)==25
# flag的长度为25字节,25-6=19个字节
#3<<2可以这么算,bin(3)=0b11向左移动2位变成1100,0b1100=12(十进制)
def lfsr(R,mask):
    output = (R << 1) & 0xffffff    #将R向左移动1位,bin(0xffffff)='0b111111111111111111111111'=0xffffff的二进制补码
    i=(R&mask)&0xffffff             #按位与运算符&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
    lastbit=0
    while i!=0:
        lastbit^=(i&1)    #按位异或运算符:当两对应的二进位相异时,结果为1
        i=i>>1
    output^=lastbit
    return (output,lastbit)

R=int(flag[5:-1],2)
mask    =   0b1010011000100011100

f=open("key","ab")   #以二进制追加模式打开
for i in range(12):
    tmp=0
    for j in range(8):
        (R,out)=lfsr(R,mask)
        tmp=(tmp << 1)^out   #按位异或运算符:当两对应的二进位相异时,结果为1
    f.write(chr(tmp))  #chr() 用一个范围在 range(256)内的(就是0~255)整数作参数,返回一个对应的字符。
f.close()

不懂LFSR的看看这篇文章,看完就懂了
深入分析CTF中的LFSR类题目(一)

理解一下这幅图就明白了,原理大致是 flag的最后一位,与lastbit的前31位,通过线性关系异或,会得到lastbit的 第32位,我们已知第32位,需要求flag的最后一位。所以逆向异或关系即可求得flag的最后一位。
在这里插入图片描述

第一种算法 EXP:
f = flag[-1]
output = ‘?’ + key[:18]
flag[-1] =key[18] ^ output[-3] ^ output[-4] ^ output[-5] ^ output[-9] ^ output[-13] ^ output[-14] ^ output[-17]

#python3
from Crypto.Util.number import*
f = open('key.txt','rb').read()
key = bytes_to_long(f)
bin_out = bin(key)[2:].zfill(12*8)
# print(bin_out) 前19位就是key
key = '0101010100111000111'
mask = '1010011000100011100'

R = ''
tem = key
for i in range(19):
    output = '?' + key[:18]
    ans = int(tem[-1-i]) ^ int(output[-3]) ^ int(output[-4]) ^ int(output[-5]) ^ int(output[-9]) ^ int(output[-13]) ^ int(output[-14]) ^ int(output[-17])
    R += str(ans)
    key = str(ans) + key[:18]

print('flag{'+R[::-1]+'}')

第二种算法EXP:

from Crypto.Util.number import*

f = open('key.txt','rb').read()
c = bytes_to_long(f)
bin_out = bin(c)[2:].zfill(12*8)   #将key文本内容转换为 2 进制数,每个字节占 8 位

R = bin_out[0:19]        #前32个2进制数,化为10进制整数


mask = 0b1010011000100011100

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)

# 根据生成规则,初始状态最后一位拼接n-1个生成位,运算后得到第n个生成位,由于生成位已知,因此可以逆推初始状态最后一位。
# 同理,逐位往前推,可得到全部的初始状态位。
# 文件的前32位二进制数,是由seed生成的一个随机数。而且是第32个生成的随机数,而且我们能根据第32个随机数猜测第31个随机数,
# 因为第31个随机数的低31位是第32个随机数的高31位。猜测32次后可以得到原始seed,即flag
def decry():
    cur = bin_out[0:19]      #前19位 2 进制数
    res = ''
    for i in range(19):
        if lfsr(int('0'+cur[0:-1],2),mask)[0] == int(cur,2):
            res += '0'
            cur = '0'+cur[0:-1]
        else:
            res += '1'
            cur = '1' + cur[0:-1]
    return int(res[::-1],2)

r = decry()
print(bin(r))
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值