D^3CTF 2022
D^3CTF
赛题质量很高,题目都设计的很好呀,前三道是比较简单的,另外三道有点难,照着官方wp复现一部分
d3factor
from Crypto.Util.number import bytes_to_long, getPrime
from secret import msg
from sympy import nextprime
from gmpy2 import invert
from hashlib import md5
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
p = getPrime(256)
q = getPrime(256)
assert p > q
n = p * q
e = 0x10001
m = bytes_to_long(msg)
c = pow(m, e, n)
N = pow(p, 7) * q
phi = pow(p, 6) * (p - 1) * (q - 1)
d1 = getPrime(2000)
d2 = nextprime(d1 + getPrime(1000))
e1 = invert(d1, phi)
e2 = invert(d2, phi)
print(f'c = {c}')
print(f'N = {N}')
print(f'e1 = {e1}')
print(f'e2 = {e2}')
'''
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
'''
d2比d1大1000bits的样子,与d1的比特数差的有点多,考虑构造关于差值的等式进行copper
消掉d1后得到式子\(e_1e_2x-(e_1-e_2)=0mod(phi)\)
注意到phi与N均含有p6=>p6>N3/4
取beta=0.75即可,epsilon的约束比较宽松
"""
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
PR.<x>=PolynomialRing(Zmod(N))
f=e1*e2*x-(e1-e2)
f=f.monic()
root=f.small_roots(X=2^1020,beta=0.75,epsilon=0.05)
print(e1*e2*root[0]-(e1-e2))
#output: 5498330243880825560336478154736411141592210908996313792046872054395398976679658325464312879090781305712698211596905825314106279441934035902545571237383430582051583244045985067458074575709473242707792625147725353815630560698228239913024228898186759660641368985679517024637086608415503468609683417679307728323433958210505654874722780394972014173838885916015811709092514670099647558318976889851674968105042856608773879099153620896269003572797579241474129549520952511194990317515806784426147925237659681587436469337994396402152317182880013883191329924124799500677464595648928836140539357418053230423056611355264914728
"""
import gmpy2
from Crypto.Util.number import *
from hashlib import md5
t=5498330243880825560336478154736411141592210908996313792046872054395398976679658325464312879090781305712698211596905825314106279441934035902545571237383430582051583244045985067458074575709473242707792625147725353815630560698228239913024228898186759660641368985679517024637086608415503468609683417679307728323433958210505654874722780394972014173838885916015811709092514670099647558318976889851674968105042856608773879099153620896269003572797579241474129549520952511194990317515806784426147925237659681587436469337994396402152317182880013883191329924124799500677464595648928836140539357418053230423056611355264914728
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
p=gmpy2.iroot(gmpy2.gcd(t,N),6)[0]
q=N//(p**7)
d=gmpy2.invert(0x10001,(p-1)*(q-1))
msg=long_to_bytes(pow(c,d,p*q))
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
print(flag)
d3qcg
from Crypto.Util.number import *
import random
from random import randint
from gmpy2 import *
from secret import flag
import hashlib
assert b'd3ctf' in flag
Bits = 512
UnKnownBits = 146
class QCG():
def __init__(self,bit_length):
p = getPrime(bit_length)
a = randint(0,p)
c = randint(0,p)
self._key = {'a':a,'c':c,'p':p}
self.secret = randint(0,p)
self.high = []
def Qnext(self,num):
return ((self._key['a'])*num**2+self._key['c'])%self._key['p']
def hint(self):
num = self.secret
for i in range(2):
num = self.Qnext(num)
self.high.append(num>>UnKnownBits)
def get_key(self):
return self._key
def get_hint(self):
return self.high
Q1 = QCG(Bits)
print(Q1.get_key())
#{'a': 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101, 'c': 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833, 'p': 7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347}
Q1.hint()
print(Q1.get_hint())
#[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
enc = bytes_to_long(hashlib.sha512(b'%d'%(secret)).digest())^bytes_to_long(flag)
print(enc)
# 6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125
QCG即Quadratic congruence generator
注意到题目输出时会截断低146位,设截断位为x,y,根据递推构造函数多元copper即可
import itertools
def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree()
R = f.base_ring()
N = R.cardinality()
f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)
G = Sequence([], f.parent())
for i in range(m+1):
base = N^(m-i) * f^i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1/factor)
H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B*monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []
a= 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c=6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
h=[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
h[0]=h[0]<<146
h[1]=h[1]<<146
PR.<x,y>=PolynomialRing(Zmod(p))
f=a*(h[0]+x)^2+c-h[1]-y
bounds=(2^146,2^146)
print(small_roots(f,bounds,m=3,d=4))
#------
import gmpy2
a=3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c= 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
h=[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
t=50712831100361370819145886978385347931029768
pad1=(h[0]<<146)+t
s2=(pad1-c)*gmpy2.invert(a,p)%p
print(s2)
#------
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
ss=4508722024464242774844580634679202019739970390460001982611686314565408465605990967298630328780463883701424894922522261864494015405770113222925776958816402
PR.<x>=PolynomialRing(Zmod(p))
f=x^2-ss
print(f.roots())
#------
import hashlib
from Crypto.Util.number import *
enc=6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125
s2=3345361405203462981041847914374453868599106060665812229784462734764742247048957655005612474587555839753748604882708741687926147536458567411789178129398205
flag =long_to_bytes(bytes_to_long(hashlib.sha512(b'%d'%(s2)).digest())^enc)
print(flag)
比赛的时候还了解了一下二次生成器的一些攻击(paper提供的是一种更强的对于QCG的攻击方式)
照着paper的方向自己实现了一下CVP,只能说数据还是差了一点,paper采用的SVP,后面一部分实在看不下去了,仅作参考吧,以后有时间再来看看
d3bug
from Crypto.Util.number import *
from secret import flag
assert flag.startswith("D3CTF{")
assert flag.endswith("}")
message = bytes_to_long(flag[6:-1])
assert message < 2**64
mask = 0b1010010000001000000010001001010010100100000010000000100010010100
def lfsr_MyCode(R,mask):
output = (R << 1) & 0xffffffffffffffff
i = (R ^ mask) & 0xffffffffffffffff
lastbit = 0
while i != 0:
lastbit ^= (i & 1)
i = i>>1
output ^= lastbit
return (output,lastbit)
def lfsr_CopiedfromInternet(R,mask):
output = (R << 1) & 0xffffffffffffffff
i = (R & mask) & 0xffffffffffffffff
lastbit = 0
while i != 0:
lastbit ^= (i & 1)
i = i>>1
output ^= lastbit
return (output,lastbit)
f=open("standardResult","w")
R=message
for i in range(35):
(R, out) = lfsr_CopiedfromInternet(R,mask)
f.write(str(out))
f.close()
f=open("myResult","w")
R=message
for i in range(35):
(R, out) = lfsr_MyCode(R,mask)
f.write(str(out))
f.close()
#Why are the results always different?!!
#Can you help me debug my code? QAQ
首先推lfsr_MyCode的规律,可以看作是在模2下各位相加再加上mask的各位相加,由于mask有偶数个1故无需考虑
观察MyCode的输出流,即状态为偶数个1时输出0,奇数个1时输出1,刚开始状态为偶数个1,则输出0
在状态向左平移的过程中,若去掉0,下一次输出仍为0,若为1下一次输出则为1,由此可知MyCode的第2~35位输出是seed的前34位
我们又已知标准lfsr的前35位输出,对已知的共69位lfsr的比特位还原,在尝试的过程中我尽可能地拟合seed的前34位数据后面的数据用已知标准输出填充,得到的结构用两种lfsr输出,看是否一致即可
mask='1010010000001000000010001001010010100100000010000000100010010100'
sign1='0100110001000110001101010101001001'
sign2='01111101111010111000010010111001101'
v=[]
A=Matrix.zero(64)
for i in range(63):
A[i,i+1]=1
for i in range(64):
A[63,i]=int(mask[i])
v.append(int(mask[i]))
A=Matrix(GF(2),A)
v=vector(GF(2),v)
T=Matrix.zero(64)
for i in range(34):
T[i,i]=1
for i in range(30):
temp=v*A^i
T[i+34]=temp
T=Matrix(GF(2),T)
vv=[]
for i in range(34):
vv.append(int(sign1[i]))
for i in range(30):
vv.append(int(sign2[i]))
vv=vector(GF(2),vv)
s=T^(-1)*vv
s=list(s)
for i in range(len(s)):
print(s[i],end='')
equivalent
from collections import namedtuple
from Crypto.Util import number
from Crypto.Random import random
PublicKey = namedtuple('PublicKey', ['a'])
SecretKey = namedtuple('SecretKey', ['s', 'e', 'p'])
def keygen(sbit, N):
s_ = [random.getrandbits(sbit) | 1 for _ in range(N)]
pbit = sum(s_).bit_length() + 1
p = number.getPrime(pbit)
while not (sum(s_) < p < 2*sum(s_)):
p = number.getPrime(pbit)
e = random.randint(p//2, p-1)
a_ = [e*s_i % p for s_i in s_]
assert 2**N > max(a_)
pk = PublicKey(a_)
sk = SecretKey(s_, e, p)
return (pk, sk)
def enc(m, pk):
assert 0 <= m < 2
n = len(pk.a)
r_ = [random.getrandbits(1) for _ in range(n-1)]
r_n = (m - sum(r_)) % 2
r_.append(r_n)
c = sum(a_i*r_i for a_i, r_i in zip(pk.a, r_))
return c
def dec(c, sk):
e_inv = number.inverse(sk.e, sk.p)
m = (e_inv * c % sk.p) % 2
return m
def encrypt(msg, pk):
bits = bin(number.bytes_to_long(msg))[2:]
cip = [enc(m, pk) for m in map(int, bits)]
return cip
def decrypt(cip, sk):
bits = [dec(c, sk) for c in cip]
msg = number.long_to_bytes(int(''.join(map(str, bits)), 2))
return msg
if __name__ == "__main__":
from secret import FLAG
pk, sk = keygen(sbit=80, N=100)
msg = FLAG.removeprefix(b"d3ctf{").removesuffix(b"}")
cip = encrypt(msg, pk)
assert msg == decrypt(cip, sk)
with open("data.txt", 'w') as f:
f.write(f"pk = {pk}\n")
f.write(f"cip = {cip}\n")
一开始就一直在做这个,开始以为就是个简单的背包变形,发现LLL和BKZ都没法解决问题的时候我就觉得估计又是哪篇paper的attack了
属实看着有点懵,又重新看了一下knapsack才知道我之前了解的直接LLL的攻击只能对低密度背包使用
Knapsack系统的密度为\(d=\frac{n}{log_2(max\{a_i\})}\)(ai为公钥)
paper提供的应该是对一种高密度背包的攻击
格学的还是不太行,有些地方看不太明白
只能先放着了,下次一定复现😢
leak_dsa
from hashlib import sha256
from secret import flag
from Crypto.Util.number import *
from random import *
import os
from binascii import *
def gen_key(qbit , pbit):
q = getPrime(qbit)
while 1:
p = getrandbits(pbit-qbit)*q + 1
if isPrime(p):
break
while 1:
h = randint(1 , p)
g = pow(h , (p-1)//q , p)
if g != 1:
break
d = randint(1 , q-1)
y = pow(g,d,p)
pubkey = (p ,q , g ,y)
prikey = (p ,q ,g ,y , d)
return pubkey , prikey
def sign(prikey , m):
p,q,g,y,d = prikey
k = randint(1 , q-1)
r = pow(g , k , p) % q
s = inverse(k , q) * (int(sha256(m).hexdigest(),16)+ d * r) % q
return (r , s) , k
def verify(pubkey , m , r ,s ):
p,q,g,y = pubkey
w = inverse(s , q)
u1 = int(sha256(m).hexdigest(),16) * w % q
u2 = r * w % q
if r == pow(g , u1 , p)*pow(y , u2,p)% q:
return 1
return 0
N = 70
pubkey , prikey = gen_key(256 , 2048)
f = open('./cipher.txt' , 'w')
f.write(str(pubkey) + '\n')
for i in range(N):
m = os.urandom(10)
signature , gift = sign(prikey , m)
mask = getrandbits(256)
f.write(hexlify(m).decode() + ',' + str(signature) +',' +str(mask & gift) +','+ str(mask) + '\n')
assert flag[:6] == b'd3ctf{' and flag[-1:] == b'}'
assert flag[6:-1] == sha256(str(prikey[-1]).encode()).hexdigest()
先了解一下HNP问题
大概就是解一系列具有模糊变量的一元一次模方程组
即Aix+Bi=kimod(N)
其中我们不知道具体的ki但是我们知道ki的比特数
不妨设比特数为K
构造格
\(L=\left[\begin{matrix}N&\\&N\\&&N\\&&&N\\...\\&&&&&N\\A_1&A_2&A_3&A_4&...&A_t&K/N\\B_1&B_2&B_3&B_4&...&B_t&&K\end{matrix}\right]\)
可知向量(k1 k2 ... kt \(\frac{Kx}{N}\) K)在格L上
可以证明的是当ki不大且获取数据组t较大时我们可以使用LLL找到该向量,从而解出x
回到该问题,由于题目并没有给出我们k的比特数,但是给出了多组签名,并且给了k的随机掩码位的值,根据wp我们要做的是将此问题划归到解HNP上
一开始看wp看着是真头疼,后来问了一下出题人就勉勉强强能够想明白了,这里记录一下大致思路
首先我们得到了k&mask的信息,也就是k的部分bits,那我们如何利用这个信息划归到hnp呢
设k=k&mask+∑ki2ti(ki是mask中的两个1之间的位置bits)
构造格
\(L=\left[\begin{matrix}q\\&q\\&&q\\...\\&&&&q\\2^{t_0}&2^{t_1}&2^{t_2}&...&2^{t_s}\end{matrix}\right]\)
通过对L使用LLL算法求得一个最短向量v
即gL[-1]mod(q)=v,把g求出来
规约的时候可以和wp一样在两边配一个平衡矩阵
于是我们对\(∑k_i2^{ti}\)乘以g可以使得其尽可能的小,通过实验可以发现大约在251bits,这样就可以使用hnp进行问题的解决了
=>\(k=k\&mask+∑k_i2^{ti}=s^{-1}h+s^{-1}rx\)
=>\(∑k_i2^{ti}=s^{-1}h+s^{-1}rx-k\&mask\)
=>\(g(s^{-1}h+s^{-1}rx-k\&mask)=g∑k_i2^{ti}\)~251bits
于是\(A=gs^{-1}r;B=g(s^{-1}h-k\&mask)\)
Ax+B=V(modq)其中V大约为251bits
利用所给数据求出多组A,B最后解个HNP问题即可
代码实现由于还有些细节没整明白就先咕咕咕了
这个是shallow的github上的代码shallow
d3share
#!sage
import random
from hashlib import sha256
from Crypto.Util.number import *
class KeyPredistribution:
# a key predistribution scheme in 《A Random Perturbation-Based Scheme for Pairwise Key Establishment in Sensor Networks》
def __init__(self ,p , t ,r , N):
self.p = p
self.t = t
self.r = r
self.N = N
self.F = self.random_symmetric_polynomial()
self.random_perturbation_polynomials()
def random_symmetric_polynomial(self):
P = PolynomialRing(GF(self.p) , "x,y")
x , y = P.gens()
F = 0
for i in range(self.t+1):
for j in range(self.t+1):
r = GF(self.p).random_element()
F += r * x^i * y^j +r * y^i * x^j
return F
def random_perturbation_polynomials(self):
P = PolynomialRing(GF(self.p) , 'y')
g = P.random_element(degree = self.t , total = self.t+1)
h = P.random_element(degree = self.t , total = self.t+1)
S = []
while len(S) < self.N:
e = GF(self.p).random_element()
if e not in S:
if g(e) < self.r and h(e) < self.r:
S.append(e)
self.g = g
self.h = h
self.S = S
def get_node(self, index):
if index > len(self.S):
print("index out of range")
return 0
xi = self.S[index]
_ , y = self.F.parent().gens()
f = self.F(xi , y)
r = random.randint(0 , 1)
f += r*self.g + (1-r)*self.h
pubkey = xi
prikey = f
return (pubkey , prikey)
def share_secret(a_prikey , b_pubkey , r):
f = a_prikey
xj = b_pubkey
share = f(xj) >> (int(log(r , 2))+1)
return share, sha256(share)
p = 2**48 - 59
r = 2**38
t = 40
n = 43
KP = KeyPredistribution(p , t ,r , n)
hint = KP.F(0,0)
# hint = 35327434352315
f = open('./data.txt' , 'w')
for i in range(n):
node = KP.get_node(i)
f.write(str(node) + '\n')
f.close()
flag = 'd3ctf{' + sha256(b''.join([long_to_bytes(int(i)) for i in KP.F.coefficients()])).hexdigest() + '}'
print(flag)
似乎是实现一个新的加密体制,不想再看paper了,留给以后复现吧🏃
wait for update

浙公网安备 33010602011771号