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}

相关推荐
某林21214 分钟前
局部路径规划器 DWB:速度采样与评分权重的取值分析
人工智能·算法·架构·机器人·技术复盘
AI职业加油站15 分钟前
模数共振行动解读|大模型应用工程师证书,匹配行业 RAG/Agent 落地人才需求
人工智能·学习·算法·职场和发展·职场发展
2601_9628857224 分钟前
从 baostock 迁移到 AlphaFeed:接口对照与代码迁移指南
python
AI情绪识别开源1 小时前
检信ALLEMOTION 标定治理与信号质量闸门 · 老年无感认知评估分析器
python
1314lay_10071 小时前
ABAP 读取服务器的文件 OPEN DATASET,READ DATASET f_filepath INTO l_file.
经验分享·笔记
七夜zippoe1 小时前
启元 Q1 腿部运动学逆解:Python 算站立下蹲关节角
开发语言·python·ai·机器人·腿部运动学
lengxuenong1 小时前
树状数组 · 信息学学习手册2-离散化与逆序对
c++·学习·算法
琳达爱分享1 小时前
五个线程同时去换 token,四个被踢下线:刷新接口其实不是幂等的
后端·算法·架构
第404号工位1 小时前
插上充电宝真能偷光相册?我拆解了一台改装充电宝,实测“恶意充电”的真实攻击链
linux·python·架构
十二1 小时前
【洛谷题解】P1115 最大子段和(前缀和 + 维护最小前缀)
数据结构·c++·算法·蓝桥杯