攻防世界——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版权协议,转载请附上原文出处链接和本声明。