NSSCTF_crypto_[LitCTF 2023]babyLCG

python 复制代码
from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag)
bit_len = m.bit_length()
a = getPrime(bit_len)
b = getPrime(bit_len)
p = getPrime(bit_len+1)

seed = m
result = []
for i in range(10):
    seed = (a*seed+b)%p
    result.append(seed)
print(result)
"""
result = [699175025435513913222265085178805479192132631113784770123757454808149151697608216361550466652878, 193316257467202036043918706856603526262215679149886976392930192639917920593706895122296071643390, 1624937780477561769577140419364339298985292198464188802403816662221142156714021229977403603922943, 659236391930254891621938248429619132720452597526316230221895367798170380093631947248925278766506, 111407194162820942281872438978366964960570302720229611594374532025973998885554449685055172110829, 1415787594624585063605356859393351333923892058922987749824214311091742328340293435914830175796909, 655057648553921580727111809001898496375489870757705297406250204329094679858718932270475755075698, 1683427135823894785654993254138434580152093609545092045940376086714124324274044014654085676620851, 492953986125248558013838257810313149490245209968714980288031443714890115686764222999717055064509, 70048773361068060773257074705619791938224397526269544533030294499007242937089146507674570192265]
"""

题目描述

题目给出了一个使用 线性同余生成器 (LCG) 生成的 10 个连续伪随机数,要求恢复初始种子 (即 flag)。

数学原理

LCG 的递推公式为:

其中 pp是未知的大质数,aa 和 bb 是未知乘数和加数,s0s0​ 是初始种子。

我们有连续输出 s1,s2,...,s10


完整代码

python 复制代码
from Crypto.Util.number import long_to_bytes
from math import gcd

# 给定的输出序列
result = [
    699175025435513913222265085178805479192132631113784770123757454808149151697608216361550466652878,
    193316257467202036043918706856603526262215679149886976392930192639917920593706895122296071643390,
    1624937780477561769577140419364339298985292198464188802403816662221142156714021229977403603922943,
    659236391930254891621938248429619132720452597526316230221895367798170380093631947248925278766506,
    111407194162820942281872438978366964960570302720229611594374532025973998885554449685055172110829,
    1415787594624585063605356859393351333923892058922987749824214311091742328340293435914830175796909,
    655057648553921580727111809001898496375489870757705297406250204329094679858718932270475755075698,
    1683427135823894785654993254138434580152093609545092045940376086714124324274044014654085676620851,
    492953986125248558013838257810313149490245209968714980288031443714890115686764222999717055064509,
    70048773361068060773257074705619791938224397526269544533030294499007242937089146507674570192265
]

# ============================================================
# 第一步:恢复模数 p
# ============================================================

# 计算相邻状态的差值 t_i = s_{i+1} - s_i (i = 0..8)
t = []
for i in range(len(result) - 1):
    t.append(result[i+1] - result[i])

# 利用 t_{i+1} * t_{i-1} - t_i^2 ≡ 0 (mod p)
# 多个这样的值求 gcd 得到 p 的倍数,进而得到 p
U = []
for i in range(1, len(t) - 1):
    U.append(t[i+1] * t[i-1] - t[i]**2)

# 求这些数的最大公约数
p = abs(U[0])
for x in U[1:]:
    p = gcd(p, x)

# 如果 p 含有小因子,可以尝试进一步分解,通常 p 就是素数
print(f"[+] 恢复的模数 p = {p}")

# ============================================================
# 第二步:恢复乘数 a
# ============================================================

# 由 t_1 ≡ a * t_0 (mod p),得到 a = t_1 * t_0^{-1} mod p
a = (t[1] * pow(t[0], -1, p)) % p
print(f"[+] 恢复的乘数 a = {a}")

# ============================================================
# 第三步:恢复加数 b
# ============================================================

# 由 s_2 ≡ a * s_1 + b (mod p),得到 b = s_2 - a * s_1 mod p
b = (result[2] - a * result[1]) % p
print(f"[+] 恢复的加数 b = {b}")

# ============================================================
# 第四步:恢复初始种子 s_0(即 m)
# ============================================================

# 由 s_1 ≡ a * s_0 + b (mod p),得到 s_0 = (s_1 - b) * a^{-1} mod p
seed = ((result[0] - b) * pow(a, -1, p)) % p
print(f"[+] 恢复的初始种子 s_0 = {seed}")

# ============================================================
# 第五步:获取 flag
# ============================================================

flag = long_to_bytes(seed)
print(f"[+] Flag: {flag.decode()}")

运行后flag为

NSSCTF{31fcd7832029a87f6c9f760fcf297b2f}

相关推荐
cdbqss110 小时前
VB2026 菜单生成基类 BqGetMenuStrip
数据库·经验分享·学习·oracle·vb
IT 行者10 小时前
SimHash 与 MinHash:相似性计算的双子星算法
算法·hash·比对
智者知已应修善业11 小时前
【51单片机8位数码管动态显示日期小数点风格】2023-11-13
c++·经验分享·笔记·算法·51单片机
智者知已应修善业11 小时前
【51单片机有三个LED 分别第一个灯闪三下 再到第二个灯又闪三下 再到第三个灯又闪三下 就这样循环程序】2023-11-16
c++·经验分享·笔记·算法·51单片机
熊猫不是猫QAQ11 小时前
NAS上的文字版《星露谷物语》,大型种田经营游戏
经验分享
渣渣xiong12 小时前
从零开始:前端转型AI agent直到就业第五十七天-第五十八天
前端·人工智能·python
小L~~~12 小时前
基于贪心策略的混合遗传算法求解01背包问题
python·算法
才兄说12 小时前
机器人二次开发机器人动作定制?动作迁移数据优化
python
洛水水13 小时前
【力扣100题】53.最长回文子串
算法·leetcode·职场和发展