window.onload=function(){ /*页面加载完成之后生成博客目录*/ BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); }

DASCTF 2023 & 0X401七月暑期挑战赛——ezAlgebra

1、题目描述:

题目代码
from Crypto.Util.number import getPrime, bytes_to_long

def YiJiuJiuQiNian(Wo, Xue, Hui, Le, Kai):
    Qi = 1997
    Che = Wo+Hui if Le==1 else Wo*Hui
    while(Xue):
        Qi += (pow(Che, Xue, Kai)) % Kai
        Xue -= 1
    return Qi
    
l = 512
m = bytes_to_long(flag)
p = getPrime(l)
q = getPrime(l//2)
r = getPrime(l//2)
n = p * q * r
t = getrandbits(32)
c1 = YiJiuJiuQiNian(t, 4, p, 1, n)
c2 = YiJiuJiuQiNian(m, 19, t, 0, q)
c3 = YiJiuJiuQiNian(m, 19, t, 1, q)
print(f"n = {n}")
print(f"c1 = {c1}")
print(f"c2 = {c2}")
print(f"c3 = {c3}")

"""
n = 119156144845956004769507478085325079414190248780654060840257869477965140304727088685316579445017214576182010373548273474121727778923582544853293534996805340795355149795694121455249972628980952137874014208209750135683003125079012121116063371902985706907482988687895813788980275896804461285403779036508897592103
c1 = 185012145382155564763088060801282407144264652101028110644849089283749320447842262397065972319766119386744305208284231153853897076876529326779092899879401876069911627013491974285327376378421323298147156687497709488102574369005495618201253946225697404932436143348932178069698091761601958275626264379615139864425
c2 = 722022978284031841958768129010024257235769706227005483829360633993196299360813
c3 = 999691052172645326792013409327337026208773437618455136594949462410165608463231
"""

2、题目分析:

先简化一下:
n = p q r

c 1 = ( t + p ) ^4 + ( t + p )^ 3 + ( t + p ) ^2 + ( t + p ) + 1997 ( m o d n )

c 2 = ( m t ) ^19 + ( m t ) ^18 + ⋯ + ( m t ) ^2 + ( m t ) + 1997 ( m o d q )

c 3 = ( m + t ) ^19 + ( m + t ) ^18 + ⋯ + ( m + t ) + 1997 ( m o d q )

已知 n , c 1 , c 2 , c 3 , 求 m

c 1 = t^ 4 + t ^3 + t ^2 + t + 1997 ( m o d p ) = >

k p = c 1 − ( t ^4 + t^ 3 + t^ 2 + t + 1997 )

联想到 p 的高位攻击

此处相当于高位已知,求低位, c o p p e r 解未知数 t

求出后带入原式, g c d ( k p , n ) 求出 p

# sage
from Crypto.Util.number import *
n =  119156144845956004769507478085325079414190248780654060840257869477965140304727088685316579445017214576182010373548273474121727778923582544853293534996805340795355149795694121455249972628980952137874014208209750135683003125079012121116063371902985706907482988687895813788980275896804461285403779036508897592103
c1 = 185012145382155564763088060801282407144264652101028110644849089283749320447842262397065972319766119386744305208284231153853897076876529326779092899879401876069911627013491974285327376378421323298147156687497709488102574369005495618201253946225697404932436143348932178069698091761601958275626264379615139864425
c2 = 722022978284031841958768129010024257235769706227005483829360633993196299360813
c3 = 999691052172645326792013409327337026208773437618455136594949462410165608463231
PR.<x> = PolynomialRing(Zmod(n))
f = x ^ 4 + x ^ 3 + x ^ 2 + x + 1997 - c1
t = f.small_roots(X = 2 ^ 32,beta = 0.4)[0]
# print(t)
t = 2915836867
kp = t ^ 4 + t ^ 3 + t ^ 2 + t + 1997 - c1
p = gcd(kp,n)
qr = n // p

观察到

c2​=(mt)^19+(mt)^18+⋯+(mt)^2+(mt)+1997(modq)

c3​=(m+t)^19+(m+t)^18+⋯+(m+t)+1997(modq)

这形式不跟题二差不多,不过是项数多了点

但(x−m)还是c2​,c3​的解,公因子还是(x−m)

可利用groebner_basis()求出q(理解groebner_basis()可参考此文章https://zhuanlan.zhihu.com/p/278946425

个人理解:打印出的结果是多项式的解集,最后的那位纯数字是多项式理想G所对应的代数集合的维度,即所生成的代数集合中的点的个数,正好可对应于q。

在上述代码基础上添加

P.<x,y> = PolynomialRing(Zmod(n))
f1 = 1997 - c3
f2 = 1997 - c2
for i in range(1,20):
    f1 += (x + t)^i
    f2 += (x * t)^i
G = [f1,f2]
B = Ideal(G).groebner_basis()
res = [x.constant_coefficient() for x in B]
q = res[1]
m = -res[0] % q
print(m)
print(q)

求出m转字符,发现得不到结果,结果是m % q,猜测比q大,爆破一下。爆破结果是以小写dasctf开头,上传的答案又要求大写DASCTF。

q = 87038069032840052005520908272237788908169043580221040711149494083975743478969
x = 56985796272753226120469211992443340429346162287195965942430959147227534853120
for i in range(10000000):
    flag = long_to_bytes(x + i * q)
    if b'dasctf' in flag :
        print(flag)
        print(i)
# dasctf{ShangPoXiaPoYaSiLeYiQianDuo} 
# i = 8751845 24bits

完整exp:

# sage
from Crypto.Util.number import *
n =  119156144845956004769507478085325079414190248780654060840257869477965140304727088685316579445017214576182010373548273474121727778923582544853293534996805340795355149795694121455249972628980952137874014208209750135683003125079012121116063371902985706907482988687895813788980275896804461285403779036508897592103
c1 = 185012145382155564763088060801282407144264652101028110644849089283749320447842262397065972319766119386744305208284231153853897076876529326779092899879401876069911627013491974285327376378421323298147156687497709488102574369005495618201253946225697404932436143348932178069698091761601958275626264379615139864425
c2 = 722022978284031841958768129010024257235769706227005483829360633993196299360813
c3 = 999691052172645326792013409327337026208773437618455136594949462410165608463231
PR.<x> = PolynomialRing(Zmod(n))
f = x ^ 4 + x ^ 3 + x ^ 2 + x + 1997 - c1
t = f.small_roots(X = 2 ^ 32,beta = 0.4)[0]
# print(t)
t = 2915836867
kp = t ^ 4 + t ^ 3 + t ^ 2 + t + 1997 - c1
p = gcd(kp,n)
qr = n // p

P.<x,y> = PolynomialRing(Zmod(n))
f1 = 1997 - c3
f2 = 1997 - c2
for i in range(1,20):
    f1 += (x + t)^i
    f2 += (x * t)^i
G = [f1,f2]
B = Ideal(G).groebner_basis()
res = [x.constant_coefficient() for x in B]
q = res[1]
m = -res[0] % q
print(m)
print(q)

q = 87038069032840052005520908272237788908169043580221040711149494083975743478969
x = 56985796272753226120469211992443340429346162287195965942430959147227534853120
for i in range(10000000):
    flag = long_to_bytes(x + i * q)
    if b'dasctf' in flag :
        print(flag)
        print(i)
# dasctf{ShangPoXiaPoYaSiLeYiQianDuo} 
# i = 8751845 24bits

 

posted @ 2023-08-10 20:40  Kicky_Mu  阅读(100)  评论(0编辑  收藏  举报