1.题目
#Encrypt.py:
import sys
from binascii import unhexlify
if(len(sys.argv)<4):
print("Usage: python Encrypt.py keyfile plaintext ciphername")
exit(1)
def lfsr(R, mask):
output = (R << 1) & 0xffffffffffffffff
i=(R&mask)&0xffffffffffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
R = 0
key = ""
with open(sys.argv[1],"r") as f:
key = f.read()
R = int(key,16)
f.close
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])
f=open(sys.argv[2],"r")
ff = open(sys.argv[3],"wb")
s = f.read()
f.close()
lent = len(s)
for i in range(0, len(a)):
ff.write((ord(s[i])^ord(a[i])).to_bytes(1, byteorder='big'))
for i in range(len(a), lent):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
ff.write((tmp^ord(s[i])).to_bytes(1, byteorder='big'))
ff.close()
#cipher.txt:not visible
#flag_encode.txt: not visible
#plain.txt: sdgfjkahblskdjxbvfskljdfbguisldfbvghkljsdfbghsjkldhbgjklsdbgvlkjsdgbkljb sdkljfhwelo;sdfghioeurthgbnjl k
#.bash_history.txt:
'''
python Encrypt.py key.txt Plain.txt cipher.txt
python Encrypt.py key.txt flag.txt flag_encode.txt
rm flag.txt
rm key.txt
'''
2.分析
.bash_history.txt文件中的信息是说,使用了同一份key.txt对Plain.txt和flag_encode.txt进行加密,得到了cipher.txt和flag_encode.txt。
mask的长度:
0b1101100000000000000000000000000000000000000000000000000000000000
length = 64
留意题目中的这部分代码:
for i in range(0, len(a)):
ff.write((ord(s[i])^ord(a[i])).to_bytes(1, byteorder='big'))
for i in range(len(a), lent):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
ff.write((tmp^ord(s[i])).to_bytes(1, byteorder='big'))
密文的前面较少的一部分使用可以来进行异或加密,所以我们只需要让密文和明文异或就能够得到key,然而我们不能知道密文的长度,我们先看一下直接异或后所有的输出
import codecs
import binascii
from Crypto.Util.strxor import strxor
cip = open('cipher.txt', 'rb').read()
msg = open('Plain.txt', 'rb').read()
bytes_data= strxor(cip, msg)[:len(cip)]
print(binascii.b2a_hex(bytes_data))
输出:
b'0123456789abcdef184bb2ec4d1ee7b86e3a6e926e3a6e8d203b2e03203b2f2c6226e22e6226fad1953215e7953374e745e7cf6d45f97467bf6adc09be5779eecc4444ccd535dba9f2aaa7fe85ad0b2aa800a81ff94ff680380e39205550c78208801067007b0cb6'
我们注意到其前16个恰好是连续的字符串,我们猜测这是key,前16个字符:
b'0123456789abcdef'
在得到了key之后,解题就只需要再一次进行异或运算即可
解题代码:
import sys
from binascii import unhexlify
from Crypto.Util.strxor import strxor
import codecs
key = '0123456789abcdef'
R = int(key, 16)
def lfsr(R, mask):
output = (R << 1) & 0xffffffffffffffff
i=(R&mask)&0xffffffffffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
cip = open('flag_encode.txt', 'rb').read()
a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])
#上面这步是将a中的16进制范围内的字符每2个一组,构成0~255范围内的8个字符,然后与密文进行异或运算,密文读入时是'\xaa'的形式
lent = len(cip)
ans = []
for i in range(len(a)):
ans.append(chr((cip[i] ^ ord(a[i]))))
for i in range(len(a), lent):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
#位移8次得到一个8位的序列,这个序列用于后续的异或运算
ans.append(chr(tmp ^ cip[i]))
#原本的加密没有改变信息原文的长度,于是可以对其进行简单异或还原信息
#cip[i]算作是int类型数据,故可以进行异或运算
print(''.join(ans))
输出:
In computing, a linear-feedback shift register (LFSR) is a shift register whose input bit is a linear function of its previous state.
The most commonly used linear function of single bits is exclusive-or (XOR). Thus, an LFSR is most often a shift register whose input bit is driven by the XOR of some bits of the overall shift register value.
The initial value of the LFSR is called the seed, and because the operation of the register is deterministic, the stream of values produced by the register is completely determined by its current (or previous) state. Likewise, because the register has a finite number of possible states, it must eventually enter a repeating cycle. However, an LFSR with a well-chosen feedback function can produce a sequence of bits that appears random and has a very long cycle.
Applications of LFSRs include generating pseudo-random numbers, pseudo-noise sequences, fast digital counters, and whitening sequences. Both hardware and software implementations of LFSRs are common.
The mathematics of a cyclic redundancy check, used to provide a quick check against transmission errors, are closely related to those of an LFSR.
Congratulations! flag is afctf{read_is_hard_but_worthy}
flag在最后一行:
afctf{read_is_hard_but_worthy}