BUUCTF [AFCTF2018]Tiny LFSR
本来以为可以好好练一练流密码的逆向分析
结果练习到的反而是python3对hex byte 类型的处理转换
题目源码
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
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") # plain
ff = open(sys.argv[3],"wb") # cipher
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 和 plain 求出key
然后有了key lsfr就只是一个流程了(根本不需要逆向) 直接求出flag
求key:
from Crypto.Util.number import *
with open(r'.\Plain.txt',"rb") as f:
plain = f.read()
with open(r'.\cipher.txt',"rb") as f:
cipher = f.read()
plain = bytes_to_long(plain)
cipher = bytes_to_long(cipher)
key = hex(plain^cipher)
print(key)
网上好多WP都是python2版本的...什么decode('hex')根本编译不了 还是用bytes_to_long是最稳健的
求flag:
from binascii import unhexlify
from libnum import *
from Crypto.Util.number import *
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
flag = ""
flag_encode = open(r'.\flag_encode.txt','rb').read()
print(flag_encode)
lent = len(flag_encode)
key = '0123456789abcdef'
a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])
for i in range(0, len(a)):
flag += chr((flag_encode[i])^ord(a[i]))
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 = 0x0123456789abcdef
for i in range(len(a),lent):
tmp = 0
for j in range(8):
(R,out) = lfsr(R,mask)
tmp = (tmp<<1)^out
aaa = flag_encode[i]
flag += chr(tmp^aaa)
print(flag)
最后:
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
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}