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}
posted @ 2023-10-05 16:54  N0zoM1z0  阅读(60)  评论(0编辑  收藏  举报