この大会は2022/4/8 19:00(JST)~2022/4/9 19:00(JST)に開催されました。
今回もチームで参戦。結果は874点で368チーム中34位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (baby)
base64デコードする。
$ echo RU5Pe1dFTENPTUVfVE9fTlVMTENPTl9DVEZ9Cg== | base64 -d ENO{WELCOME_TO_NULLCON_CTF}
ENO{WELCOME_TO_NULLCON_CTF}
cookie lover (cry)
サーバの処理概要は以下の通り。
・msg = 'I love cookies.' ・key: RSA秘密鍵 ・以下繰り返し ・cmd: メニュー選択 ・cmd[:2] == b'1:'の場合 ・sign(cmd[2:])の結果を表示 ・cmd[2:]にb'cookie'が含まれていたら、0を返す。 ・cmd[2:]に各バイト文字のコードが32より小さいものがあったら、0を返す。 ・pow(bytes_to_long(cmd[2:]), d, n) ・cmd[:2] == b'2:'の場合 ・verify(int(cmd[2:].decode()))の結果を表示 ・bytes_to_long(msg) == pow(int(cmd[2:].decode()), e, n)の場合、フラグを返す。
msgの数値化した値を素因数分解し、それぞれの値の復号値の掛け算をしたものがmsgの復号値になる。このことをスクリプトにして、フラグを取得する。
msgの数値 = 2 * 5 * 6673 * 189344417922901 * 30051184098398543
1バイトごとの数値が32より小さいものがないようにすることを考慮して、以下のように組み合わせる。
>>> '%x' % (2 * 5 * 6673 * 189344417922901) 'af585ed1634e6272' >>> '%x' % 30051184098398543 '6ac3648943d14f' msgの数値 = (2 * 5 * 6673 * 189344417922901) * 30051184098398543
#!/usr/bin/env python3 import socket from Crypto.Util.number import * from Crypto.PublicKey import RSA def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) msg = 'I love cookies.' i_msg = bytes_to_long(msg.encode()) assert i_msg % 2 == 0 with open('pubkey.pem', 'r') as f: pub_pem = f.read() pubkey = RSA.importKey(pub_pem) n = pubkey.n s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('52.59.124.14', 10301)) i_msg1 = 2 * 5 * 6673 * 189344417922901 i_msg2 = 30051184098398543 assert i_msg == i_msg1 * i_msg2 msg1 = long_to_bytes(i_msg1) msg2 = long_to_bytes(i_msg2) data = recvuntil(s, b'check]\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data) cmd1 = b'1:' + msg1 print(cmd1) s.sendall(cmd1 + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) c1 = int(data) data = recvuntil(s, b'check]\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data) cmd2 = b'1:' + msg2 print(cmd2) s.sendall(cmd2 + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) c2 = int(data) data = recvuntil(s, b'check]\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data) c = (c1 * c2) % n cmd3 = b'2:' + str(c).encode() print(cmd3) s.sendall(cmd3 + b'\n') data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
Choose an option: 1:[text to sign] 2:[number - signature to check] b'1:\xafX^\xd1cNbr' 325690727908661499309661798673134746525549931298526474206266022934601444708113047135538801328273183297655028939045499865404394823941240366064657468406941255955543239155462791788307004634331285485892917231231535154491480414174110780962202278496000932209175962032151237886596020914761101015606206893177904134713327192496525522973087334386489302244577603477091685695503257531016400169510979360508202905327850786665513071465331459167490648236114913457458979699134001127868136528012905568773910174487093556652184961183575109149941636305890323261605585481820984155205006869910027003730275723789202922476747279116413984761934121175634970596086140934920675738310431675513690082442869526858283838789816550273821346287346247705433357168442589963315788300739505889843762042516200701415034107391026223313860185806426680409603345861645877984652881067094328071044764946477238165736269428785099544134006057946961512482428478101621396328497532118337656844687710248423996821791509608367788650054029785629740188415994398629373996648229976382156946666818287824516294737657584859221147520073523918224710415748442782455079832736893891124063604720331349499371222833636810873692673580690201751213383218525203673097913454100392088940949006666473385795391405 Choose an option: 1:[text to sign] 2:[number - signature to check] b'1:j\xc3d\x89C\xd1O' 208198990457945937850609311949608176940012395585539332857257067088968427765226163105859687045659561311594400130540516324714817279401844231629262039240904353095416052352496624630113295859222371130952078485039577334384466107875635753028354946420390098694645736246658854182214672336881314799660743325422065712289502420823736493097608814506814256224506757621157275144001135782191054555391441361338471890537154199941992003533221046511955718140429145618768496493555842382918609047753848418895683548356612656999584272503410562983108698153938413445184343582536960274615998732804465232528115930925501201440604777047927165194658124970222970361692822147825046137833768228200005349167259989260725956184603808237558364594206141109794131971913136203898250335845941797424497471833855184786585773711086768133398324593827071277030767872613010460903209647660757178737420249612734974747196142519046313575163675183695056555150040849643757943916749567302853548309927504155366045862962743975056260881143894235457241631234157217478981887233851117304041174464144889252285820478077989914532082803208048645316784315822729581069884421571288419110534658097386516170522447330669376592657176021898629534711821414172468669721575071589053669414994342633548028257950 Choose an option: 1:[text to sign] 2:[number - signature to check] b'2:183715238308397635712374225419373805798742055683226422934080084912571963507041250961583553698774247650805521395803139201549546155514498290541895722622526436040024047904660300222065763712351217474928376850784630905553758858190205688837414953457818339523500001823621579084464449491627975153761076059266019332369948606754941770662639776141799102648900815323489156665596632472281491282410300991241823300454592922461162611382496591490550609271962691628152420985917389235738904080699097528791626413835794266350039503418910923006851517224066201307979706970243349020918755341888204032054136258892397118667475213806953074733426062459693660535346560600965189675021611731714089952250296904007231831487782499114621964969534223196097402736888347041882248897823173621222165816190410685609663388419181176124525018049553548103350701273672763892456783772563315621245515637664525782066737220163193595126710707023308068862240772717620707827931707550917607230887757066852815460593413638711731996164882740050526557868528818690008964887793725631236051966033348445245363394748484485498232392925138253100412827331658375963317501552336516833908072999587184562493624756880635192816071931270468844048857769080593876604160303151379277321929506581398341475479232' ENO{F4ct0r_and_Conqu3r!}
ENO{F4ct0r_and_Conqu3r!}
Magic words (cry)
サーバの処理概要は以下の通り。
・srand(time(0)); ・12回以下を繰り返す。 ・index: ランダム12未満数値 ・targetにmagic_words[index]を結合 ・targetに" "を結合 ・targetに"egg -- give me the flag!"を結合 ・targetを表示 ・inputStr: 入力(1024バイト以下) ・n: 固定値(既知) ・signature: inputStrの数値 ・m = pow(signature, 3, n) ・char* message = int_to_str(m); ・strcmp(message, target) == 0の場合、フラグを表示
mの文字列化が
#!/usr/bin/env python3 import socket import re import gmpy2 from Crypto.Util.number import * def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) n = 618017787734894212297412626251373685391953260761562256145235489725638613940584232503544382290786003502312209667905128601350448023284044287685001349014156076694914712630398005605673740514051697161500094865589407030636020089742702469018865286861672757837780829537694996694833864683805379159042221723723842387709902526369317372614408759564577441603426577837263761362135010436432956275299236838020581149454958441919492440492313018496438498099089383812883390835577605611991978206224568903757920872823293843687276713402767349404190867763874002307512458092607168715450826196573891917818134117192644486518276385456954928916750027466243826789735151096947239658610479195958319740857188397997117968901882796441973903340603204071299778964190138301428335590196310114790206400024512865068139543501059161433303153043130579702895687471084173256419199357102357728600646492441278405167508180066175830384059728198376079159561904247074846373084032155551839906550032001949969880315993549738076287202881585332049659570380033962200120029734918281696120171036422629762465758525540626266912510777059762980057239483211399081674862153728665111324068484754456207003656318475064950873727298779453666117120500091671142668282469471670064268176600698035510728754159 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('52.59.124.14', 10302)) data = recvuntil(s, b'number.\n').rstrip() print(data) pattern = b'"(.+)"' m = re.search(pattern, data.encode()) target = m.group(1) target += b'\x00' * 256 c = bytes_to_long(target) m = int(gmpy2.iroot(c, 3)[0]) + 1 print(m) s.sendall(str(m).encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
You think you can give me orders? Prove your authority by signing: "spam ham mike holy pteng mike pteng moly moly pteng ene moly egg -- give me the flag!" I want the signature as decimal number. 4181321586603772534793357116592013204177518788955354274759485758634250435240920991719187402108130848481412597142621465930044162030324501918549598769751084475013644442314335348243421214275827733923475024407420375384957499465874028037432088251822128037165226893884317905590494 You were right. Here is your flag: ENO{c0mp4re_th3_whol3_length}
ENO{c0mp4re_th3_whol3_length}