lcg入门
先看原题代码
from libnum import *
flag = 'flag{******************}'
flag = s2n(flag)
length = flag.bit_length()
a = generate_prime(length)
b = generate_prime(length)
n = generate_prime(length)
for i in range(10):
flag = (a * flag + b) % n
print("a =", a)
print("b =", b)
print("n =", n)
print("flag =", flag)
# a = 10580362976768902535288290537881894669438793788144555901400894449594743420700735933898091469
# b = 12282491670012215371979074133375864865383435870031708675997502402287216522639028762493710827
# n = 15544810823190562032492196545115274631091651502678197172285073194125696949924554440256408651
# flag = 14208190311706700229018574851578988188134550363358366844269050987652736462089394391688795530
通过分析代码可知这个程序是将flag进行转换后通过循环取模的方式对flag加密
循环中的公式是标准的lcg(线性同余方法)的形式
X
n
+
1
=
(
a
X
n
+
b
)
m
o
d
m
X_{n+1} = (aX_n + b)\ mod\ m
Xn+1=(aXn+b) mod m
逆推公式的推导过程为
X
n
+
1
=
(
a
X
n
+
b
)
m
o
d
m
⟹
a
X
n
=
(
X
n
+
1
−
b
)
m
o
d
m
⟹
X
n
=
(
a
−
1
X
n
+
1
−
b
)
m
o
d
m
X_{n+1} = (aX_n + b)\ mod\ m \\ \Longrightarrow aX_n=(X_{n+1}-b)\ mod\ m \quad \quad \\ \Longrightarrow X_n=(a^{-1}X_{n+1}-b)\ mod\ m \quad
Xn+1=(aXn+b) mod m⟹aXn=(Xn+1−b) mod m⟹Xn=(a−1Xn+1−b) mod m
故该公式的逆推公式为
X
n
=
(
a
−
1
(
X
n
+
1
−
b
)
)
m
o
d
m
X_n=(a^{-1}(X_{n+1}-b)) \ mod \ m
Xn=(a−1(Xn+1−b)) mod m
其中$ a^{-1} $表示的是a相对于模数m的乘法逆元,即为题中的a相对于n的乘法逆元,这里使用gmpy2模块中的invert函数进行计算。
解题脚本
import libnum
import gmpy2
a = 10580362976768902535288290537881894669438793788144555901400894449594743420700735933898091469
b = 12282491670012215371979074133375864865383435870031708675997502402287216522639028762493710827
n = 15544810823190562032492196545115274631091651502678197172285073194125696949924554440256408651
flag = 14208190311706700229018574851578988188134550363358366844269050987652736462089394391688795530
an = gmpy2.invert(a, n)
for i in range(10):
flag = (an * (flag - b)) % n
print(libnum.n2s(int(flag)))
最后得到flag为flag{90c353c0d77a8d0abfcebffec5c02302}