攻防世界——streamgame1

攻防世界——streamgame1

原理:爆破flag
题目

在这里插入图片描述
题解:拿到两个文件,先看一下py文件

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的二进制补码 24
    i=(R&mask)&0xffffff             #按位与运算符&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 24
    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()

分析代码:flag总共19位,且从21行能看出flag应该是2进制,lfsr应该是加密函数。从下面看出有8次循环,每次返回一个比特,8个比特组成一个字节,总共有十二个,都存到key文件中。

key文件
在这里插入图片描述
分析加密的方法比较困难,但因为flag只有19位,即2**19种可能,可以直接爆破。

代码

def lfsr(R,mask):
    output = (R << 1) & 0xffffff    #将R向左移动1位,bin(0xffffff)='0b111111111111111111111111'=0xffffff的二进制补码
    i=(R&mask)&0xffffff             #按位与运算符&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 24
    lastbit=0
    while i!=0:
        lastbit^=(i&1)    #按位异或运算符:当两对应的二进位相异时,结果为1
        i=i>>1
    output^=lastbit
    return (output,lastbit)
key = [0x55,0x38,0xf7,0x42,0xc1,0x0d,0xb2,0xc7,0xed,0xe0,0x24,0x3a]
mask = 0b1010011000100011100
tmp = 0
tip = 0
for k in range(2**19):
    R = k
    tip = 1
    for i in range(12):
        tmp = 0
        for j in range(8):
            (R,out)=lfsr(R,mask)
            tmp=(tmp << 1)^out
        if tmp != key[i]:
            tip = 0
            break
    if tip == 1:
        print("flag{"+bin(k)[2:]+"}")
        break

flag{1110101100001101011}


版权声明:本文为weixin_51867782原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。