この大会は2020/6/16 0:30(JST)~2020/6/18 0:30(JST)に開催されました。
今回もチームで参戦。結果は4252点で810チーム中63位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome to Phase 1 (Misc)
入力欄に書いてある。
zh3r0{is_this_a_real_flag?}
Flag 5 (Subset of subset of hacking machines challenges)
$ nmap -Pn hackit.zh3r0.ml Starting Nmap 7.60 ( https://nmap.org ) at 2020-06-16 20:20 JST Nmap scan report for hackit.zh3r0.ml (139.59.3.42) Host is up (0.14s latency). Not shown: 998 filtered ports PORT STATE SERVICE 22/tcp open ssh 99/tcp open metagram Nmap done: 1 IP address (1 host up) scanned in 22.31 seconds $ nmap -P0 -A hackit.zh3r0.ml -p 22,99 Starting Nmap 7.60 ( https://nmap.org ) at 2020-06-16 20:25 JST Nmap scan report for hackit.zh3r0.ml (139.59.3.42) Host is up (0.13s latency). PORT STATE SERVICE VERSION 22/tcp open http PHP cli server 5.5 or later |_http-title: Site doesn't have a title (text/html; charset=UTF-8). 99/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 70:78:8f:70:79:59:72:5f:05:c9:2a:63:b4:34:c1:52 (RSA) | 256 08:6d:42:16:2a:47:ae:b4:d7:fa:35:28:91:67:ab:63 (ECDSA) |_ 256 e4:89:6b:09:37:64:c2:47:01:bd:c2:32:d8:cd:06:2d (EdDSA) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 53.07 seconds $ curl http://hackit.zh3r0.ml:22/ z3hr0{shouldve_added_some_filter_here}
z3hr0{shouldve_added_some_filter_here}
snakes everywhere (Reversing)
Pythonコードのアセンブリからコードにすると、以下のようになる。
from flags import flag1 flag = flag1 fake_flag = 'zh3r0{fake flag}' key = 'I_l0v3_r3v3r51ng' assert len(flag) == 38 def xor(str1, str2): return chr(ord(str1) ^ ord(str2)) ciphertext = '' for i in range(len(flag)//3): ciphertext += chr(ord(key[i]) * ord(flag[i]) - i) for i in range(len(flag)//3, len(flag)//3*2): ciphertext += chr(ord(flag[i]) * ord(key[i%len(key)]) + i) for i in range(len(key)//2, len(flag)): ciphertext += xor(key[i%16], flag[i]) file = open('ciphertext.txt', 'w') print(len(ciphertext)) file.write(ciphertext) file.close()
以上から逆算していけばフラグになる。
#!/usr/bin/env python3 import codecs def xor(str1, str2): return chr(ord(str1) ^ ord(str2)) key = 'I_l0v3_r3v3r51ng' with codecs.open('snake.txt', 'r', 'utf-8') as f: ciphertext = f.read() flag = '' for i in range(12): flag += chr((ord(ciphertext[i]) + i) // ord(key[i])) for i in range(12, 24): flag += chr((ord(ciphertext[i]) - i) // ord(key[i%len(key)])) for i in range(8, 38): if i < 24: assert flag[i] == xor(ciphertext[i+16], key[i%16]) else: flag += xor(ciphertext[i+16], key[i%16]) print(flag)
zh3r0{Python_disass3mbly_is v3ry_E4sy}
Web-Warmup (Web)
HTMLソースを見る。読み込んでいるbg.cssを見ると、コメントにフラグが書いてあった。
/*css is easy, I think. Don't you?zh3r0{y3s_th1s_1s_w4rmup}*/
zh3r0{y3s_th1s_1s_w4rmup}
LSB fun (Forensics)
Windowsのjstegツールで抽出する。
>jsteg reveal chall.jpg zh3r0{j5t3g_i5_c00l}
zh3r0{j5t3g_i5_c00l}
Katycat (Forensics)
$ zsteg katy.png b1,rgb,lsb,xy .. text: "https://pastebin.com/hvgCXNcP" b2,r,msb,xy .. file: PGP\011Secret Key - b2,rgb,msb,xy .. text: "EEQPUUU@U" b2,abgr,msb,xy .. text: "WSSWCCCCSSWWCC" b3,bgr,msb,xy .. text: "(Z0-X0-H" b4,r,lsb,xy .. text: "DfffdDB\"" b4,r,msb,xy .. text: "@\"fa\"DD$DD" b4,g,lsb,xy .. text: "D\"\"$\"D\"\"\" " b4,g,msb,xy .. text: "&b\"fa\"DD$D\"DDD" b4,b,lsb,xy .. text: "vPUFwDT!" b4,b,msb,xy .. text: "USUs33UU&\"Q3" b4,rgb,lsb,xy .. text: "hDdD\"B$\"\"\"\"dF\"b$$" b4,rgb,msb,xy .. text: "QU3sUS53337uSp" b4,bgr,lsb,xy .. text: "fdDDB$\"\"\"\"b&Db$\"" b4,bgr,msb,xy .. text: "Su3S5U3335WsuP" b4,abgr,msb,xy .. text: "?U?U?5?5?"
https://pastebin.com/hvgCXNcPにアクセスしてみると、以下の文字列がある。
UEsDBAoACQAAALq0vFDu3sG8JQAAABkAAAAIABwAZmxhZy50eHRVVAkAA+jvz179789edXgLAAEE 6AMAAAToAwAAt9tbOQhvceVTC9i83YoBgbIW5fmqoaO3mVwXSLOMqNulwvcwb1BLBwju3sG8JQAA ABkAAABQSwECHgMKAAkAAAC6tLxQ7t7BvCUAAAAZAAAACAAYAAAAAAABAAAApIEAAAAAZmxhZy50 eHRVVAUAA+jvz151eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAAdwAAAAAA
enc = ''' UEsDBAoACQAAALq0vFDu3sG8JQAAABkAAAAIABwAZmxhZy50eHRVVAkAA+jvz179789edXgLAAEE 6AMAAAToAwAAt9tbOQhvceVTC9i83YoBgbIW5fmqoaO3mVwXSLOMqNulwvcwb1BLBwju3sG8JQAA ABkAAABQSwECHgMKAAkAAAC6tLxQ7t7BvCUAAAAZAAAACAAYAAAAAAABAAAApIEAAAAAZmxhZy50 eHRVVAUAA+jvz151eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAAdwAAAAAA ''' enc = enc.replace('\n', '') with open('flag.zip', 'wb') as f: f.write(enc.decode('base64'))
base64デコードすると、zipになるが、パスワードがかかっている。fcrackzipでパスワードクラックしてみる。
$ fcrackzip -u -D -p dict/rockyou.txt flag.zip PASSWORD FOUND!!!!: pw == kitkat
このパスワードで解凍する。
$ unzip -P kitkat flag.zip Archive: flag.zip extracting: flag.txt $ cat flag.txt K9bC_L`D?f0DEb8c?_06cDJN
rot47で復号すると、フラグになった。
zh3r0{1sn7_st3g4n0_e4sy}
Snow (Forensics)
タイトルからもsnowを使ったステガノグラフィと推測できる。.secret.txtの内容をパスワードとして抽出する。
>SNOW.EXE -C -p welc0me_to_zh3r0_ctf chall.txt zh3r0{i5_it_sn0w1ng?}
zh3r0{i5_it_sn0w1ng?}
RSA-Warmup (Crypto)
$ nc crypto.zh3r0.ml 8451 N: 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857 e 65537 CT: 28279148543261010538786162189188416138622702190690046805887004409024981386725281303105636820548914828865663276341527926288823477904578678093032127397866691471033090624228990190190140386526912958442365620531660273304172392330422040873262164993051721152973279728450632330158105145649469394623518488176940748325366439174
Nを素因数分解する。
$ python -m primefac 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857: 3964720609 91356878046538845391249767733132663845083802343724385839231338471084211074980428432811708245248646075946434389922073580423752703749567339886240641643080698481631763985139626653876483367776304928896638799693856555016772889621297864627795470513024314819363930040122989604964027163384423229540220633843045267673
Nを素因数分解できたので、あとはそのまま復号する。
from Crypto.Util.number import * N = 362204497165012221441752622398014284477672934484246574352668248354962122223480948879218151496432533426651807605790387028320471297675381207280285987455705667520240462620907047537189803348668442653464783479975255974364741816154041849217512816179839303882436285701309813781493647198306032967736450341404564444063064572857 e = 65537 CT = 28279148543261010538786162189188416138622702190690046805887004409024981386725281303105636820548914828865663276341527926288823477904578678093032127397866691471033090624228990190190140386526912958442365620531660273304172392330422040873262164993051721152973279728450632330158105145649469394623518488176940748325366439174 p = 3964720609 q = 91356878046538845391249767733132663845083802343724385839231338471084211074980428432811708245248646075946434389922073580423752703749567339886240641643080698481631763985139626653876483367776304928896638799693856555016772889621297864627795470513024314819363930040122989604964027163384423229540220633843045267673 phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(CT, d, N) flag = long_to_bytes(m) print flag
zh3r0{RSA_1s_Fun}
Mix (Crypto)
base65536でデコードする。
#!/usr/bin/env python3 import base65536 with open('chall_encrypted.txt', 'r', encoding='utf_8') as f: ct = f.read() pt = base65536.decode(ct) print(pt.decode())
実行結果は以下の通り。
flag 1: Yjod od s lrunpstf djogy vo[jrtyrcy jrtr od upi g;sh xj4t-}U-i+dit4+ flag 2: 3030313130313030203031313130303130203030313130303131203031303131313131203030313130313030203031313130313131203030313130303131203031313130303131203030313130303030203031313031313031203030313130303131203031303131313131203031313130313131203031313031303031203030313130313131203031313031303030 flag 3: MTExMTExMTExMTAwMTAwMDEwMTAxMDExMTAxMDExMTExMTEwMTAxMTExMTExMTExMDExMDExMDExMDExMDAwMDAxMTAxMDAxMDAxMDAxMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAxMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMTAxMDAwMTAxMDAxMDAwMTAxMDAxMTExMTExMTAwMTAxMDAxMDExMTExMTExMTAwMTAxMDAxMTAwMDAwMDAwMDAwMDAwMTAxMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDExMTExMTExMTExMTExMTExMTExMDAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMDAwMDAwMDAxMDEwMDExMDAwMDAwMDAxMDEwMDAxMDEwMTExMTAwMTAxMDAxMDExMTExMTExMTExMTExMTExMTExMDAxMDEwMDExMDExMDExMTExMTExMTExMTAwMTAxMA==
flag1~3について、それぞれ復号する必要がある。まずflag1については、各文字をUS配列キーボード上で左の文字に変える。
This is a keyboard shift ciphertext here is you flag zh3r0{Y0u_sur3_
次にflag2はhexデコードすると、2進数のASCIIコードが並んでいるのがわかるので、デコードする。
import base64 ct2 = '3030313130313030203031313130303130203030313130303131203031303131313131203030313130313030203031313130313131203030313130303131203031313130303131203030313130303030203031313031313031203030313130303131203031303131313131203031313130313131203031313031303031203030313130313131203031313031303030' codes = ct2.decode('hex').split(' ') flag2 = '' for code in codes: flag2 += chr(int(code, 2)) print flag2
デコード結果は以下の通り。
4r3_4w3s0m3_wi7h
最後にflag3については、base64デコードすると、0,1の並んだ文字列になるが、ASCIIコードにはなりそうにない。
1111111111001000101010111010111111101011111111110110110110110000011010010010010000000000000000001010011000000000000000000000000000000000000000000000000000000001010000000000001010001010010001010011111111001010010111111111001010011000000000000001010010000000000000000000000000000001010111111111111111111110010100000000000000000000000000010100000000010100110000000010100010101111001010010111111111111111111110010100110110111111111111001010
問題を見ると、SPOONというキーワードがあるので、調べてみると、Spoon Languageというものがあることがわかる。
https://www.dcode.fr/spoon-languageでデコードする。
_411_7h3_ski115}
flag1~3を結合すると、フラグになる。
zh3r0{Y0u_sur3_4r3_4w3s0m3_wi7h_411_7h3_ski115}
Hastad's message (Crypto)
$ nc crypto.zh3r0.ml 7419 N: 22857403917033452762301692151936680227099179828447116694851576122227087851149555427000138614019347046657401967421147503016546446657912243103301489550801502213543799142440722257289782903210973777123770395462277652515090800990170935194739452788926924406411625140822688653866031925496143186166969089756967341706986678103581032106577269283579684740814341978215925969756042680055259503028748627289133764296953426402876584404716806524279688134865241125740556757179831843282004974142256384849751862870211107430066634096097714894315793983740153650155659957823284584625222819243597312146000907539885211491273592108608676263997 CT: 21006791237991463493340715948837281319345332975431116155246886857329226729176905006985301880229589771867164219946980507403131176313843758775517084997896302863517136186936942094292340604242114096356212545068140977209543062639322853952829213905545327059774710190550607656944699178883239469025363244471355734382420605349807467572623064978145945360251167254005860156200061225217268443957714842188064887796139342976650738189179581667380553718551142665142086887013363723794633316229945140842423696160124298510198972514083898687854267419336322673376025386514986398539403721584892994795627805100546778227736928427965280816039 $ nc crypto.zh3r0.ml 7419 N: 24255028471131132079553905484198967796113853854803832085857908151952952553438604497305380360218255010195759694646983763016990035030508175202633392488210643722838705715759466198971587743605730499883974472311824555697152669592357863583927334616520558312740769160009255637189341430484907205847141876471366729441606996227896102150555964555972937245587927782688252918165407439303880665315125498637886009255567255874696729407591739218027242787230753662154898772475316535468193123937724482351740172029114212735258050226173549824091790974175866156475826591910151603770169641134890040540391370445465191312108856014264989983419 CT: 4080653980915597905639514646198687473573442849454819707783099713713422382104870992346376322305324753220468980472324072065019769335937812772641959339576410882752539996679965165219562794135836515575063660680045105348959510487942209928320980889028161465222578675623217424488964105504097617934299285784701174152694716817179016013110373107461312130891720745243058109317442985903785433116301947585694340522495090274741149337040549108069094609388063239087266931938935205446241123974559960107196840388273379246802454394826076801079280490108853216721513492813056227181113503696807736676905961129314440189516070951160240768528 $ nc crypto.zh3r0.ml 7419 N: 18170781317829964454680876495568985113697632391187407846578744087052531477112675213533542625672700822419610345901567198182263091158570601201787845714888045495826219850734105016410092117287277362378896745761380158857097548540976713621657106454534379363303323375130629105535594640138008735015400277243571219812012584396420515815878989240581459952456797172991674149087707378266680425895017939205927487902023669063943408647789564745167286117702947615719992719924064383905809432619142537197018133574831738605207342838580303912716997382979289558793912617558864411334676100405687905822983720599084620562783990512841069780401 CT: 16421004495511763958782822739048726299470163120688526903461320430488416917368074624661373617529321882858883043268395753857587802837859712349474497032398844368474587293204872415008847994460996019119277400038454245204198348047373004175429102952579524430005982588506808607416160075948392466286975076688338000579281720715833339965992184047365696237560807592187133148808044698570623096872957459722460928209621248015591145194604248730523613931253283523316930243593394425608043954849400410380900216653789971518865354330515457388937591390035942970879666182575102575041672419570372174753138366738036997445784549007667425022295
eの値はわからないが、とりあえずe=3として3つのデータを集め、Hastad's Broadcast Attackで復号してみるが、うまくいかなかった。さらに2つのデータを集める。
$ nc crypto.zh3r0.ml 7419 N: 18381521670468669483125585535872682141850263297128579361275636911380507573797401758589301007911962912929657515275269863194175875752890317760263717055015302034421756983390372419334702052084367063446373277862931097423244154285118179117892587143633004715840167349173688639034638801842458735448404548970627564765423490499776295630455197197223957539093720798843471184912396633300558792099829828026289655503505196822190051132389391628953432211739874968197367189223781866012905951782997344495708430917952820714445618318673029669347893710046232869414785081166992164976832492308617162252015602581429407743510730957911298012421 CT: 1818892344291150537872012729215705122734238326815668996961579488232419188824050503233307373549204308663271437843774188077568286368923059868354156657642490397060779759446489103790176917775051873835530733346890879137836113716115814508550855715821953590672459496312656022341509256040734847291970639809901518117832540714387827314693528653612061512064870782976670018665074687028614426300382563677842204341520468146624639048010518108375189941778370046173224264766679336949866012929878305757088219461570251770129940691519585417412368422989271566419214088150943534964026343300089924340622123992441664730270764149871235142536 $ nc crypto.zh3r0.ml 7419 N: 24734494903694969744575863846845904407753451836991665788830976839955898670258636144673676463220033110047190799495183607210280172541939189869982701604224204422324525455826659132479539317246176913090534409398141536909955246566256622784342406536057772835527020520414060722692873534272745699558390874305048328998316865423785482997405348891762811594525859452959439903945538655453636380296676586240884908596590906244873206042296763628632887732787926635197575233002004463287098051749689831983198984586683992196167915209070530685176685511999474083049088414885221523468506180076982155175996087885097390199263784159028723755969 CT: 12234027254738065079308678164515853762386657938164876547464782059807602392721470637458014128343488029878456988990625453370008672737998196811664785626635975123287666874966033053311723420277382605028538477470057448860946203384350301962098533905082391988247355522230150210738399620642541614854621638391571546534083090214981674398127144628767303126200529760600329589741832571931960007009869597427838973352486821367509562025643864799572949058480884145061530932914189605837814509387660323215110814788732659079516894101010991761217221401823561781414765493231103098860170642291471339517281171816879226186688416616775070727473
今度はeの値を5にして試してみる。
import functools from Crypto.Util.number import * def chinese_remainder(n, a): sum = 0 prod = functools.reduce(lambda a, b: a*b, n) for n_i, a_i in zip(n, a): p = prod // n_i sum += a_i * mul_inv(p, n_i) * p return sum % prod def mul_inv(a, b): b0 = b x0, x1 = 0, 1 if b == 1: return 1 while a > 1: q = a // b a, b = b, a%b x0, x1 = x1 - q * x0, x0 if x1 < 0: x1 += b0 return x1 def inv_pow(c, e): low = -1 high = c+1 while low + 1 < high: m = (low + high) // 2 p = pow(m, e) if p < c: low = m else: high = m m = high assert pow(m, e) == c return m N1 = 22857403917033452762301692151936680227099179828447116694851576122227087851149555427000138614019347046657401967421147503016546446657912243103301489550801502213543799142440722257289782903210973777123770395462277652515090800990170935194739452788926924406411625140822688653866031925496143186166969089756967341706986678103581032106577269283579684740814341978215925969756042680055259503028748627289133764296953426402876584404716806524279688134865241125740556757179831843282004974142256384849751862870211107430066634096097714894315793983740153650155659957823284584625222819243597312146000907539885211491273592108608676263997 CT1 = 21006791237991463493340715948837281319345332975431116155246886857329226729176905006985301880229589771867164219946980507403131176313843758775517084997896302863517136186936942094292340604242114096356212545068140977209543062639322853952829213905545327059774710190550607656944699178883239469025363244471355734382420605349807467572623064978145945360251167254005860156200061225217268443957714842188064887796139342976650738189179581667380553718551142665142086887013363723794633316229945140842423696160124298510198972514083898687854267419336322673376025386514986398539403721584892994795627805100546778227736928427965280816039 N2 = 24255028471131132079553905484198967796113853854803832085857908151952952553438604497305380360218255010195759694646983763016990035030508175202633392488210643722838705715759466198971587743605730499883974472311824555697152669592357863583927334616520558312740769160009255637189341430484907205847141876471366729441606996227896102150555964555972937245587927782688252918165407439303880665315125498637886009255567255874696729407591739218027242787230753662154898772475316535468193123937724482351740172029114212735258050226173549824091790974175866156475826591910151603770169641134890040540391370445465191312108856014264989983419 CT2 = 4080653980915597905639514646198687473573442849454819707783099713713422382104870992346376322305324753220468980472324072065019769335937812772641959339576410882752539996679965165219562794135836515575063660680045105348959510487942209928320980889028161465222578675623217424488964105504097617934299285784701174152694716817179016013110373107461312130891720745243058109317442985903785433116301947585694340522495090274741149337040549108069094609388063239087266931938935205446241123974559960107196840388273379246802454394826076801079280490108853216721513492813056227181113503696807736676905961129314440189516070951160240768528 N3 = 18170781317829964454680876495568985113697632391187407846578744087052531477112675213533542625672700822419610345901567198182263091158570601201787845714888045495826219850734105016410092117287277362378896745761380158857097548540976713621657106454534379363303323375130629105535594640138008735015400277243571219812012584396420515815878989240581459952456797172991674149087707378266680425895017939205927487902023669063943408647789564745167286117702947615719992719924064383905809432619142537197018133574831738605207342838580303912716997382979289558793912617558864411334676100405687905822983720599084620562783990512841069780401 CT3 = 16421004495511763958782822739048726299470163120688526903461320430488416917368074624661373617529321882858883043268395753857587802837859712349474497032398844368474587293204872415008847994460996019119277400038454245204198348047373004175429102952579524430005982588506808607416160075948392466286975076688338000579281720715833339965992184047365696237560807592187133148808044698570623096872957459722460928209621248015591145194604248730523613931253283523316930243593394425608043954849400410380900216653789971518865354330515457388937591390035942970879666182575102575041672419570372174753138366738036997445784549007667425022295 N4 = 18381521670468669483125585535872682141850263297128579361275636911380507573797401758589301007911962912929657515275269863194175875752890317760263717055015302034421756983390372419334702052084367063446373277862931097423244154285118179117892587143633004715840167349173688639034638801842458735448404548970627564765423490499776295630455197197223957539093720798843471184912396633300558792099829828026289655503505196822190051132389391628953432211739874968197367189223781866012905951782997344495708430917952820714445618318673029669347893710046232869414785081166992164976832492308617162252015602581429407743510730957911298012421 CT4 = 1818892344291150537872012729215705122734238326815668996961579488232419188824050503233307373549204308663271437843774188077568286368923059868354156657642490397060779759446489103790176917775051873835530733346890879137836113716115814508550855715821953590672459496312656022341509256040734847291970639809901518117832540714387827314693528653612061512064870782976670018665074687028614426300382563677842204341520468146624639048010518108375189941778370046173224264766679336949866012929878305757088219461570251770129940691519585417412368422989271566419214088150943534964026343300089924340622123992441664730270764149871235142536 N5 = 24734494903694969744575863846845904407753451836991665788830976839955898670258636144673676463220033110047190799495183607210280172541939189869982701604224204422324525455826659132479539317246176913090534409398141536909955246566256622784342406536057772835527020520414060722692873534272745699558390874305048328998316865423785482997405348891762811594525859452959439903945538655453636380296676586240884908596590906244873206042296763628632887732787926635197575233002004463287098051749689831983198984586683992196167915209070530685176685511999474083049088414885221523468506180076982155175996087885097390199263784159028723755969 CT5 = 12234027254738065079308678164515853762386657938164876547464782059807602392721470637458014128343488029878456988990625453370008672737998196811664785626635975123287666874966033053311723420277382605028538477470057448860946203384350301962098533905082391988247355522230150210738399620642541614854621638391571546534083090214981674398127144628767303126200529760600329589741832571931960007009869597427838973352486821367509562025643864799572949058480884145061530932914189605837814509387660323215110814788732659079516894101010991761217221401823561781414765493231103098860170642291471339517281171816879226186688416616775070727473 N = [N1, N2, N3, N4, N5] C = [CT1, CT2, CT3, CT4, CT5] e = len(N) a = chinese_remainder(N, C) for n, c in zip(N, C): assert a % n == c m = inv_pow(a, e) flag = long_to_bytes(m) print flag
実行結果は以下の通り。
Its great that you have come till here. As promised here is your flag: zh3r0{RSA_1s_0n3_of_th3_b4st_encrypt10n_Bu66y}
zh3r0{RSA_1s_0n3_of_th3_b4st_encrypt10n_Bu66y}
Help me (Crypto)
Pythonコードのアセンブリからコードにすると、以下のようになる。
from flag import flag, key from binascii import hexlify from Crypto.Util.number import * assert len(flag) == 48 fake_flag = 'zh3r0{l0l_thi5_i5_n0t_th3_fl4g}' def xor(str1, str2, num): return chr((ord(str1[num]) + num) ^ ord(str2[num])) def first_half(half_flag): return [hexlify(half_flag[i:i+4].encode()) for i in range(0, len(half_flag), 4)] def second_half(half_flag): return [bytes_to_long(half_flag[i:i+4].encode()) for i in range(0, len(half_flag), 4)] def encrypt(flag, key): final = [] first_xor = [xor(flag[:len(flag)//2], key[len(key)//2:], i) for i in range(len(flag)//2)] second_xor = [xor(flag[len(flag)//2:], key[:len(key)//2], i) for i in range(len(flag)//2)] final += first_half(''.join(first_xor)) final += second_half(''.join(second_xor)) return final print(encrypt(key, flag))
このコードを見ると、フラグを前半、後半に分け、以下のような処理になっている。
・フラグの前半、鍵の後半とXORを取り、4バイトごとに16進数表示にする。 ・フラグの後半、鍵の前半とXORを取り、4バイトごとに数値表示にする。
鍵がわかれば、復号できる。鍵は以下の文字列であるようだが、エンコードされている。
5Nzwbdkvm1VF1X3zc8d6kPd7MMTgSW9Dv1otpwkbPyggHqk5CaEHYwCD14vBdc3w86
試した結果、base58デコードして、rot47にすると、正しい鍵になる。あとはXORで元に戻していく。
#!/usr/bin/env python3 import base58 from binascii import unhexlify from Crypto.Util.number import * def rot47(s): d = '' for c in s: code = ord(c) + 47 if code > 126: code -= 94 d += chr(code) return d def rev_xor(str1, str2, num): return chr((ord(str1[num]) ^ ord(str2[num])) - num) key = '5Nzwbdkvm1VF1X3zc8d6kPd7MMTgSW9Dv1otpwkbPyggHqk5CaEHYwCD14vBdc3w86' key = rot47(base58.b58decode(key).decode()) print('key =', key) ct = [b'03367345', b'46c39f41c3a8', b'1544651a', b'03451b28', b'77c3aac3a275', b'c39e16c3b6c3b2', 391124763, 121061897, 1396123432, 389813723487, 295339258400, 131682038629031] ct1 = '' for i in range(6): ct1 += (unhexlify(ct[i])).decode() flag1 = '' for i in range(24): flag1 += rev_xor(ct1, key[len(key)//2:], i) ct2 = '' for i in range(6): ct2 += (long_to_bytes(ct[i+6])).decode() flag2 = '' for i in range(24): flag2 += rev_xor(ct2, key[:len(key)//2], i) flag = flag1 + flag2 print(flag)
実行結果は以下の通り。
key = H3ll0_tbh_Th15_15_7h3_k3y_F0r_7hi5_ch4ll3ng3_atb zh3r0{pyth0n_di54ss3mbly_byt3c0d3_i5_s0_aw350m3}
zh3r0{pyth0n_di54ss3mbly_byt3c0d3_i5_s0_aw350m3}
We are related (Crypto)
$ nc crypto.zh3r0.ml 9841 __ __ _ _ \ \ / /__| | ___ ___ _ __ ___ ___ | |_ ___ \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \ \ V V / __/ | (_| (_) | | | | | | __/ | || (_) | \_/\_/ \___|_|\___\___/|_| |_| |_|\___| \__\___/ ______ _____ ___ ____ _____ _____ |__ / |__ |___ / _ __ / _ \ / ___|_ _| ___| / /| '_ \ |_ \| '__| | | | | | | | | |_ / /_| | | |___) | | | |_| | | |___ | | | _| /____|_| |_|____/|_| \___/ \____| |_| |_| Enter the Selection from below: 1.Print PublicKey 2.Encrypt 0.Exit 1 -----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAl/DEzNkDSy545CVnRDY6 MvnY3uT9AqXvUawLjvPxkpGFvjNZgXUZDXz4d+OM+kI0wCitG/qKKyALNBCRV4H1 Ff032MF4M83DZauv9mekDRYTHt1kc3yjXGgkDKrbwx/52oK1zzjDpdL35+0DGrCV MuM6UUGmwULkt9pwkltaQ7CnK/mD8r9/kxCvYrsOdXKfG7oa6M8jmJ2Fg8KI30K7 BNLBQnrHEd+gk9cbeZO2EPfCgpeRBIkpN/m+wCaVeF4MhvHAqO7WY8HWGnWOXTvX s/s38/18neVZpi6sb+Xzd5bS3MXF6LAYnpsPFtlZQwkef0isv+fIbRehCBxOOXMO cwIBAw== -----END PUBLIC KEY----- - Enter the Selection from below: 1.Print PublicKey 2.Encrypt 0.Exit 2 Enter the string to encode: abcd Enc(flag + txt )= 8970069242936796240592467432599156013080215640242622142716638380716496388318218827228177466775343321619498071518451653744711981856521130553675889757562908518677580048412886296996915808378746450183982256985464602144653407697809249520698602827527280781562784845946163489064901426799558385428176157519796179474332484171830380047013723814868909474003768621828427343543355871057472154281785885153866549296559467827664976305001529862210453635791629571086504961684919394576382581049981522305048694616340885019017787650425307937177838677302828709346413542174337381942446754224559359173158887030894762785463508182475761729429
差異が小さい2つの平文を指定して得られた暗号文から、Franklin-Reiter Related Message Attackで復号する。
import socket import re from Crypto.PublicKey import RSA from Crypto.Util.number import * def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def related_message_attack(c1, c2, diff, e, n): PRx.<x> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+diff)^e - c2 def gcd(g1, g2): while g2: g1, g2 = g2, g1 % g2 return g1.monic() return -gcd(g1, g2)[0] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.zh3r0.ml', 9841)) data = recvuntil(s, 'Exit\n').rstrip() print data print '1' s.sendall('1\n') data = recvuntil(s, 'Exit\n').rstrip() print data pattern = '(-----BEGIN.+)\n-\n' m = re.search(pattern, data, re.DOTALL) pub_data = m.group(1) pubkey = RSA.importKey(pub_data) n = pubkey.n e = pubkey.e print '2' s.sendall('2\n') data = recvuntil(s, ': ') print data + '0' s.sendall('0\n') data = recvuntil(s, '\n').rstrip() print data c1 = int(data.split('= ')[1]) data = recvuntil(s, 'Exit\n').rstrip() print data print '2' s.sendall('2\n') data = recvuntil(s, ': ') print data + '1' s.sendall('1\n') data = recvuntil(s, '\n').rstrip() print data c2 = int(data.split('= ')[1]) m = related_message_attack(c1, c2, 1, e, n) - ord('0') flag = long_to_bytes(m) print flag
実行結果は以下の通り。
__ __ _ _ \ \ / /__| | ___ ___ _ __ ___ ___ | |_ ___ \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \ \ V V / __/ | (_| (_) | | | | | | __/ | || (_) | \_/\_/ \___|_|\___\___/|_| |_| |_|\___| \__\___/ ______ _____ ___ ____ _____ _____ |__ / |__ |___ / _ __ / _ \ / ___|_ _| ___| / /| '_ \ |_ \| '__| | | | | | | | | |_ / /_| | | |___) | | | |_| | | |___ | | | _| /____|_| |_|____/|_| \___/ \____| |_| |_| Enter the Selection from below: 1.Print PublicKey 2.Encrypt 0.Exit 1 -----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAl/DEzNkDSy545CVnRDY6 MvnY3uT9AqXvUawLjvPxkpGFvjNZgXUZDXz4d+OM+kI0wCitG/qKKyALNBCRV4H1 Ff032MF4M83DZauv9mekDRYTHt1kc3yjXGgkDKrbwx/52oK1zzjDpdL35+0DGrCV MuM6UUGmwULkt9pwkltaQ7CnK/mD8r9/kxCvYrsOdXKfG7oa6M8jmJ2Fg8KI30K7 BNLBQnrHEd+gk9cbeZO2EPfCgpeRBIkpN/m+wCaVeF4MhvHAqO7WY8HWGnWOXTvX s/s38/18neVZpi6sb+Xzd5bS3MXF6LAYnpsPFtlZQwkef0isv+fIbRehCBxOOXMO cwIBAw== -----END PUBLIC KEY----- - Enter the Selection from below: 1.Print PublicKey 2.Encrypt 0.Exit 2 Enter the string to encode: 0 Enc(flag + txt )= 13169774813221511932243873546844686383429967108387653396065460783119889477620840823513401679577611996837338005483588575134052478350079942715431961589620136843875590673217399575273596108447574506950030016546674713998660920813377509803665385450453818464732354501901994635510858425018006454080817781883348815744626138292034308959728140477817938045617359712978850536365597757007166295857825722644656280282334225559119248341906162439090046230116071626572773985654425634020373645249892360206543799112345973352843561359517466444973871246937018740694815587461488742430916233108821158490464189819556074363093373542390633034484 Enter the Selection from below: 1.Print PublicKey 2.Encrypt 0.Exit 2 Enter the string to encode: 1 Enc(flag + txt )= 7173580354976976582846590191301810085856396752549786919532282832533101326381038480413419787621164385989627028836508242290734402539094318654342082710202448254109164534425787618048338637638538182485709796170229306721213213871796048985877100141346650130649164671419423764444799227908522501862169358337016555547839809907903306641248006682666090175543733313599888473230020267536267560168443530120397567559212060988777001875141401939586720334705305599527225657558531710039260966722747077329579035916023580488134685249195364073768587522245963657969409482612377689329215793636904499387493478394264950062032110440994873062374 RSA is secure and all but the only thing I want to say is zh3r0{Hey_y0u_Sh0u1dn't_S3nd_r3l4ted_m3ssag3s_0r_h4v3_shot_p4ddings_wh3n_e_1s_sm411!!!!!}.
zh3r0{Hey_y0u_Sh0u1dn't_S3nd_r3l4ted_m3ssag3s_0r_h4v3_shot_p4ddings_wh3n_e_1s_sm411!!!!!}
Analyse me (Crypto)
サーバの処理概要は以下の通り。
・msgの長さは80 ・4バイトごとに以下を繰り返し、順に行う。 ・base64 ・base32 ・base85 ・hexlify →結果を数値化して、|区切りで表示
このことからmsgを求めることが可能。msgを正しく入力できたら、次のステージに進める。
・keyを表示 →final_keyに設定 ・list_flag: flagを4バイトごとに16進数表記した配列 ・rand_num = 2~4ランダム整数 ・flagの各文字について以下の処理を行う。 ・chr = <flagの4バイト16進数表記(8バイト)> ・rand_num回実行 ・chr=table[chr[0]][chr[1]]+table[chr[2]][chr[3]]+table[chr[4]][chr[5]]+table[chr[6]][chr[7]] ・final_listに追加 ・key_list: final_keyを4バイトごとに16進数表記した配列 ・xor_list: final_listとkey_listをXORしたデータを表示 ・フラグを入力したら、正しいかどうかをチェックできる。
key_listとkey_listをxorしたら、final_listになる。あとはテーブルの参照の仕方から元に戻して、先頭がフラグの先頭4バイトの16進数表記と同じになるまで戻す。
#!/usr/bin/env python3 import socket from Crypto.Util.number import * from Crypto.Util.strxor import strxor from binascii import * from base64 import * import string table = {'0':{'0':'63','1':'7c','2':'77','3':'7b','4':'f2','5':'6b','6':'6f','7':'c5','8':'30','9':'01','a':'67','b':'2b','c':'fe','d':'d7','e':'ab','f':'76'}, '1':{'0':'ca','1':'82','2':'c9','3':'7d','4':'fa','5':'59','6':'47','7':'f0','8':'ad','9':'d4','a':'a2','b':'af','c':'9c','d':'a4','e':'72','f':'c0'}, '2':{'0':'b7','1':'fd','2':'93','3':'26','4':'36','5':'3f','6':'f7','7':'cc','8':'34','9':'a5','a':'e5','b':'f1','c':'71','d':'d8','e':'31','f':'15'}, '3':{'0':'04','1':'c7','2':'23','3':'c3','4':'18','5':'96','6':'05','7':'9a','8':'07','9':'12','a':'80','b':'e2','c':'eb','d':'27','e':'b2','f':'75'}, '4':{'0':'09','1':'83','2':'2c','3':'1a','4':'1b','5':'6e','6':'5a','7':'a0','8':'52','9':'3b','a':'d6','b':'b3','c':'29','d':'e3','e':'2f','f':'84'}, '5':{'0':'53','1':'d1','2':'00','3':'ed','4':'20','5':'fc','6':'b1','7':'5b','8':'6a','9':'cb','a':'be','b':'39','c':'4a','d':'4c','e':'58','f':'cf'}, '6':{'0':'d0','1':'ef','2':'aa','3':'fb','4':'43','5':'4d','6':'33','7':'85','8':'45','9':'f9','a':'02','b':'7f','c':'50','d':'3c','e':'9f','f':'a8'}, '7':{'0':'51','1':'a3','2':'40','3':'8f','4':'92','5':'9d','6':'38','7':'f5','8':'bc','9':'b6','a':'da','b':'21','c':'10','d':'ff','e':'f3','f':'d2'}, '8':{'0':'cd','1':'0c','2':'13','3':'ec','4':'5f','5':'97','6':'44','7':'17','8':'c4','9':'a7','a':'7e','b':'3d','c':'64','d':'5d','e':'19','f':'73'}, '9':{'0':'60','1':'81','2':'4f','3':'dc','4':'22','5':'2a','6':'90','7':'88','8':'46','9':'ee','a':'b8','b':'14','c':'de','d':'5e','e':'0b','f':'db'}, 'a':{'0':'e0','1':'32','2':'3a','3':'0a','4':'49','5':'06','6':'24','7':'5c','8':'c2','9':'d3','a':'ac','b':'62','c':'91','d':'95','e':'e4','f':'79'}, 'b':{'0':'e7','1':'c8','2':'37','3':'6d','4':'8d','5':'d5','6':'4e','7':'a9','8':'6c','9':'56','a':'f4','b':'ea','c':'65','d':'7a','e':'ae','f':'08'}, 'c':{'0':'ba','1':'78','2':'25','3':'2e','4':'1c','5':'a6','6':'b4','7':'c6','8':'e8','9':'dd','a':'74','b':'1f','c':'4b','d':'bd','e':'8b','f':'8a'}, 'd':{'0':'70','1':'3e','2':'b5','3':'66','4':'48','5':'03','6':'f6','7':'0e','8':'61','9':'35','a':'57','b':'b9','c':'86','d':'c1','e':'1d','f':'9e'}, 'e':{'0':'e1','1':'f8','2':'98','3':'11','4':'69','5':'d9','6':'8e','7':'94','8':'9b','9':'1e','a':'87','b':'e9','c':'ce','d':'55','e':'28','f':'df'}, 'f':{'0':'8c','1':'a1','2':'89','3':'0d','4':'bf','5':'36','6':'42','7':'68','8':'41','9':'99','a':'2d','b':'0f','c':'b0','d':'54','e':'bb','f':'16'}} def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) def decode(msg, count): count = (count % 4) + 1 if count == 1: return b64decode(msg) elif count == 2: return b32decode(msg) elif count == 3: return b85decode(msg) else: return unhexlify(msg) def search(s): for a in string.hexdigits[:16]: for b in string.hexdigits[:16]: if table[a][b] == s: return a + b return '' def rev_rand(lst): rev = [] for e in lst: d = b'' for i in range(0, len(e), 2): d += search(e[i:i+2].decode()).encode() rev.append(d) return rev s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.zh3r0.ml', 3871)) data = recvuntil(s, b'message:') codes = data.split('\n')[-2].split('|')[:-1] msg = b'' for i in range(len(codes)): b = long_to_bytes(int(codes[i])) msg += decode(b, i) print(data + msg.decode()) s.sendall(msg + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data) key = long_to_bytes(int(data.split(' ')[-1])) data = recvuntil(s, b'DECODING!!! \n').rstrip() print(data) data = recvuntil(s, b'flag:') key_list = [hexlify(key[i:i+4]) for i in range(0, len(key), 4)] xor_list = eval(data.split('\n')[-2]) final_list = [strxor(i, j) for i, j in zip(xor_list, key_list)] for i in range(5): final_list = rev_rand(final_list) if final_list[0] == b'7a683372': break flag = unhexlify(b''.join(final_list)) print(data + flag.decode()) s.sendall(flag + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
Hello! Welcome to Xor analysis.. There are two parts. All the best ;) Here is the first part: 5943134639005711677|5491378081737038141|366970695973|3833466206172886320|5640277313745009981|5351739078059639101|302416945480|3762814891798442803|6354696933901548861|5139258452082510141|305635213400|3688506584576963897|5568232986773634365|5139251786226882877|357308525154|3847819437120304993|7008813202989464893|5786655223480211773|306693940071|3689633605503693413| Enter the decoded message:G00D_TH3_FIRST_P4RT_I5_D0N3_HER3_I5_4_F14G_F0R_Y0U_H4RD_W0RK_=_zh3r0{f4k3_f14g}. You have done well. Here is the key: 140262390255733908276964893730429404145946321017929888946337794323005965712203877415028 You completed the first part Here is the second and final part ;) GOOD LUCK DECODING!!! [b'\x01Z\nU\x05R\x06R', b'\x0b\t\x00RV\x04\x0e\x01', b'\x06\x0b\x00W\n\x06\x05W', b'\x07\x07\x01\\\x0e\x07\x04P', b'T\x01\x06W\x03\x04\x05R', b'\x04QS\x06\x0b\n\r_', b'W\x0b\x04P\x0cST\r', b'\nUS\x01\x01U\r\x00', b'\x05T\x03\x02\x05\x08\x03\x03'] Enter the flag:zh3r0{Y0u_4r3_4_v3ry_G00d_4nalys3r!} Perfect you got the flag ;) Go submit it!!!
zh3r0{Y0u_4r3_4_v3ry_G00d_4nalys3r!}
Uncipher Me (Crypto)
key.txtの内容をbase64デコードする。
N: GI3DONZWGQZDGMRVGEYDKOBVHE2DMMJYG4ZDANBTGA4TIMBRGEYTGMBZGM4TSMBYGI2TMMBQGU4DINJXGQ2TKNBQGA3TKNZSG43DMOBTHE2DIOJYG43DQMZWHE4TMMZZGQYTSMBTHEZDANJXHE4DMMJWGMYTENJSG44TCMZUHE4DINJQGQYTMNRWGM4TAMRXGM4TQNRUGIYTCMRZGI2DINBXGA3TSMRVGI4DCNZYG44DANZUGYYDMMBTGQ3DAOBXG4ZDGNJVHEYDSNBRHA2TKMJWGY4TOOJUGQ3TKOBTG44TOOBVGI4DOMJQGUZTMNBUGE4DONRZGAYTSOBTG44DAMZTGEZTCOJUGQ3DINZSGQZDONRTGY3DKOJTGEZDGOBVGE3TEOJSHA4TMNRVGMYDSMRWGA2DONJUG44TOMBXGEYDGMRXGUZTMOJVG4YDQNJVHA4DMNRRGMZTQNRWGI3DONZSGA3DCOJRGM3DANRTGY2TSMJUHA4DONZRGI3DKNZRGY2DCOJYGE3DSNZQGIYDQNZRGQZDMMBTHAZDANBXHE4TCMJZGA3TAMRTHEZTAMBVGAZDCNZUGY2TIMZSG4YTQMZWGE4DQOJXGAZTSOBSGY4TAOBTGM2TGNBZGI2DEMBRG44TGMZRHE3DKNZVGQ4DMNJZGI2DQNBXHA3DCNBZGA4DEMZTGYYTENBYGE4TEMRQGM4DOMBVGYYTKMJRGMZTEOBRGI2TQOBXGU2TKNBYGIYDMNBSGAYDGMJXHAZTEMRSGE3TQOBSGE4DMNJYGA2TOMJTGEZTENRYGM4DMMJQGI4DIMJYG4YTOOJUHE4DOOBQGIZTMMJWGM2TEOBXGI2TOOJSGM3TQOJRG4ZTIMRSGIYTOOJRGQYTINJYG43TGOBRGYZTGOBSHA3DQNZYGQZTSNBZGY3DAMZSGU3TGNBRGQZTCOBTGQ3TMMZUGQ2DGMZSGAYDAOJRGI2DSMJSGU3DINZTHEZQ==== e: GY2TKMZX ct: GB7kTHaRdkH#IRfHZ?RjH8(afGc-0eG&eLbI5IRiHaIplG&VOmGcz+eFf=(ZF)=hYH8D9dH83?ZH#9gnI59LaIW{seGc-9iGBP(YGB7YWIWaafIWspgHa0jnG%z_gIXE~mH90gjIW#yoIXE;iGdDRkI5jspH#jvjIWaRcGc_<ZGdVahH8?jmGB!0bH!?FfG&eUmF*!CdH#9UjHZ?FeFflhaFfceWGcz<bI5RggH!?OfHZwIgI5aXaH83_eG&4ClH#RXfH#IdiFgP?YH#askGBGzaFgQ3fI5{~oF*P<bF*PtTHZe9gI5apkIW#pnHZU|ZIXO5mHaImhHZd_XGBPtUFflYVIW#yqF*i9eH83+XH#apfGc`6gFg7qbHa9piHZ?LgGdVdjGBh+dHZe3gH90dkF*r6iIWaLgIW{&mIWaRbI5s&rI5RdkIWaLgHaIdcGBP(YG&nRjH#IgiGBP$dGc`FjG&nRfGB`3YI5;;lHZnFfG%++VF)}bSH#9UjFgZ9fGB+|XG&DIhGcq+fHa9RhFgP$XIXN;gGBP(bF)%VVFf}wdFf%bVH#9RgH#9aiHaIjeI5jykGc-3jG%+?XH!?IhG%_?YF*!6cF)}eWI59XhIXE#iI5jgfF*!3hH!v_WGB7zZI503WF)=nYHZ(FbHZd|VIW;gfFf}tcFgGwVF*P(bHa9pmGdM6cI5IgfGBh<ZGdVIfF*P(cH#s&mGB+|aF*h|bHZU+ZF*!6eGdVLkIX5{tGdMXnHZ(LhH#IOdI503XFf=hUG5
N, eはbase32、ctはbase85でデコードできる。NはFermat法で素因数分解できたので、そのまま復号する。
#!/usr/bin/env python3 import base64 from Crypto.Util.number import * def isqrt(n): x = n y = (x + n // x) // 2 while y < x: x = y y = (x + n // x) // 2 return x def fermat(n): x = isqrt(n) + 1 y = isqrt(x * x - n) while True: w = x * x - n - y * y if w == 0: break elif w > 0: y += 1 else: x += 1 return x - y, x + y with open('key.txt', 'r') as f: key = f.read() param = base64.b64decode(key).decode() N = int(base64.b32decode(param.split('\n')[0].split(' ')[1]).decode()) e = int(base64.b32decode(param.split('\n')[1].split(' ')[2]).decode()) ct = int(base64.b85decode(param.split('\n')[2].split(' ')[3]).decode()) p, q = fermat(N) phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(ct, d, N) pt = long_to_bytes(m).decode() print(pt)
この実行結果は以下の通り。
key: kD87Ef4y043nhee-W_Hytc0d3Bkiw4Gw21m-7AHpZkc= This is one of the keys for the encryption.Totally 3 keys to decrypt the encrypted text
次にkey_2.txtの内容をrot47で復号する。
key: iQZijGdoX0hepv2wnFZOUsTWU-v6xyGWyqSan_p75CE= Here's another key for the encryption. if you are a good cryptographer you can identify the common symmetric encryption.
さらにkey_3.txtの内容をVigenere暗号と推測して、https://www.guballa.de/vigenere-solverで復号する。
key: XeQVPB98P3fve4lJvfk345uARbNDE4F17NFZJBHC1dY= The last key and you can go decrypte the cipher, if you couldn't identify then see the starting part of the ciphertext, if the decryptions with the keys doesn't work then try rearranging the keys.
ct.txtの内容からFernat暗号であると推測でき、3つの各キーで復号を試す。
この結果key2を使って、Fernat暗号として復号することができた。
from cryptography.fernet import Fernet token = 'gAAAAABe5zDHy1Vk74P8AspzQ4bqK9dzfI52djZeMbsXRk8G5ng1BtYmDj7v6SCbx7cvnUFu2fDh6XTVtQPQqlJcVVCxGoA0P4L_gtSIGHQPLZysxuoN1E7kP_5lZFbZLo6b6G-YqFxs' key = 'iQZijGdoX0hepv2wnFZOUsTWU-v6xyGWyqSan_p75CE=' f = Fernet(key) flag = f.decrypt(token) print flag
zh3r0{Symm3tric_3ncrypti0n_i5_5tr0ng}