from PIL import Image import os defextract_rgb_to_hex_reverse(image_path, output_path): # 打开图像并转换为 RGB 模式 img = Image.open(image_path).convert('RGB') # 提取所有像素的 RGB 值 pixels = list(img.getdata()) # 转换为十六进制字符串并逆序 hex_colors = ['{:02x}{:02x}{:02x}'.format(r, g, b) for r, g, b in pixels] hex_colors.reverse() # 写入文本文件 with open(output_path, 'w') as f: for hex_color in hex_colors: f.write(hex_color + 'n') print(f'[+] 十六进制数据已保存到: {output_path}') # 示例用法 if __name__ == '__main__': extract_rgb_to_hex_reverse('瓦学弟天天开心.png', 'rgb_hex_data.txt')
img
数据整合成压缩包,利用密码解码
best_FPS_g@me!!}
img
只有一半flag
拼在一起
flag{Val0rant_1s_th3_best_FPS_g@me!!}
Cry
dp
出题人说dp都不会打什么密码? n = 110231451148882079381796143358970452100202953702391108796134950841737642949460527878714265898036116331356438846901198470479054762675790266666921561175879745335346704648242558094026330525194100460497557690574823790674495407503937159099381516207615786485815588440939371996099127648410831094531405905724333332751 dp = 3086447084488829312768217706085402222803155373133262724515307236287352098952292947424429554074367555883852997440538764377662477589192987750154075762783925 c = 59325046548488308883386075244531371583402390744927996480498220618691766045737849650329706821216622090853171635701444247741920578127703036446381752396125610456124290112692914728856924559989383692987222821742728733347723840032917282464481629726528696226995176072605314263644914703785378425284460609365608120126 e = 65537
dp泄露模板梭了
img
flag:flag{C5G0_1s_the_8eSt_FPS_G@m3}
ezRSA
from sympy import factorint, mod_inverse # 参数 e = 65537 n = 1000000000000000000000000000156000000000000000000000000005643 c = 418535905348643941073541505434424306523376401168593325605206 # 分解 n factors = factorint(n) print('[*] 分解结果:', factors) # 检查是否只分解成两个素数 if len(factors) == 2: p, q = list(factors.keys()) phi = (p - 1) * (q - 1) d = mod_inverse(e, phi) m = pow(c, d, n) print('[*] 明文 m:', m) try: print('[*] 解码:', bytes.fromhex(hex(m)[2:]).decode()) except: print('[*] 无法直接转成字符串') else: print('[!] n 并不是两个素数的乘积')
defdecrypt(ciphertext: str, num_columns: int) -> str: num_rows = (len(ciphertext) + num_columns - 1) // num_columns # 初始化矩阵,先用空格填充 grid = [[' 'for _ in range(num_columns)] for _ in range(num_rows)] index = 0 # 按列优先顺序填充密文字符 for col in range(num_columns): for row in range(num_rows): if index < len(ciphertext): grid[row][col] = ciphertext[index] index += 1 # 按行优先顺序读取矩阵 plaintext = '' for row in range(num_rows): for col in range(num_columns): plaintext += grid[row][col] return plaintext.rstrip() decrypted_text = decrypt('ntid c{}rShcljrko od lc WYicO',5) print(decrypted_text) decrypted_text = decrypt(decrypted_text,4) print(decrypted_text)
img
接着通过维吉尼亚解密
img
接着是仿射密码解密
img
然后是单表替换,这里大小写没转换成功,手动转一下结果
img
结果看起来很像凯撒,直接凯撒解密
img
flag{nxtcNBflagNBctfflag}
babyrsa
分析代码,发现生成的素数p+1光滑,用Williams的p+1算法分解得到p1,q1
from Cryptodome.Util.number import * from gmpy2 import * from itertools import count n = 151767047787614712083974720416865469041528766980347881592164779139223941980832935534609228636599644744364450753148219193621511377088383418096756216139022880709 e = 65537 c = 26971181342240802276810747395669930355754928952080329914687241779532014305320191048439959934699795162709365987652696472998140484810728817991804469778237933925 defmlucas(v, a, n): v1, v2 = v, (v ** 2 - 2) % n for bit in bin(a)[3:]: v1, v2 = ((v1 ** 2 - 2) % n, (v1 * v2 - v) % n) if bit == '0'else ( (v1 * v2 - v) % n, (v2 ** 2 - 2) % n) return v1 defprimegen(): yield2 yield3 yield5 yield7 yield11 yield13 ps = primegen() # yay recursion p = ps.__next__() and ps.__next__() q, sieve, n = p ** 2, {}, 13 whileTrue: if n notin sieve: if n < q: yield n else: next, step = q + 2 * p, 2 * p while next in sieve: next += step sieve[next] = step p = ps.__next__() q = p ** 2 else: step = sieve.pop(n) next = n + step while next in sieve: next += step sieve[next] = step n += 2 defilog(x, b):# greatest integer l such that b**l <= x. l = 0 while x >= b: x /= b l += 1 return l defattack(n): for v in count(1): for p in primegen(): e = ilog(isqrt(n), p) if e == 0: break for _ in range(e): v = mlucas(v, p, n) g = gcd(v - 2, n) if1 < g < n: return int(g), int(n // g) # g|n if g == n: break p1, q1 = attack(n) print(p1) print(q1)
然后求e打boneh-durfee即可
p1=647625598040937990477179775340017395831855498212348808173836982264933068647233 q1=234343806431846981391062476356400447729334179333927516463017977438646752515331973 c1 = 6701513605196718137208327145211106525052740242222174201768345944717813148931922063338128366155730924516887607710111701686062781667128443135522927486682574 e=c1-p1 print(e) n = 10037257627154486608196774801095855162090578704439233219876490744017222686494761706171113312036056644757212254824459536550416291797454693336043852190135363 c = 6723803125309437675713195914771839852631361554645954138639198200804046718848872479140347495288135138109762940384847808522874831433140182790750890982139835 from __future__ import print_function import time ############################################ # Config ########################################## ''' Setting debug to true will display more informations about the lattice, the bounds, the vectors... ''' debug = True ''' Setting strict to true will stop the algorithm (and return (-1, -1)) if we don't have a correct upperbound on the determinant. Note that this doesn't necesseraly mean that no solutions will be found since the theoretical upperbound is usualy far away from actual results. That is why you should probably use `strict = False` ''' strict = False ''' This is experimental, but has provided remarkable results so far. It tries to reduce the lattice as much as it can while keeping its efficiency. I see no reason not to use this option, but if things don't work, you should try disabling it ''' helpful_only = True dimension_min = 7# stop removing if lattice reaches that dimension ############################################ # Functions ########################################## # display stats on helpful vectors defhelpful_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') # display matrix picture with 0 and X defmatrix_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] == 0else'X' if BB.dimensions()[0] < 60: a += ' ' if BB[ii, ii] >= bound: a += '~' print(a) # tries to remove unhelpful vectors # we start at current = n-1 (last vector) defremove_unhelpful(BB, monomials, bound, current): # end of our recursive function if current == -1or BB.dimensions()[0] <= dimension_min: return BB # we start by checking from the end for ii in range(current, -1, -1): # if it is unhelpful: if BB[ii, ii] >= bound: affected_vectors = 0 affected_vector_index = 0 # let's check if it affects other vectors for jj in range(ii + 1, BB.dimensions()[0]): # if another vector is affected: # we increase the count if BB[jj, ii] != 0: affected_vectors += 1 affected_vector_index = jj # level:0 # if no other vectors end up affected # we remove it 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 # level:1 # if just one was affected we check # if it is affecting someone else elif affected_vectors == 1: affected_deeper = True for kk in range(affected_vector_index + 1, BB.dimensions()[0]): # if it is affecting even one vector # we give up on this one if BB[kk, affected_vector_index] != 0: affected_deeper = False # remove both it if no other vector was affected and # this helpful vector is not helpful enough # compared to our unhelpful one 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 if `strict=true`, and determinant doesn't bound * x0,y0 the solutions of `pol` ''' defboneh_durfee(pol, modulus, mm, tt, XX, YY): ''' Boneh and Durfee revisited by Herrmann and May finds a solution if: * d < N^delta * |x| < e^delta * |y| < e^0.5 whenever 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-shifts 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-shifts list of monomials monomials = [] for polynomial in gg: for monomial in polynomial.monomials(): if monomial notin monomials: monomials.append(monomial) monomials.sort() # y-shifts (selected by Herrman and May) 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-shifts list of monomials for jj in range(1, tt + 1): for kk in range(floor(mm / tt) * jj, mm + 1): monomials.append(u ^ kk * y ^ jj) # construct lattice 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) # Prototype to reduce the lattice if helpful_only: # automatically remove BB = remove_unhelpful(BB, monomials, modulus ^ mm, nn - 1) # reset dimension nn = BB.dimensions()[0] if nn == 0: print('failure') return0, 0 # check if vectors are helpful if debug: helpful_vectors(BB, modulus ^ mm) # check if determinant is correctly bounded 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.LLL() if debug: print('LLL is done!') # transform vector i & j -> polynomials 1 & 2 if debug: print('looking for independent vectors in the lattice') found_polynomials = False for pol1_idx in range(nn - 1): for pol2_idx in range(pol1_idx + 1, nn): # for i and j, create the two polynomials 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) # resultant PR.<q> = PolynomialRing(ZZ) rr = pol1.resultant(pol2) # are these good polynomials? 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 ifnot found_polynomials: print('no independant vectors could be found. This should very rarely happen...') return0, 0 rr = rr(q, q) # solutions soly = rr.roots() if len(soly) == 0: print('Your prediction (delta) is too small') return0, 0 soly = soly[0][0] ss = pol1(q, soly) solx = ss.roots()[0][0] # return solx, soly defexample(): ############################################ # How To Use This Script ########################################## # # The problem to solve (edit the following values) # # the modulus N = 10037257627154486608196774801095855162090578704439233219876490744017222686494761706171113312036056644757212254824459536550416291797454693336043852190135363 # the public exponent e =6701513605196718137208327145211106525052740242222174201768345944717813148931274437740087428165253744741547590314279846187850432858954606153257994418035341 # the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = .25# this means that d < N^delta # # Lattice (tweak those values) # # you should tweak this (after a first run), (e.g. increment it until a solution is found) m = 4# size of the lattice (bigger the better/slower) # you need to be a lattice master to tweak these t = int((1 - 2 * delta) * m) # optimization from Herrmann and May X = 2 * floor(N ^ delta) # this _might_ be too much Y = floor(N ^(1/2)) # correct if p, q are ~ same size # # Don't touch anything below # # Problem put in equation P.<x,y> = PolynomialRing(ZZ) A = int((N + 1) / 2) pol = 1 + x * (A + y) # # Find the solutions! # # Checking bounds if debug: print('=== checking values ===') print('* delta:', delta) print('* delta < 0.292', delta < 0.292) print('* size of e:', int(log(e) / log(2))) print('* size of N:', int(log(N) / log(2))) 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) # found a solution? if solx > 0: print('=== solution found ===') ifFalse: print('x:', solx) print('y:', soly) d = int(pol(solx, soly) / e) print('private key found:', d) else: print('=== no solution was found ===') if debug: print(('=== %s seconds ===' % (time.time() - start_time))) if __name__ == '__main__': example()
解RSA
from Cryptodome.Util.number import long_to_bytes d=1322874566486382881454604115011030734869 n = 10037257627154486608196774801095855162090578704439233219876490744017222686494761706171113312036056644757212254824459536550416291797454693336043852190135363 c = 6723803125309437675713195914771839852631361554645954138639198200804046718848872479140347495288135138109762940384847808522874831433140182790750890982139835 m=pow(c,d,n) print(long_to_bytes(m))