この大会は2022/4/23 15:30(JST)~2022/4/23 21:30(JST)に開催されました。
今回もチームで参戦。結果は991点で270チーム中54位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (MISC 1)
Discordに入り、#rulesチャネルのトピックを見ると、フラグが書いてあった。
CUCTF{L3T_TH3_G4M35_B3G1N}
Justin.tv (OSINT 70)
Sookhabournvitaで検索したら、Youtubeのチェンネルを見つけた。
https://www.youtube.com/channel/UCU3yIHO5WurwDtx6SAh8Inw
概要のリンクにある動画を見てみる。動画の途中でフラグが見えた。
CUCTF{L34K5_0N_57R34M5}
babyrev1 (REVERSE ENGINEERING 70)
Ghidraでデコンパイルする。
undefined8 main(void) { char *__dest; bool bVar1; ulong uVar2; char *__src; undefined8 uStack128; long local_78 [2]; basic_string local_68 [40]; char *local_40; long local_38; int local_2c; uStack128 = 0x10120d; std::operator<<((basic_ostream *)std::cout,"Input Flag: \n"); uStack128 = 0x101219; std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(); /* try { // try from 00101227 to 00101492 has its CatchHandler @ 001014ab */ uStack128 = 0x10122c; std::operator>>((basic_istream *)std::cin,local_68); uStack128 = 0x101238; local_2c = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(); local_78[0] = (long)(local_2c + 1); local_38 = local_78[0] + -1; local_78[1] = 0; uVar2 = (local_78[0] + 0xfU) / 0x10; local_40 = (char *)(local_78 + uVar2 * -2); (&uStack128)[uVar2 * -2] = 0x1012a9; __src = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>:: c_str(); __dest = local_40; (&uStack128)[uVar2 * -2] = 0x1012bb; strcpy(__dest,__src); (&uStack128)[uVar2 * -2] = 0x1012ce; bVar1 = std::operator!=(local_68,""); if (bVar1 != false) { if (local_2c == 0x1b) { if (((((((*local_40 == 'C') && (local_40[1] == 'U')) && (local_40[2] == 'C')) && ((local_40[3] == 'T' && (local_40[4] == 'F')))) && (local_40[5] == '{')) && (((((local_40[6] == 'W' && (local_40[7] == '3')) && ((local_40[8] == 'l' && (((local_40[9] == 'c' && (local_40[10] == '0')) && (local_40[0xb] == 'm')))))) && (((local_40[0xc] == '3' && (local_40[0xd] == '_')) && ((local_40[0xe] == '7' && ((((local_40[0xf] == '0' && (local_40[0x10] == '_')) && ((local_40[0x11] == 'R' && (((local_40[0x12] == '3' && (local_40[0x13] == 'v')) && (local_40[0x14] == '3'))))) ) && ((local_40[0x15] == 'r' && (local_40[0x16] == '5')))))))))) && (local_40[0x17] == '1')))) && (((local_40[0x18] == 'n' && (local_40[0x19] == 'g')) && (local_40[0x1a] == '}')))) { (&uStack128)[uVar2 * -2] = 0x101480; printf("Correct Flag!!"); } } else { (&uStack128)[uVar2 * -2] = 0x101493; printf("Wrong Flag"); } } (&uStack128)[uVar2 * -2] = 0x1014a4; std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string ((basic_string<char,std::char_traits<char>,std::allocator<char>> *)local_68); return 0; }
入力文字を1文字ずつ比較しているので、その文字を並べる。
CUCTF{W3lc0m3_70_R3v3r51ng}
sihT elipmoC (REVERSE ENGINEERING 200)
pycをデコンパイルする。
$ uncompyle6 out.pyc # uncompyle6 version 3.8.0 # Python bytecode 2.7 (62211) # Decompiled from: Python 3.6.9 (default, Mar 15 2022, 13:55:28) # [GCC 8.4.0] # Embedded file name: out.py # Compiled at: 2022-04-09 06:54:01 def fun(a, b): f = a ^ b s = pow(f, a, b) return s def fun2(x, y): ans = x ^ y return ans f = open('flag.txt', 'r') a = f.readline() j = 2 k = j + 2 output = '' for i in range(len(a)): s1 = fun(j, k) s2 = fun2(s1, ord(a[i])) output += chr(s2) j += 2 k = j + 2 f1 = open('output.txt', 'w') f1.write(output) f1.close() # okay decompiling out.pyc
このことを元に、フラグを復元する。
#!/usr/bin/env python3 def fun(a, b): f = a ^ b s = pow(f, a, b) return s def fun2(x, y): ans = x ^ y return ans with open('output.txt', 'r') as f: output = f.read() j = 2 k = j + 2 flag = '' for i in range(len(output)): s1 = fun(j, k) s2 = fun2(s1, ord(output[i])) flag += chr(s2) j += 2 k = j + 2 print(flag)
CUCTF{unc0mp1l3d}
PHP Trickster (WEB 200)
'phpcanbetrickysometimes'を''に置換しても、'phpcanbetrickysometimes'になるよう間に入れた文字列を指定する。
first_answer=phpcanbephpcanbetrickysometimestrickysometimes
http://13.233.100.207/bsdfbysvfgys.phpにアクセスすると、以下のようなメッセージが表示される。
Awesome! Now proceed to the next level. Visit /chicken-dinner.php
http://13.233.100.207/chicken-dinner.phpにアクセスすると、次のPHPの問題が出題される。
今度はmd5の値が==で"0"と等しくなるものを指定すればよい。
例えば、240610708の場合、0e462097431906509019562988736854となり、0と同等。http://13.233.100.207/chicken-dinner.php?secondanswer=240610708にアクセスすると、以下のようなメッセージが表示される。
You did it! CUCTF{PHP_1S_TR!CKY_BUT_!MP0RT4NT}
CUCTF{PHP_1S_TR!CKY_BUT_!MP0RT4NT}
Beluga's secret (STEGANOGRAPHY 70)
Audacityで開き、スペクトログラムを見ると、フラグが現れた。
1N5PECT1NG_7H3_SP3CT0GR4MS
CUCTF{1N5PECT1NG_7H3_SP3CT0GR4MS}
Abracadabra Magic (STEGANOGRAPHY 100)
PNGファイルのヘッダが壊れているので、修正する。
4a 50 45 47 -> 89 50 4e 47
さらに末尾にはごみが入っているので、取り除く。修正したPNGファイルをStegSolveで開き、Red plane 2を見ると、フラグが現れる。
CUCTF{1S_1T_H1DD3N_3N0UGH?}
Skittle-chan's secret (CRYPTOGRAPHY 70)
Discordでskittle-chanボットに以下のDMを投げる。
!flag
以下の応答があった。
Uh-- uhm--- do i have it? Decode THIS >>>> aGVja3VyIGdhdmUgbWUgYSBrZXkgIiRzdWRvIGhlY2sgaGVja3VyIg== Hint :blush: : Bases turn red litmus paper blue!
$ echo aGVja3VyIGdhdmUgbWUgYSBrZXkgIiRzdWRvIGhlY2sgaGVja3VyIg== | base64 -d heckur gave me a key "$sudo heck heckur"
今度は以下のDMを投げる。
$sudo heck heckur
すると以下の応答があった。
Oh wow!! :heart_eyes: Bu-- But this is not the end.... Keep trying! :wink: Here is your next challenge. >>>> #Orthytn_tvi_synt_cyf_hjh Hint : Beluga rotates around the flag or is it the other way round?
シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。
ROT13 #Begulga_giv_flag_pls_uwu
今度は以下のDMを投げる。
#Begulga_giv_flag_pls_uwu
すると以下の応答があった。
Managed to solve that too? :heart_eyes: :heart_eyes: :heart_eyes: I think i have to throw something more salty! :wink: :face_with_hand_over_mouth: Okay. Solve this! :smirk: >>>> DYNNL{Slmenre_msgyy_bfkfara_dsk_vkgvpl_cy_tii_myyt} FACT: Belu/Begugla`s real name is "Beluga"
Vigenere暗号。https://www.dcode.fr/vigenere-cipherで復号する。
鍵はBELUGA。
CUCTF{Skittle_loves_begugla_coz_begula_is_the_best}
Romeo Santos Amigo (CRYPTOGRAPHY 200)
n = p * q f = (p + q) * p = p ** 2 + n
n, fがわかっているので、pを算出できる。qもわかるので、あとはそのまま復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * import gmpy2 n = 11829886750485477875976635072018090905143443625007546794348497637966197279803681213779006459999746001196971426170849463947098364679127042949733914239579104586870722387114340480000486856505649674159770197506405951312626957318515896751767047062828839549974251678347976185495852674150282088401081165333834461071224526054075524891724970500077599114868606849229149187142341846051527710265752567974703774179138223020001489651131113721765229046264198068712659964490412666162428987002387692631015099403880204125842922799024065172364105218572478815185466933632832934972516132474664570985119914475072648885508244964020524399053 f = 20043009015985698100425274947483305876785498175015449361182182417373035151653086573036155733253044537568811200485247118262264159846001127988203128268971273737956995677175065567379060331866330565896616577747421528604583105194539099675088529204429423364238272532358443699593880949743306523057388833615446729693504763564236862533691242407058582727871791364492231151285880449861165764374968357317223326722079234280155917463431388210349115191828122932453215979076470629530940642049833751942988818180451773645576734459003809686228170008273943185203268076716312410237373925376218933795301756901875959064459973014819534965734 c = 797073641485868004817216562170655455035575406588406652196942486967584215459893094533869888868503189461184119339856836498920166781639768351027919077118462077303982791831632122628673038236983663558470883953241953414646314480971601889852350674583308477166067573190459828689466309957397059077868419835940038633609014280898238950919351159762301810840683827179829257077915691935483135181184077726634138367723588715592565453940927603481342507466629361299663182223554674989869928484376734029297350761412822198777372704066055309236759459950636661393795865613239596796507963896308065878136758416960367988318034971930081770122 e = 65537 p = gmpy2.iroot(f - n, 2)[0] q = n // p assert p * q == n phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
CUCTF{y0u_4r3_b3773r_cryp70gr4ph3r}
Feedback (MISC 10)
アンケートに答えたら、フラグが表示された。
CUCTF{Th4nk_y0u_f0r_j01n1ng}