二元LCG

题目:

from secret import flag

assert flag[:5] == b'cazy{'
assert flag[-1:] == b'}'
flag = flag[5:-1]
assert (len(flag) == 24)


class my_LCG:
    def __init__(self, seed1, seed2):
        self.state = [seed1, seed2]
        self.n = getPrime(64)
        while 1:
            self.a = bytes_to_long(flag[:8])
            self.b = bytes_to_long(flag[8:16])
            self.c = bytes_to_long(flag[16:])
            if self.a < self.n and self.b < self.n and self.c < self.n:
                break

    def next(self):
        new = (self.a * self.state[-1] + self.b * self.state[-2] + self.c) % self.n
        self.state.append(new)
        return new


def main():
    lcg = my_LCG(getRandomInteger(64), getRandomInteger(64))
    print("data = " + str([lcg.next() for _ in range(5)]))
    print("n = " + str(lcg.n))


if __name__ == "__main__":
    main()

# data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
# n = 10104483468358610819

解题思路:

  • 二元LCG就是多了一组生成器,解题思路和一元一样,还是推出相关等式
  • tmp[1] = data[1] - data[0]

tmp[2] = data[2] - data[1]

tmp[3] = data[3] - data[2]

tmp[4] = data[4] - data[3]

data[2] = (a * data[1] + b * data[0] + c) % n

data[3] = (a * data[2] + b * data[1] + c) % n

data[4] = (a * data[3] + b * data[2] + c) % n

  • tmp[3] = (a * tmp[2] + b * tmp[1]) % n

tmp[4] = (a * tmp[3] + b * tmp[2]) % n

  • ①式 × tmp[2] - ②式 × tmp[1]

解答:

import gmpy2
from Crypto.Util.number import *
data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
n = 10104483468358610819

tmp = [0]
for i in range(1,5):
    tmp.append(data[i] - data[i-1])

a = ((tmp[3] * tmp[2] - tmp[4] * tmp[1]) * gmpy2.invert(tmp[2] * tmp[2] - tmp[3] * tmp[1],n)) % n
b = ((tmp[3] - a * tmp[2]) * gmpy2.invert(tmp[1],n)) % n
c = (data[2] - a * data[1] - b * data[0]) % n
print(b'cazy{' + long_to_bytes(a) + long_to_bytes(b) + long_to_bytes(c) + b'}')
#cazy{L1near_Equ4t1on6_1s_34sy}

ai一把梭

AI思路:

代码功能分析

  1. **my_LCG**
    • 初始化 (**__init__** 方法)
      • 接收两个初始种子seed1seed2,并将其存储到self.state列表中
      • 随机生成一个 64 位的素数n,作为模数
      • flag中提取三个参数abc,并确保它们小于n
        • a来自flag的前 8 字节
        • b来自flag的第 8 到第 16 字节
        • c来自flag的第 16 到第 24 字节
    • 生成下一个随机数 (**next**方法)
      • 根据线性同余公式计算新的随机数:new=(a⋅state[−1]+b⋅state[−2]+c) mod n
      • 将新生成的随机数追加到self.state列表中,并返回该值
  2. **main**函数
    • 创建一个my_LCG实例,初始种子为两个随机的 64 位整数
    • 生成 5 个随机数并打印出来
    • 打印模数n
  3. 已知输出
    • 已知生成的 5 个随机数:
    • data=[2626199569775466793,8922951687182166500,454458498974504742,7289424376539417914,8673638837300855396]
    • 模数:n=10104483468358610819

正确的分析和求解过程

我们需要从已知的线性同余方程组中解出 a、b 和 c,已知的方程组如下:

x3=(a⋅x2+b⋅x1+c) mod n

x4=(a⋅x3+b⋅x2+c) mod n

x5=(a⋅x4+b⋅x3+c) mod n

其中:

  • x1=2626199569775466793
  • x2=8922951687182166500
  • x3=454458498974504742
  • x4=7289424376539417914
  • x5=8673638837300855396
  • n=10104483468358610819

正确的求解步骤

  1. 建立方程组
    • 从第一个方程:x3=(a⋅x2+b⋅x1+c) mod n
    • 从第二个方程:x4=(a⋅x3+b⋅x2+c) mod n
    • 从第三个方程:x5=(a⋅x4+b⋅x3+c) mod n
  2. **消去 **c
    • 从第一个方程中解出 c:c=(x3−a⋅x2−b⋅x1) mod n
    • 将 c 代入第二个方程:x4=(a⋅x3+b⋅x2+x3−a⋅x2−b⋅x1) mod n
    • 化简得:x4=(a⋅(x3−x2)+b⋅(x2−x1)+x3) mod n
    • 将 c 代入第三个方程:x5=(a⋅x4+b⋅x3+x3−a⋅x2−b⋅x1) mod n
    • 化简得:x5=(a⋅(x4−x2)+b⋅(x3−x1)+x3) mod n
  3. **求解 a 和 **b
    • 从第二个方程:x4=(a⋅(x3−x2)+b⋅(x2−x1)+x3) mod n
    • 重新整理:a⋅(x3−x2)+b⋅(x2−x1)=(x4−x3) mod n
    • 从第三个方程:x5=(a⋅(x4−x2)+b⋅(x3−x1)+x3) mod n
    • 重新整理:a⋅(x4−x2)+b⋅(x3−x1)=(x5−x3) mod n
  4. 线性方程组求解
    • 我们得到了两个线性方程:

a⋅(x3−x2)+b⋅(x2−x1)=(x4−x3) mod n

a⋅(x4−x2)+b⋅(x3−x1)=(x5−x3) mod n

- 这是一个二元一次线性方程组,可以使用矩阵求逆或高斯消元法求解 a 和 b
from Crypto.Util.number import long_to_bytes, getPrime
from Crypto.Random import get_random_bytes

# 已知数据
data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
n = 10104483468358610819

# 提取已知值
x1, x2, x3, x4, x5 = data

# 建立方程组
# a * (x3 - x2) + b * (x2 - x1) = (x4 - x3) % n
# a * (x4 - x2) + b * (x3 - x1) = (x5 - x3) % n

# 系数矩阵
A = [
    [x3 - x2, x2 - x1],
    [x4 - x2, x3 - x1]
]

# 常数向量
B = [
    (x4 - x3) % n,
    (x5 - x3) % n
]

# 求解线性方程组
def matrix_inverse(A, n):
    det = (A[0][0] * A[1][1] - A[0][1] * A[1][0]) % n
    det_inv = pow(det, -1, n)
    inv_A = [
        [A[1][1], -A[0][1]],
        [-A[1][0], A[0][0]]
    ]
    for i in range(2):
        for j in range(2):
            inv_A[i][j] = (inv_A[i][j] * det_inv) % n
    return inv_A

# 计算矩阵的逆
inv_A = matrix_inverse(A, n)

# 求解 a 和 b
a = (inv_A[0][0] * B[0] + inv_A[0][1] * B[1]) % n
b = (inv_A[1][0] * B[0] + inv_A[1][1] * B[1]) % n

# 求解 c
c = (x3 - a * x2 - b * x1) % n

# 转换为字节形式
flag = b'cazy{' + long_to_bytes(a, 8) + long_to_bytes(b, 8) + long_to_bytes(c, 8) + b'}'
print(flag)
#cazy{L1near_Equ4t1on6_1s_34sy}
posted @ 2025-03-12 00:03  sevensnight  阅读(32)  评论(0)    收藏  举报