この大会は2022/9/10 1:00(JST)~2022/9/12 1:00(JST)に開催されました。
今回もチームで参戦。結果は1787点で884チーム中128位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome (misc)
Discordに入り、#rulesチャネルでリアクションすると、新しいチャネルが現れる。#announcementsチャネルのトピックを見ると、フラグが書いてあった。
flag{c54w_f1n4l5_15_1n_p3r50n_y4y}
Quantum Leap (misc)
フラグは"flag{"から始まり、"}"で終わるので、該当する文字の2進数を比較する。
>>> bin(ord('f')) '0b1100110' >>> bin(ord('w')) '0b1110111' 下0, 4bit反転 下1, 3, 5bit -> 1, 0, 1 >>> bin(ord('l')) '0b1101100' >>> bin(ord('x')) '0b1111000' 下2, 4bit反転 下1, 3, 5bit -> 0, 1, 1 >>> bin(ord('a')) '0b1100001' >>> bin(ord('q')) '0b1110001' 下4bit反転 下1, 3, 5bit -> 0, 0, 1 >>> bin(ord('g')) '0b1100111' >>> bin(ord('v')) '0b1110110' 下0, 4bit反転 下1, 3, 5bit -> 1, 0, 1 >>> bin(ord('{')) '0b1111011' >>> bin(ord('n')) '0b1101110' 下0, 2, 4bit反転 下1, 3, 5bit -> 1, 1, 1 >>> bin(ord('}')) '0b1111101' >>> bin(ord('i')) '0b1101001' 下2, 4bit反転 下1, 3, 5bit -> 0, 1, 1
以下の法則で変換されていると推測できる。
・下1bitが1の場合、下0ビットを反転 ・下3bitが1の場合、下2ビットを反転 ・下5bitが1の場合、下4ビットを反転
これを元に復元する。
#!/usr/bin/env python3 with open('output', 'r') as f: data = f.read().rstrip() flag = '' for d in data: b = bin(ord(d))[2:].zfill(8) b = list(b) if b[2] == '1': b[3] = str(int(b[3]) ^ 1) if b[4] == '1': b[5] = str(int(b[5]) ^ 1) if b[6] == '1': b[7] = str(int(b[7]) ^ 1) b = ''.join(b) flag += chr(int(b, 2)) print(flag)
flag{4_qu4ntum_g4t3}
DockREleakage (rev)
docker imageのtar.gzを展開し、確認する。repositoriesを見る。
{"dockre-chal":{"latest":"928ab519cd995aeae5eced3dbe4b7e86c8bc7f7662ef0f73e59c2f30b2b3b8e4"}}
928ab519cd995aeae5eced3dbe4b7e86c8bc7f7662ef0f73e59c2f30b2b3b8e4のlayer.tarを展開し、chal/flag.txtを見る。
73c73d_w17h1n_7h3_d0ck3rf1l3} Find the rest of the flag by yourself!
フラグの後半が見つかった。次にacbb216b17482071caca135101282177f6ffed7b8ee0bfc5323aae103c216d74.jsonを見る。この中のデータの一つに以下のデータがある。
{"created":"2022-09-03T07:46:12.680399343Z","created_by":"/bin/sh -c echo \"ZmxhZ3tuM3Yzcl9sMzR2M181M241MTcxdjNfMW5mMHJtNDcxMG5fdW5wcjA=\" \u003e /dev/null","empty_layer":true}
base64文字列をデコードする。
$ echo ZmxhZ3tuM3Yzcl9sMzR2M181M241MTcxdjNfMW5mMHJtNDcxMG5fdW5wcjA= | base64 -d flag{n3v3r_l34v3_53n5171v3_1nf0rm4710n_unpr0
先ほどのフラグの後半部と結合すると、フラグになる。
flag{n3v3r_l34v3_53n5171v3_1nf0rm4710n_unpr073c73d_w17h1n_7h3_d0ck3rf1l3}
Word Wide Web (web)
http://web.chal.csaw.io:5010/stuffにアクセスすると、たくさんの単語が表示される。その中に一つの単語だけリンクがあるので、アクセスしてみる。すると、またたくさんの単語が表示され、その中に一つの単語だけリンクがある。繰り返し、リンクをたどる処理をスクリプトにし、実行する。
#!/usr/bin/env python3 import requests import re s = requests.Session() url = 'http://web.chal.csaw.io:5010' path = '' while True: r = s.get(url + path) body = r.text pattern = '\<a href="(\/.+)"\>' m = re.search(pattern, body) if m is None: print(body) break path = m.group(1)
行きついたところにフラグがあった。
CTF{w0rdS_4R3_4mAz1nG_r1ght}
Gotta Crack Them All (crypto)
keyとXORを取っている。パスワードの一つが"Cacturne-Grass-Dark"とわかっている。
$ nc crypto.chal.csaw.io 5002 You can encrypt a pre-approved password using this service. What is the password you would like to encrypt? >> Cacturne-Grass-Dark The encrypted password is: b'kz\xc6\xb9\xd9Du\xcb\x8a\x9e\xe0\x9d\xbeo\xee\x03\xcf\xddd' Would you like to go again? (Y/N)
暗号化リストの6行目が該当の暗号だとわかるので、XORでキーを割り出し、復号する。鍵の長さが不足しているので、推測して復号する。37行目から以下のように推測し、XORでキーを割り出し、再度復号する。
b'Hakamo-o-Dragon-Fig\xd5\xe3wj0' → b'Hakamo-o-Dragon-Fighting'
#!/usr/bin/env python3 from Crypto.Util.strxor import strxor from string import * with open('encrypted_passwords.txt', 'rb') as f: words = f.read().splitlines() with open('leaked_password.txt', 'r') as f: leaked = f.read() key = strxor(words[5], leaked.encode()) for word in words: password = strxor((key * 2)[:len(word)], word) print('[-]', password) # guess key += strxor(words[36][len(key):], b'hting') for word in words: password = strxor((key * 2)[:len(word)], word) print('[+]', password)
実行結果は以下の通り。
[-] b'Kingler-Water' [-] b'Darkrai-Dark' [-] b'Chingling-Psychic' [-] b'Happiny-Normal' [-] b'Clawitzer-Water' [-] b'Cacturne-Grass-Dark' [-] b'Slowking-Poison-Psy\xde\xffwg' [-] b'Sneasel-Dark-Ice' [-] b'Hoopa-Psychic-Ghost' [-] b'Rhyperior-Ground-Ro\xde\xfc' [-] b'Seedot-Grass' [-] b'Chinchou-Water-Elec\xc9\xe5wg' [-] b'Tsareena-Grass' [-] b'Excadrill-Ground-St\xd8\xf2r' [-] b'Gumshoos-Normal' [-] b'Kricketune-Bug' [-] b'Dartrix-Grass-Flyin\xda' [-] b'Pikipek-Normal-Flyi\xd3\xf0' [-] b'Dugtrio-Ground-Stee\xd1' [-] b'Basculin-Water' [-] b'Hippowdon-Ground' [-] b'Togetic-Fairy-Flyin\xda' [-] b'Finneon-Water' [-] b'Riolu-Fighting' [-] b'Entei-Fire' [-] b'Spritzee-Fairy' [-] b'Mantine-Water-Flyin\xda' [-] b'Silvally-Normal' [-] b'Bellsprout-Grass-Po\xd4\xe4qj' [-] b'Wyrdeer-Normal-Psyc\xd5\xfe}' [-] b'Marill-Water-Fairy' [-] b'Herdier-Normal' [-] b'Altaria-Dragon-Flyi\xd3\xf0' [-] b'Thwackey-Grass' [-] b'Spewpa-Bug' [-] b'Bronzong-Steel-Psyc\xd5\xfe}' [-] b'Hakamo-o-Dragon-Fig\xd5\xe3wj0' [-] b'Chespin-Grass' [-] b'Mr. Mime-Psychic-Fa\xd4\xe5g' [-] b'Tornadus-Flying' [-] b'Pupitar-Rock-Ground' [-] b'Combusken-Fire-Figh\xc9\xfepc' [-] b'Guzzlord-Dark-Drago\xd3' [-] b'Carnivine-Grass' [-] b'Growlithe-Fire' [-] b'Grubbin-Bug' [-] b'Gastrodon-Water-Gro\xc8\xf9z' [-] b'Goomy-Dragon' [-] b'Thievul-Dark' [-] b'1n53cu2357234mc1ph3\x8f' [-] b'Seadra-Water' [+] b'Kingler-Water' [+] b'Darkrai-Dark' [+] b'Chingling-Psychic' [+] b'Happiny-Normal' [+] b'Clawitzer-Water' [+] b'Cacturne-Grass-Dark' [+] b'Slowking-Poison-Psychic' [+] b'Sneasel-Dark-Ice' [+] b'Hoopa-Psychic-Ghost' [+] b'Rhyperior-Ground-Rock' [+] b'Seedot-Grass' [+] b'Chinchou-Water-Electric' [+] b'Tsareena-Grass' [+] b'Excadrill-Ground-Steel' [+] b'Gumshoos-Normal' [+] b'Kricketune-Bug' [+] b'Dartrix-Grass-Flying' [+] b'Pikipek-Normal-Flying' [+] b'Dugtrio-Ground-Steel' [+] b'Basculin-Water' [+] b'Hippowdon-Ground' [+] b'Togetic-Fairy-Flying' [+] b'Finneon-Water' [+] b'Riolu-Fighting' [+] b'Entei-Fire' [+] b'Spritzee-Fairy' [+] b'Mantine-Water-Flying' [+] b'Silvally-Normal' [+] b'Bellsprout-Grass-Poison' [+] b'Wyrdeer-Normal-Psychic' [+] b'Marill-Water-Fairy' [+] b'Herdier-Normal' [+] b'Altaria-Dragon-Flying' [+] b'Thwackey-Grass' [+] b'Spewpa-Bug' [+] b'Bronzong-Steel-Psychic' [+] b'Hakamo-o-Dragon-Fighting' [+] b'Chespin-Grass' [+] b'Mr. Mime-Psychic-Fairy' [+] b'Tornadus-Flying' [+] b'Pupitar-Rock-Ground' [+] b'Combusken-Fire-Fighting' [+] b'Guzzlord-Dark-Dragon' [+] b'Carnivine-Grass' [+] b'Growlithe-Fire' [+] b'Grubbin-Bug' [+] b'Gastrodon-Water-Ground' [+] b'Goomy-Dragon' [+] b'Thievul-Dark' [+] b'1n53cu2357234mc1ph32' [+] b'Seadra-Water'
この中からadminのパスワードと思われる、ポケモンのモンスター名でないものがフラグ。
1n53cu2357234mc1ph32
Phi Too Much In Common (crypto)
$ nc crypto.chal.csaw.io 5000 ********** TOO MUCH IN COMMON ********** Have at it! /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 66230379529365020257079274492974065493126330971013187062230550667484536336498921190934189244362957312249586769969174687366278892047021464836842536529323843984917711253546999262427337059964746457287003004612989077687496386808318868155443955433495669933416861831960406309846051654977485404679018836950591207073 e = 3203033219058218846809870595889303749356759660802874921757919347285050689023 c = 16602634789029238804962653840385596228672793718393061759190379436477434589539439401344810124749337507914027486814367920958698864422367836842000865838169143446244202199945258912479805482529460471614475452210103481314126501905118652422131330354981855680471366776223771244856426005553912820240798175126871245542 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 97158515552243305887166842257349497196761944723849796333314570210192465467248058977973817520811466238434579242618470413011446370885671769783517122178886737136267378478851110781637707375501871752419723352747812903232025026662684439394479235396634760931569159089432041476376506570454407306279469567609447874133 e = 18408112354007983870269760119469358714794425138855862698209283717095203251527 c = 40597559051967819648988812970676624339815299554173974340185756834851649772498697096416499057158638069790189014561709885506503658509085168258788719816632907655273832559720389170846504255470221971178328064025401908633312901398161846240306537659732243916190526957713561623469784228736357566604931785270598213207 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 77552624443207359646089700308292520363775651928919510316405587244412029459793814355599651363969705936241997624014034446410130409040520904704222288741418451869075450281604530862820189902262119380780789529627644683074820698307434013253176331127640530460518445472446585030342275865032619556106417427541045657889 e = 8290673712481114196337956497649210842364305631913472623568114174185580849831 c = 62227187843422899487768810431178945148094010586999335663611835937007997481020063524535949914284336751562242177109249354250522379832825592726182607445470462086490320419744326295588542630205868022550363635863255848462379142157715139645979242744412831701661714996123243796658849718267858779823092830129715228493 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 66230379529365020257079274492974065493126330971013187062230550667484536336498921190934189244362957312249586769969174687366278892047021464836842536529323843984917711253546999262427337059964746457287003004612989077687496386808318868155443955433495669933416861831960406309846051654977485404679018836950591207073 e = 6461914606527340033058068371191892105920231183404124838916730227375848219991 c = 61747655950367328690845311363491999477172913254413763024768230345790552599866557902469338036025727322620488230742095151608347464525375842535363889225896691398096757040997363089905454473662909295617645290221572120790915100723370598403902217780692569984791434842099938496690776449770494327844731248133766400182 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 2 12345678 Nope!
何回かciphertext_infoを取得すると、同じNで異なるeで暗号化したcが得られる。Common Modulus Attackで復号する。
これをクリアすると、phiを計算する問題が出題される。N, e, dがわかっているので、phiを算出し答える。
#!/usr/bin/env python3 import socket import gmpy2 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) def commom_modulus_attack(c1, c2, e1, e2, n): gcd, s1, s2 = gmpy2.gcdext(e1, e2) if s1 < 0: s1 = -s1 c1 = gmpy2.invert(c1, n) elif s2 < 0: s2 = -s2 c2 = gmpy2.invert(c2, n) v = pow(c1, s1, n) w = pow(c2, s2, n) x = (v*w) % n return x s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.chal.csaw.io', 5000)) ns = [] es = [] cs = [] while True: data = recvuntil(s, b'\n> ') print(data + '1') s.sendall(b'1\n') data = recvuntil(s, b'\n').rstrip() print(data) N = int(data.split(' ')[-1]) data = recvuntil(s, b'\n').rstrip() print(data) e = int(data.split(' ')[-1]) data = recvuntil(s, b'\n').rstrip() print(data) c = int(data.split(' ')[-1]) if N in ns: index = ns.index(N) e1 = es[index] e2 = e c1 = cs[index] c2 = c m = commom_modulus_attack(c1, c2, e1, e2, N) try: password = long_to_bytes(m).decode() break except: ns.append(N) es.append(e) cs.append(c) else: ns.append(N) es.append(e) cs.append(c) data = recvuntil(s, b'\n> ') print(data + '2 ' + password) s.sendall(b'2 '+ password.encode() + b'\n') data = recvuntil(s, b'\n> ') N = int(data.splitlines()[6].split(' ')[-1]) e = int(data.splitlines()[8].split(' ')[-1]) d = int(data.splitlines()[10].split(' ')[-1]) rsa = RSA.construct((N, e, d)) p = rsa.p q = rsa.q phi = (p - 1) * (q - 1) print(data + '2 ' + str(phi)) s.sendall(b'2 '+ str(phi).encode() + b'\n') for _ in range(5): data = recvuntil(s, b'\n').rstrip() print(data)
実行結果は以下の通り。
********** TOO MUCH IN COMMON ********** Have at it! /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 92599299343232292261834178543890237387484921511614229653415119150379025672557158079593766699105621305545121399064580043995019950138120667405208241479131905776463986888676538577986955456126293031500188512827288084619006072487276385597167984228025224038068741864645024709036190735173856986216816635205617371251 e = 16928907533626229902284227783657840508336857921783474343555553116847230865331 c = 79570849854711607139417345642388677273839703713555430342321535812820875952624829829228862056309772593548873488031858181225277251937313263316901165117441026524819040228237484837355605354466786258483584226934759111747348086470492341818531267980922417619965568267394278979803974326580670936121922143960459533798 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 66841426676804688396771769972561843618412039028675927408156721898462403499632272355018096006084265389119375725460220991982054036255312770486606664268573532988575589293219994782714415202818755031344902659461329975751170875314154800578771280759291227371080846206675137271359015081773571314195744455213154427597 e = 20643168474203546933298257670240213719583351519179679768833156342247300184973 c = 34367729465156325930897062256052971848240755538905676844390968630323096992780138935126484933870426892930284766886879143689207515309637107833249240440322560307519059504083894525893593615656325221819307854771539020472177848929350810915040438732916654817910816704684422906316608152236582001686917198854494566951 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 93150654553270961014768164130409121928813076081873161613053090131547851938714893597908885804564067189857086242620569580714858215239915642529188260181294150027598408092318846514660800971605904900252102919761867835829741604253924392570808908720438859080776198561197727644262517765355363081126013877332755639777 e = 14564002562960621555096419172124728966001366362068142277514940102932321715587 c = 26823373791497368615326329325823097570538826785067685635320982007306494352439874098201830966485969176118141362926620739747065514898346909721894614163220613190756377329935483173296178692954012036304274932386801987084207773762448597756225917999340679191286184229577288745713915917134865116686254096088755399915 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 97934790717457816377408047595808017336290557647132874078463273042273480783693965913047913569035873972956920187266096013384149733128634153495383667005783367406343085928898092741457647502175596143302932648245342944432576818196386356562830861689797976228719838904175290216793497280116034968767061763793356427923 e = 17026356965343564383006139344035147997574236973261931055393297574271594721947 c = 36422996639906934280791759292864646158321891131994714018774979799204112699817423912629655615142621165865073844048825501188197026566655735034651136290222437988406549568072738686120589143594127844448881834208636747038354360336434517062474426581430949103364256096272027091751555393826040970441807243209096030970 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 1 N = 93150654553270961014768164130409121928813076081873161613053090131547851938714893597908885804564067189857086242620569580714858215239915642529188260181294150027598408092318846514660800971605904900252102919761867835829741604253924392570808908720438859080776198561197727644262517765355363081126013877332755639777 e = 3903045633246461963443996627866752963174454790408982275112905147194381029419 c = 63047438524847764130018540464138007337825148721616052463529587222913141611318978605784743617174005749795694486145667033309999978142171791961527324895350873542614181199261564385165826366721405368299699380566756406246665364100155930677775564053779176118898354227653325334993025828331467179165827916940801675049 > /------------------------------\ | COMMANDS | | | | 1) ciphertext_info | | 2) solve_challenge <password> | | 3) exit | \------------------------------/ > 2 d0nt_reUs3_c0mm0n_m0duLus_iN_RSA ********** What the Phi? ********** Give me phi and I'll give you a flag N = 97934790717457816377408047595808017336290557647132874078463273042273480783693965913047913569035873972956920187266096013384149733128634153495383667005783367406343085928898092741457647502175596143302932648245342944432576818196386356562830861689797976228719838904175290216793497280116034968767061763793356427923 e = 24246426518850857132122259750361730417342755259639998613040824532553721920239 d = 38550551838267677901600814308974794800412771782528865753556316459464100087576689630219459038572918207153521275050604895720746906733498267505162038809151851814433919954002172458165034676258879934994139534497931839686512983498911853904726892873467416261172268490783160334649530502171196793008921183132824046351 /------------------------------\ | COMMANDS | | | | 1) try_again | | 2) phi <phi_value> | | 3) exit | \------------------------------/ > 2 97934790717457816377408047595808017336290557647132874078463273042273480783693965913047913569035873972956920187266096013384149733128634153495383667005783347591848586542793419570625418124529900910744439497817365571012710187525969553709932015969835839230374334244769937204684915684471122778808735239720897227128 What?! How did you do that?? flag{aR3nT_U_tH3_RSA_ninJA}
flag{aR3nT_U_tH3_RSA_ninJA}
Not Too Taxing (crypto)
bkcrackで既知平文攻撃を行う。
$ ./bkcrack -C Tax_Ret_Form_Nov_2021.zip -c Tax_Ret_Form_Nov_2021.pdf -p Tax_Ret_Form_Blank.pdf bkcrack 1.0.0 - 2020-11-11 Generated 4194304 Z values. [11:07:32] Z reduction using 150176 bytes of known plaintext 22.6 % (33917 / 150176) 255 values remaining. [11:07:36] Attack on 255 Z values at index 117285 Keys: b2c4a24e f036ff3a 998f6727 47.5 % (121 / 255) [11:07:37] Keys b2c4a24e f036ff3a 998f6727 $ ./bkcrack -C Tax_Ret_Form_Nov_2021.zip -c Tax_Ret_Form_Nov_2021.pdf -k b2c4a24e f036ff3a 998f6727 -d Tax_Ret_Form_Nov_2021.pdf bkcrack 1.5.0 - 2022-07-07 [13:41:06] Writing deciphered data Tax_Ret_Form_Nov_2021.pdf (maybe compressed) Wrote deciphered data.
抽出したTax_Ret_Form_Nov_2021.pdfをPDFStreamDumperで開き、各オブジェクトを見ていく。オブジェクト1268にフラグが書いてあった。
flag{1f_y0u_u53_z1pcryp70_4ny0n3_c4n_aud17_y0u}