前言
lj比赛,lj题目,场景题不会出就别出,出的跟musc脑电波一样,只写几题wp
题目
babyrsa
task.py
from Crypto.Util.number import *import decimalm=long_to_bytes("?????")p=getPrime(1024)while True: q=getPrime(1024) if p>q: breakn=p*qe="?????"d=inverse(e,(p-1)*(q-1))c=pow(m,e,n)decimal.getcontext().prec = 1024P=decimal.Decimal(p)Q=decimal.Decimal(q)leak=decimal.Decimal((3*P*P-1)/(3*P*Q))print("c =",c)print("leak =",leak)print("d =",d)和basectf2024的题差不多,连分数展开就行
exp.py
c = 7908369000608075306226552240713890041649799894903074579356627811865842237315201153498579205223600526520994811661608630888045462921547166872107507948062717836952855804806976414887413729060431265217539895710936669089248515746191716161194996469977577048602427553584286064475300979649416171469313168995504717602670924606819204605601860560767900702512753735554900344201907921239415885901489708576066483012272256175573658509614344875077232108364134161997767814675830320630271209201503987787921279932886374846298269125068817280777403718279754392091441050281244934594776307137448975055247018414699621410668188864774860026941
leak = 1.396995694831414203476063690838730308815841662737318558906107823553922718340982125801595368449608188770051881765292978548960520326036779130167518285237817101541807766017642530065080930654694948943506714268685400709580398894902693407016988670394423892586264077247263710263220932577837642377245651448838665854362532801659965471421937839336237670710012298796758992931116659292915200628873553198226185187089027680973673618973869464164460226697625936493428822424637497370197316811245879504779934098600596822159243994319583651080005054538419168988020562590543262648544970376255020489363894055887067948343768399654357738592577280906555896933717091837896978973488220368081406433117367524537063718421897982643644320078600517763936883820416362057895941185749296170109172249907094176821124345672294602380784325702476105763209165109703429326132417850746805701054961710623030742187505484821961670922386999933202645522248608323217011522889282323071281405301772218220381951540118124201599862330377374571641729649420917168701463539034702411
d = 16306054997613721520756151430779642117683661431522665108784419231044104572118893098180652730976905729602478591047033305251624752030036736271198006715513694904231940253554804069707679445942892410812386221633728427239116007373836662495075237456279818311659331982404534490546781763464409713789636372508503902598331950861474527128323735250673137355260113147338636761737748874105625008482750923429512271416511835596944209137554445130949731646669691366003832655082535985891463876904334888009751956386994969339847254470145428608062575606120441725590059524749595027078238962391188809496875025237129899849787699468205026040721
from Crypto.Util.number import *
cf = continued_fraction(leak)convers = cf.convergents()for pkd in convers: # possible k, d pp, pq = pkd.as_integer_ratio() pp=int(pp) if pp.bit_length()==1024 and isPrime(pp): flag=long_to_bytes(int(pow(c,d,pp))) if b'flag' in flag: print(flag) breakpeco
task.py
from Crypto.Util.number import *from secret import FLAG,x,y
f0= bytes_to_long(FLAG[:len(FLAG)//2].encode())f1= bytes_to_long(FLAG[len(FLAG)//2:].encode())
n= int()c= int()gift1= int()gift2= int()
m=getPrime(1876)p=getPrime(1024)q=getPrime(1024)print(p,q)n=p*qe=65537c=pow(m,e,n)print('n=',n)print('c=',c)print('gift1=',1293023064232431070902426583269468463*x**2-105279230912868770223946474836383391725923*y**2)print('gift2=',(p**7+q**13)&(2**777-1))
assert (x*f0+y*f1)%m <2**99前面gift1是个pell方程,sagemath有个函数可以写,都是感觉有点慢,还得自己筛选正数解,ai更是手搓一堆,这里推荐用from sympy.solvers.diophantine.diophantine import diop_DN,包好的。
pq可以通过copper出来,但是我是捡的(),看这个
然后打个格就行了
exp.py
from Crypto.Util.number import *from gmpy2 import *from sage.all import *from sympy.core.intfunc import irootfrom sympy.solvers.diophantine.diophantine import diop_DN
n= int(18443962106578943927922829208562388331564422618353954662348987125496135728205879853444693999188714508145409575298801277623433658530589571956301880815632542860363148763704636874275223979061507756787642735086825973011622866458454405794279633717255674221895468734500735123736684346340314680683830866884050311047424068122453972745273167956795195575475691048908906061023817574695902603984554911326264947716547564759877947888574515784489778380086664649338093680740990860192640619047071160362288611331225632270531304525264824445326394068892806774552310748255977040249822464839809344521107040968321810533993659358229305320413)c= int(8176283809770578639445916571748890916863681496488338436815389781344271720445865752568007651231910205530735296305471880971422173915403956857863330698931559658909826642456860761540607878553228782799635976463090037022164739976302533892173751687781100980039065722082091714141141136171701360981540040678479802206949078162548124224838019262997441233919136963696523351831737708850863538007579105976954619102728135600542584651031405327214877358323388674864043740117718200022790892542634633918493245432384562983429810936975869853596007429259749282607844407676244954057886824475948603911174707176467261179324130051317766768127)gift1= int(1293023064232431070902426583269468463)gift2= int(26161714402997656593966327522661504448812191236385246127313450633226841096347099194721417620572738092514050785292503472019045698167235604357096118735431692892202119807587271344465029467089266358735895706496467947787464475365718387614)
x = diop_DN(105279230912868770223946474836383391725923//1293023064232431070902426583269468463,gift1//1293023064232431070902426583269468463)[0][0]yy=(1293023064232431070902426583269468463*x**2-gift1)//105279230912868770223946474836383391725923y=iroot(yy,2)[0]print(x)print(y)x=int(x)y=int(y)p = 110321094976129707319520600986374898031772388334195419291797204096276942296698733990367680023948047820442401228783658911134388494335281166694315709721180388295015528680094263090624783953349710316927409137594927749594230788983109047830897067234559148509079478238626283574442539878131266374870841191635047394681q = 167184364065364685056497190415155636144720644950725295920271367595483444357416641085807605674441141156570389367370149531967480290218274897524375212202875627325755457975276196034582673268786547482587150378645612877166485244134843695743056623756823734183252667243967918491196265305063449882555425959453836272773m=pow(c,inverse(65537,(p-1)*(q-1)),n)W=2**100M = Matrix(ZZ, [ [1, 0, x * W], [0, 1, y * W], [0, 0, m * W] ])L=M.LLL()for row in L: try: r0 = abs(row[0]) r1 = abs(row[1]) r2 = abs(row[2])
p1 = long_to_bytes(r0) p2 = long_to_bytes(r1) p3=long_to_bytes(r2)
print(p1) print(p2) print(p3) except Exception: continue比较懒直接全输出出来了
pem
给了残缺的公钥和私钥,比较抽象的是给了ne,哎,你需要通过公钥和私钥文件把n给拼出来,这个n才是对的,哥们是没想到的,大ne,d拿boneh_durfee打
exp.py
from __future__ import print_functionimport time
############################################# Config##########################################
"""Setting debug to true will display more informationsabout the lattice, the bounds, the vectors..."""debug = True
"""Setting strict to true will stop the algorithm (andreturn (-1, -1)) if we don't have a correctupperbound on the determinant. Note that thisdoesn't necesseraly mean that no solutionswill be found since the theoretical upperbound isusualy far away from actual results. That is whyyou should probably use `strict = False`"""strict = False
"""This is experimental, but has provided remarkable resultsso far. It tries to reduce the lattice as much as it canwhile keeping its efficiency. I see no reason not to usethis option, but if things don't work, you should trydisabling it"""helpful_only = Truedimension_min = 7 # stop removing if lattice reaches that dimension
############################################# Functions##########################################
# display stats on helpful vectorsdef 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")
# display matrix picture with 0 and Xdef 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)
# tries to remove unhelpful vectors# we start at current = n-1 (last vector)def remove_unhelpful(BB, monomials, bound, current): # end of our recursive function if current == -1 or 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`"""def boneh_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 not in 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") return 0,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
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(): ############################################ # How To Use This Script ##########################################
# # The problem to solve (edit the following values) #
# the modulus N = # the public exponent e =
# the hypothesis on the private exponent (the theoretical maximum is 0.292) delta = .28 # 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 = 8 # 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 ===") if False: 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()
# e="70 55 09 ec 28 3d c9 4e 3b be 85 ca 1e 36 85 85 86 72 1f 3d 1a 8d 67 81 34 51 e1 60 72 8c c8 7e 73 a5 f1 6a 3c 4e d3 ef b5 53 ed e1 5d 54 01 de 32 c2 65 cc 49 02 a6 66 6a 3b 7d 8e 98 44 b9 cb 2a 1f fc 44 79 df 0d 0f 1e e9 92 71 84 93 ad 47 cb 28 9d f2 06 33 7a 06 3a 0f b0 d7 5f 66 a0 99 81 20 a0 22 7b 4a c0 10 00 ee e0 e8 e6 00 12 aa 6a b6 13 fb 92 b3 73 92 2e e3 28 5b 6c bd 42 9a 3b f8 a6 31 72 09 0e 14 6b 19 cf 19 0a f1 5a be 65 73 e9 9a bb fd 01 69 5f 80 0c 2c f4 70 63 ef 7f ec 9e 69 60 f9 19 68 24 3b 67 32 ae 43 1a 3e f4 08 ea 02 7e 3e 7c d4 46 e3 3d 43 0f 18 ed ba d8 c6 5f 75 4b 06 4a 83 cc 0f f8 1d 79 47 26 c5 c1 f7 d3 9f f9 1a 79 cd 3a 7e 18 fe 26 f3 cf a2 3d e3 34 9f cb 44 d7 08 4a 05 e7 9a ed 98 90 ad ea e9 32 d3 e7 78 9d 02 08 32 43 23 62 b1 e1 25"# n="00 d8 1d b1 95 02 4c 9b d0 3d d8 56 65 6a d1 19 fa 19 a0 a7 71 20 bf 10 d9 c4 02 f4 eb 3d c7 98 b6 11 fd d9 c2 09 c1 7d 87 93 9f a9 2f b0 e8 c1 14 73 23 22 7d d2 ed d8 1b 40 f6 82 a5 4d e1 03 5f 0a f0 3a 66 0e c1 b3 4d b6 88 84 d0 38 e2 e1 af aa b7 95 46 d4 72 50 fd 30 d2 a7 0a 7f fd 83 f1 13 8f 35 3e c9 4f 58 bf 2b 34 48 f8 c4 d3 32 41 9e 3e 1a 32 cf 73 1d ce db 66 ec 1f c4 0a fd fe 3a 05 ad 2d 1c f4 f7 66 a6 42 cb 64 69 0b 45 e2 b6 46 56 3a fb 6d fd f5 99 df 84 83 8b 71 1f 1b 0a 79 b5 f7 bd f1 08 8a 4f 77 a1 0b 13 ad 8a 36 71 db ff 92 00 13 13 7f c5 e2 97 5a 58 1c d8 7b cc 85 15 d8 73 bf ae c4 33 4c b1 c3 1b 16 20 63 16 f9 2c be 44 9f ae 81 15 74 11 3e 5e b2 ed 01 53 d1 fc cb 80 a0 21 0e 80 76 e1 c5 fb f6 af ab be a7 3a d1 80 5c 0a 1b 20 c7 0c f2 c1 3b fe 03"# w=0# nlow=""# for i in e.split(" "):# w+=1# nlow+=i# print(int(nlow,16))n=e=c=open("/Users/zsm/Downloads/crypto/pem/enc","rb").read()from Crypto.Util.number import *c=bytes_to_long(c)d=m=pow(c,d,n)print(long_to_bytes(m))RandomAudit
最重量级的
题目描述
某内部审计系统号称“全部采用自研高强度密码模块”,为了节省日志空间,他们把敏感日志 AES 加密后上传,又用 RSA 对关键密钥做了“备份加密”,最后还用“秘密分享”来保护真正的 FLAG。不幸的是,开发同学对“随机数”和“密码学”理解似乎有点……偏差。你从审计服务器上拿到了以下文件你的任务是:从这些文件中还原出最终的 flag。
给了四个文件aes_ct.txt,这个是aes相关的。rsa_pub.txt给了ne。session_ids.txt给了四个随机数。shares.enc给了三个加密后的数。
这玩意你得语文阅读能力好一点。
我们先进行对话,对话之后按照系统来说就是要对日志进行加密了,加密的时候采用的key和iv继续用这个LCG生成。
第三个第四个64-bit拼接起来刚好是iv,第一个第二个64-bit是key,但是CBC模式下解密是乱码。那么我们尝试其他的方法,CTR下拿到106141198856029082317733263764736461207。
这玩意是seed,当成LCG新的种子,往后爆破可以分解N。
然后去解密那三个数,得到一个等差数列[a, b, c] —> c - b == b - a(diff),uuid是32位,diff转16进制之后刚好是32位,然后用”-“连上。
神了,脚本就不放了()
总结
感觉出题风格越来越奇怪了?感觉都想往实际环境的方向走,但是都很怪,要么是出的不太实际,要么是沾点脑洞。
那就得想怎么出的实际了。实际生活的密码学其实是比较安全的,如果想贴近实际,可能只有侧信道比较多?比如vctf的哪一题,强网拟态决赛的那个侧信道misc?感觉需要多方向结合起来,比如web中有dh或者是其他的东西泄露,也有可能像那个misc一样简单的侧信道之后再misc工具求解?
其实有个大胆的想法,如果webshell弹了之后需要解密码提权怎么样(,或者是域管理的密钥、凭证需要密码学的东西?说不定下次tkkctf就有了()
Some information may be outdated