Mobile wallpaper 1Mobile wallpaper 2Mobile wallpaper 3Mobile wallpaper 4Mobile wallpaper 5Mobile wallpaper 6
635 words
3 minutes
御网杯 2026 复现
2026-06-02
统计加载中...

因为没打御网杯,所以问 Lamb 学妹要了题复现一下看看。

Crypto#

BabyRSA#

题目:

from Crypto.Util.number import bytes_to_long, getPrime
from secret import flag
m = bytes_to_long(flag)
e = 3
p = getPrime(512)
q = getPrime(512)
n = p * q
c = pow(m, e, n)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")

签到题,对c + k * n开三次根找flag就行(本题中直接对c开即可)。

exp.py

from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
n = 106376708471638081356023241888652175743260071488862952322696441188500330953258762786909460198563614242640037648446773201494442383628725589189230563631047713207930813772004230385987574126969015874307576382328088151347177772790519879585263208787209747491607370703131250822062490952064568038598955428368247262989
e = 3
c = 2217344750798176987884922681016983401499645893525707818415742269785793369334864878621546637030713277893458149668533117349008039140359740471790484492703060384410958650758080292114663603623769028805539666282734724093278095429393220973912927452539157520935554837926799000926309
for k in range(10000):
res = iroot(c + k * n, e)
if res[1]:
m = int(res[0])
print(long_to_bytes(m).decode())
break
# flag{01412463306735a1bcace3b5d20293f1}

ScatterRSA#

题目:

from secret import flag
from Crypto.Util.number import *
import random
m = bytes_to_long(flag)
e = 3
print(f"e = {e}")
for i in range(3):
p = getPrime(512)
q = getPrime(512)
n = p * q
a = random.getrandbits(128) | (1 << 127)
b = random.getrandbits(256) | (1 << 255)
c = pow(a * m + b, e, n)
print(f"n{i+1} = {n}")
print(f"a{i+1} = {a}")
print(f"b{i+1} = {b}")
print(f"c{i+1} = {c}")

题目给出三组数据:

ci(aim+bi)e(modni)c_i\equiv (a_i*m+b_i)^e\pmod{n_i}

其中,a为 128-bit,b为 256-bit,e = 3

也就是说我们可以得到三个如下形式且都有一个小根x = m的多项式:

fi(x)=(aix+bi)3cif_i(x)=(a_i*x+b_i)^3-c_i

将其通过CRT合并后得到一个模N = n1 * n2 * n3域下的多项式,此时N很大而x很小,直接 CopperSmith 打出x即可。

exp.py

# SageMath 10.7
from Crypto.Util.number import long_to_bytes
e = 3
n1 = 78406644063412330827144269082165693855524775872040115517201173073443410480229769568274148648378599447340559212013136304104371398343431564153428535062874800376311265127625727766687101716232202416348874941159422385827020377234200304383339914279306109539295055950771168695795983450922479086642719974951568001123
a1 = 179069785188197128063735833062298282088
b1 = 108602310920516135899953625199026479831613528130098983765509775304380481049236
c1 = 63252812179719365415824095661395699873619221281620649284116525456495492657969128347395906262694181920298642514886137258913612425874543244412361141570055505065364160387485022351593955914517007934817693712484398995438325025790526298775819525749798156105149707900940592786793945170245658868658074048714286848360
n2 = 95020468976740939492744504421572718358377589957590862534596426944713745697519407316474954374220717547414847190383624684829981365714162496004205923099654648343561409997185055826399789260059018296236445634896974399171937408534594770556492595577486034736886981715897932731287622893964944487359432563222589773169
a2 = 256937765435419090013996554824329198102
b2 = 106194089384191278641160829411989148866555891040956845008761670010296097473891
c2 = 69189455762124018990354259751049315347885716276141026926254387098606184767677119541615753786850384135301904271598568283598341309350338300849980006939154544582117288358462253645929195237077943587484536869068620740282202954818087710662521305731662434404639604765467522290344380872734642898064819919222866525595
n3 = 76327387850259066558503241279944367595819739218711435387090070188701489593268018671200393965036334822971788731105131043689617213814536539958962946216274727013886635077932479201396877992034094563923228010894175882636493331356330645383301647712606020240651124738679361743860337944932489521911308225518554189671
a3 = 230197610510629587425547735570441529186
b3 = 102036531983721422375656270902750955826372568198958868967463605609586959104862
c3 = 70530911982806921131468678265423284512112079960880985596519011279227498232312624801272691438407551711362218333097001183623780244884146290664329110735889965737872515329899563749587762154521351009913925896897262019326623455825827780598885978929696497223116909384396989202217844912113182815342075250443286215518
N = n1 * n2 * n3
params = [(n1, a1, b1, c1), (n2, a2, b2, c2), (n3, a3, b3, c3)]
R = Zmod(N)['x']
x = R.gen()
coeffs = []
for deg in range(4):
coeffs_mod = []
for n, a, b, c in params:
poly = (a * x + b) ** e - c
coeffs_mod.append(ZZ(poly[deg]) % n)
coeffs.append(crt(coeffs_mod, [n for n, _, _, _ in params]))
f = sum(coeffs[deg] * x ** deg for deg in range(4)).monic()
roots = f.small_roots(X=2**512, beta=0.34, epsilon=0.05)
print(long_to_bytes(ZZ(roots[0])).decode())
# flag{82a05145b36137b03a83e7f0ff974472}

ECDSA#

题目:

{
"public_key_x": 32278952872456905780547099814767063939618086688091564927040207716943270835518,
"public_key_y": 93846569305589930548786857142802880745325076740913072568852571412159575637982,
"message1": "57656c636f6d6520746f2074686520435446206368616c6c656e676521",
"message2": "506c65617365207265636f766572207468652073656372657420666c61672e",
"signature1_r": 42578704313794367821723835270379231244352828328579180961262224566499528870073,
"signature1_s": 61517967644966080965941217493019375085650749498249064881177432677183620596205,
"signature2_r": 42578704313794367821723835270379231244352828328579180961262224566499528870073,
"signature2_s": 20743684232977419667933391628349856033378723646037279217784454422133981848103,
"curve": "SECP256k1"
}

题目名似乎直接说了nonce重用,仔细看看题目数据会发现r也是一样的。从签名公式开始浅推一下:

sk1(z+rd)(modn)s\equiv k^{-1}*(z+r*d)\pmod{n}

k重用时:

s1k1(z1+rd)(modn)s2k1(z2+rd)(modn)\begin{aligned} s_1\equiv k^{-1}*(z_1+r*d)\pmod{n}\\ s_2\equiv k^{-1}*(z_2+r*d)\pmod{n} \end{aligned}

两式相减:

k(z1z2)(s1s2)1(modn)k\equiv (z_1-z_2)*(s_1-s_2)^{-1}\pmod{n}

再代回任一签名等式即可恢复私钥:

d(sikzi)r1(modn)d\equiv(s_i*k-z_i)*r^{-1}\pmod{n}

exp.py

from hashlib import sha256
from Crypto.Util.number import inverse
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
public_key_x = 32278952872456905780547099814767063939618086688091564927040207716943270835518
public_key_y = 93846569305589930548786857142802880745325076740913072568852571412159575637982
message1 = "57656c636f6d6520746f2074686520435446206368616c6c656e676521"
message2 = "506c65617365207265636f766572207468652073656372657420666c61672e"
signature1_r = 42578704313794367821723835270379231244352828328579180961262224566499528870073
signature1_s = 61517967644966080965941217493019375085650749498249064881177432677183620596205
signature2_r = 42578704313794367821723835270379231244352828328579180961262224566499528870073
signature2_s = 20743684232977419667933391628349856033378723646037279217784454422133981848103
z1 = int(sha256(bytes.fromhex(message1)).hexdigest(), 16)
z2 = int(sha256(bytes.fromhex(message2)).hexdigest(), 16)
k = (z1 - z2) * inverse(signature1_s - signature2_s, n) % n
d = (signature1_s * k - z1) * inverse(signature1_r, n) % n
flag = f"flag{{ecdsa_nonce_reuse_{hex(d)[2:][:32]}}}"
print(flag)
# flag{ecdsa_nonce_reuse_d35fe9a03a2162fd5441bb19346d95fd}

ECB#

网上找到的wp传送门,神题我只能说。

exp.py

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
c = open("ciphertext.bin", "rb").read()
key = b'VERY_SECRET_KEY!'
cipher = AES.new(key, AES.MODE_ECB)
m = unpad(cipher.decrypt(c), 16).decode()
print(m)
# CTF{SECRET_FLAG:flag{c2jqvo7s6dfnkjuobt1x7hfksa9cp7pu}}END_OF_FLAG
御网杯 2026 复现
https://q1uju.cc/posts/御网杯2026复现/
Author
Q1uJu
Published at
2026-06-02
License
CC BY-NC-SA 4.0

Some information may be outdated