LCG隔位输出(多次连续加密)

题目:

from Crypto.Util.number import *

flag = b'NSSCTF{******}'

class LCG:
    def __init__(self, seed, a, b, m):
        self.seed = seed  # 初始种子
        self.a = a  # 乘数
        self.b = b  # 增量
        self.m = m  # 模数

    def generate(self):
        self.seed = (self.a * self.seed + self.b) % self.m
        self.seed = (self.a * self.seed + self.b) % self.m
        return self.seed

lcg = LCG(bytes_to_long(flag), getPrime(255), getPrime(255), getPrime(256))

for i in range(getPrime(16)):
    lcg.generate()

print(lcg.generate())
print(lcg.generate())
print(lcg.generate())
print(lcg.generate())
print(lcg.generate())
'''
25445927935559969212648839062255651208014967526951331344342413906051118248013,
81572970970116732975667604095930675262596098540738447440566868976253289440293,
6956793925625110803779114150160476498676179542815207353218944386232051429289,
88042506866508011592456777776490262927213783361334741921985316105965255450508,
5652832125321707726481846809536180176877263519327268361130605456255558285092
'''

解题思路:

  • 这里进行了两次加密,我们得到的并不是连续的输出,而是隔位输出,比如是 X2,X4,X6,X8,X10
def generate(self):
        self.seed = (self.a * self.seed + self.b) % self.m
        self.seed = (self.a * self.seed + self.b) % self.m
        return self.seed
  • 首先要恢复模数m,依然可以构造消去增量b构造等比数列,所以我们依然可以用之前的方法求m

  • 接下来就是求a

  • 然后就是这个a^2,可以把a^2看作a,把(a+1)*b看成b,这样就相当于重新构造了一个LCG

解答:

import gmpy2
from Crypto.Util.number import GCD, isPrime, long_to_bytes

c = [25445927935559969212648839062255651208014967526951331344342413906051118248013,
81572970970116732975667604095930675262596098540738447440566868976253289440293,
6956793925625110803779114150160476498676179542815207353218944386232051429289,
88042506866508011592456777776490262927213783361334741921985316105965255450508,
5652832125321707726481846809536180176877263519327268361130605456255558285092]

t=[]
for i in range(1,len(c)):
    t.append(c[i]-c[i-1])

m = 0
for i in range(1,len(t)-1):
    m = GCD(t[i+1]*t[i-1]-t[i]**2, m)
# print(isPrime(m))   # true

a = (c[3]-c[2])*gmpy2.invert(c[2]-c[1],m) % m
b = (c[2]-a*c[1]) % m    # 把(a+1)*b当成b就可以了
# print(gmpy2.gcd(a,m))
# print(gmpy2.gcd(b,m))
a_1=gmpy2.invert(a,m)

for i in range(2**16):
    c[1] = (c[1]-b) * a_1 % m
    flag = long_to_bytes(c[1])

    if b'NSSCTF{' in flag:
        print(flag)
        break
#NSSCTF{step_step_step}
posted @ 2025-03-12 00:03  sevensnight  阅读(35)  评论(0)    收藏  举报