この大会は2023/6/24 14:00(JST)~2023/6/26 2:00(JST)に開催されました。
この大会は個人戦。結果は690点でした。順位や参加者数は不明です。
自分で解けた問題をWriteupとして書いておきます。
Sanity check (Misc)
ルールにフラグフォーマットが書いてあった。
aupCTF{5an1ty-ch3ck}
Fun (Misc)
scriptタグで挟み、ブラウザで開くと、フラグがポップアップされて表示された。
aupCTF{j4v45c1pt_but_f*ck3d}
Zoo (Misc)
YouTubeに最初にアップロードされた日時をEpoch Timestampで答える問題。
Googleで調べると、以下のページが見つかる。
https://en.wikipedia.org/wiki/Me_at_the_zoo
YouTubeに初めてアップロードされた日時は以下の通り。
April 24, 2005, at 03:31:52 UTC
Epoch Timestampに変換する。
1114313512
aupCTF{1114313512}
The Circle Of Life (Misc)
GCodeで書かれているようだ。以下のURLのオンラインのNC viewerで開くと、フラグが見える。
https://ncviewer.com/
aupCTF{Ti3_i3_fu9_rig4ht}
Starter (Web)
HTMLソースをを見ると、以下のようになっている。
<div class="word"> <span id="letter1">a</span> <span id="letter2">u</span> <span id="letter3">p</span> <span id="letter4">C</span> <span id="letter5">T</span> <span id="letter6">F</span> <span id="letter7">{</span> </div> <div class="word"> <span id="letter8">w</span> <span id="letter9">4</span> <span id="letter10">5</span> <span id="letter11">n</span> <span id="letter12">'</span> <span id="letter13">t</span> <span id="letter14">-</span> <span id="letter15">t</span> <span id="letter16">h</span> <span id="letter17">4</span> <span id="letter18">7</span> <span id="letter19">-</span> <span id="letter20">h</span> <span id="letter21">4</span> <span id="letter22">r</span> <span id="letter23">d</span> <span id="letter24">-</span> <span id="letter25">r</span> <span id="letter26">1</span> <span id="letter27">g</span> <span id="letter28">h</span> <span id="letter29">7</span> </div> <div class="word"> <span id="letter30">}</span> </div>
順に並べると、フラグになる。
aupCTF{w45n't-th47-h4rd-r1gh7}
SQLi - 1 (Web)
SQLインジェクション。以下のように入力し、Submitすると、フラグが表示された。
Username: ' or 1=1 -- Password: (空)
aupCTF{3a5y-sql-1nj3cti0n}
Header (Web)
Webページにはこう書いてある。
リクエストヘッダ'GETFLAG'が'yes'の場合、フラグを含むページを返すということらしい。
$ curl https://challs.aupctf.live/header/ -H "GETFLAG: yes" aupCTF{cust0m-he4d3r-r3qu3st}
aupCTF{cust0m-he4d3r-r3qu3st}
Directory (Web)
https://challs.aupctf.live/dir/page/1/~https://challs.aupctf.live/dir/page/1000/までのリンクがある。どれかにフラグが含まれているらしい。
スクリプトで順にページを見ていき、フラグを探す。
#!/usr/bin/env python3 import requests for i in range(1, 1001): url = 'https://challs.aupctf.live/dir/page/%d/' % i print('[+] url:', url) r = requests.get(url) if 'No flag for you' not in r.text: print(r.text) break
実行結果は以下の通り。
: : [+] url: https://challs.aupctf.live/dir/page/710/ [+] url: https://challs.aupctf.live/dir/page/711/ [+] url: https://challs.aupctf.live/dir/page/712/ <!DOCTYPE html> <html> <head> <title>You Found Me</title> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 0; } h1, h2{ text-align: center; margin-top: 50px; } </style> </head> <body> <h1>Here is your flag, You deserve it</h1> <br> <h2>The flag is: aupCTF{d1r3ct0r13s-tr1v14l-fl4g}</h2> </body> </html>
aupCTF{d1r3ct0r13s-tr1v14l-fl4g}
Thread (Forensics)
ハッシュ値を元に、Popular threat labelを答える問題。VirusTotalで以下のハッシュを調べる。
d0ee6ffc8ce0e7f21cdcbd5e98c2dd4174a5d1b0266ec7f69075a0d9bea14757
popular threat labelは以下の通り。
trojan.nanocore/msil
aupCTF{trojan.nanocore/msil}
I Love Math (Forensics)
PDFにパスワードがかかっているので、クラックする。
$ pdf2john math.pdf > hash.txt $ john --wordlist=dict/rockyou.txt hash.txt Using default input encoding: UTF-8 Loaded 1 password hash (PDF [MD5 SHA2 RC4/AES 32/64]) Cost 1 (revision) is 6 for all loaded hashes Will run 2 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status naruto (math.pdf) 1g 0:00:00:00 DONE (2023-06-25 13:54) 12.50g/s 1600p/s 1600c/s 1600C/s samantha..diamond Use the "--show --format=PDF" options to display all of the cracked passwords reliably Session completed.
パスワードはnaruto。このパスワードでPDFを開くが、フラグが見つからない。「I can't see anything here」とだけ書いてある。全選択し、コピペする。
I can't see anything here The flag for this challenge is of the form: aupCTF{I_Love_Math_x_y}, where x and y are the solution to these equations: 2x + 4y = 16 3x + 7y = 25
x, yを求める必要がある。普通に数学として解く。
6x + 12y = 48 6x + 14y = 50
上記から以下のことがわかる。
y = 1
さらに以下のことがわかる。
x = 6
aupCTF{I_Love_Math_6_1}
Syrio Forel (Steganography)
base64デコードすると、jpgになる。画像にこう書いてある。
what do we say to the god of death
これをGoogle検索すると、以下の言葉が出てくる。
Not today
aupCTF{Not_today}
LSB (Steganography)
$ zsteg naruto.png imagedata .. text: "$:;`VV(-1" b1,b,lsb,xy .. file: OpenPGP Secret Key b1,rgb,lsb,xy .. text: "aupCTF{zst1g-1s-c00l_rig3ht}" b2,rgb,lsb,xy .. file: big endian ispell 3.0 hash file, and 13698 string characters
aupCTF{zst1g-1s-c00l_rig3ht}
Deep (Steganography)
問題タイトルからDeepSoundの問題と推測する。パスワードがかかっているので、John the Ripperでクラックする。
$ deepsound2john truefan.wav > hash.txt $ john --wordlist=dict/rockyou.txt hash.txt Created directory: /home/kali/.john Using default input encoding: UTF-8 Loaded 1 password hash (dynamic_1529 [sha1($p null_padded_to_len_32) (DeepSound) 256/256 AVX2 8x1]) Warning: no OpenMP support for this hash type, consider --fork=2 Press 'q' or Ctrl-C to abort, almost any other key for status iamironman (truefan.wav) 1g 0:00:00:00 DONE (2023-06-25 12:51) 20.00g/s 7056Kp/s 7056Kc/s 7056KC/s julian24..hotchick13 Use the "--show --format=dynamic_1529" options to display all of the cracked passwords reliably Session completed.
パスワードはiamironman。DeepSoundでこのパスワードを使って秘密ファイルを抽出する。marvel.exeが抽出できた。
$ strings marvel.exe| grep python
bpython310.dll
6python310.dll
Python3.10製なのでデコンパイルする。
$ python3 pyinstxtractor.py marvel.exe [+] Processing marvel.exe [+] Pyinstaller version: 2.1+ [+] Python version: 3.10 [+] Length of package: 6342224 bytes [+] Found 61 files in CArchive [+] Beginning extraction...please standby [+] Possible entry point: pyiboot01_bootstrap.pyc [+] Possible entry point: pyi_rth_inspect.pyc [+] Possible entry point: marvel.pyc [!] Warning: This script is running in a different Python version than the one used to build the executable. [!] Please run this script in Python 3.10 to prevent extraction errors during unmarshalling [!] Skipping pyz extraction [+] Successfully extracted pyinstaller archive: marvel.exe You can now use a python decompiler on the pyc files within the extracted directory $ pycdc marvel.exe_extracted/marvel.pyc # Source Generated with Decompyle++ # File: marvel.pyc (Python 3.10) import sys questions = [ { 'question': 'How much does Morgan Starks love her dad? [number]', 'answer': '3000' }, { 'question': 'What is the full form of J.A.R.V.I.S.?', 'answer': 'Just A Rather Very Intelligent System' }, { 'question': 'What is the full form of AI that replaced J.A.R.V.I.S.?', 'answer': 'Female Replacement Intelligent Digital Assistant Youth' }] def ask_question(question): user_answer = input(question['question'] + ' \n') if user_answer.lower() == question['answer'].lower(): return True def main(): for question in questions: if not ask_question(question): print('Incorrect answer!') sys.exit(0) print('\n\n\nCongratulations! You are a true Marvel Nerd like Me ;/') print('Flag format: iron man first appearance year underscore last appearance year in movies') input('Press any key to exit...') if __name__ == '__main__': main() return None
映画でアイアンマンが最初に登場した年と、最後に登場した年がフラグ。
aupCTF{2008_2019}
Obfuscated (Steganography)
JPGファイルだがバイト単位で前半4ビットと後半4ビットが入れ替わっているので、修復する。
#!/usr/bin/env python3 with open('flag.jpg', 'rb') as f: data = f.read() out = b'' for d in data: code = (d >> 4) + ((d & 0xf) << 4) out += bytes([code]) with open('flag_fix.jpg', 'wb') as f: f.write(out)
修復した画像にフラグが書いてあった。
aupCTF{sw4p3d_w0w453?5422asd!1}
XOR (Steganography)
2つの画像のXORを取ってみる。
#!/usr/bin/env python3 from PIL import Image img1 = Image.open('img1.png').convert('RGB') img2 = Image.open('img2.png').convert('RGB') w, h = img1.size output_img = Image.new('RGB', (w, h), (255, 255, 255)) for y in range(h): for x in range(w): r1, g1, b1 = img1.getpixel((x, y)) r2, g2, b2 = img2.getpixel((x, y)) output_img.putpixel((x, y), (r1 ^ r2, g1 ^ g2, b1 ^ b2)) output_img.save('flag.png')
XORした画像には以下のように書いてある。
Shorts ID: LYkCU8Kn3a8
このIDの長さからYouTubeのパラメータと推測し、以下にアクセスする。
https://www.youtube.com/watch?v=LYkCU8Kn3a8
hexahueの画像が流れているので、デコードしていく。
w0wgraps
aupCTF{w0wgraps}
Rotation (Cryptography)
シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherでAscii charactersの範囲で復号する。
Rotation 27: smhULX{q0m-x0mfv-e3}
さらにLetters onlyの範囲で復号する。
Rotation 18: aupCTF{y0u-f0und-m3}
aupCTF{y0u-f0und-m3}
Ancient Cipher (Cryptography)
シーザー暗号と推測して、https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。
Rotation 17: aupCTF{B0b's_Bad_Crypt0graphy_5k1lls}
aupCTF{B0b's_Bad_Crypt0graphy_5k1lls}
Disorder (Cryptography)
転置暗号のようなので、その法則を探す。
11111111112222222222 012345678901234567890123456789 utsa}Ts0aXa{1_eC1ngXph__XF_tmX
10から左に10ごと、3箇所回ったら、5個左に行って、3箇所回る。
11から左に10ごと、3箇所回ったら、5個左に行って、3箇所回る。
これを繰り返す。
10: a 00: u 20: p 15: C 05: T 25: F 11: { 01: t 21: h 16: 1 06: s 26: _ 12: 1 02: s 22: _ 17: n 07: 0 27: t 13: _ 03: a 23: _ 18: g 08: a 28: m 14: e 04: } 24: X 19: X 09: X 29: X
パディングのXを除き並べると、フラグになっている。
aupCTF{th1s_1s_n0t_a_game}
RSA (Cryptography)
RSA暗号で、n, e, cの他にp + qとp - qの値がわかっている。
phiは以下の計算で割り出すことができる。
phi = (p - 1) * (q - 1) = n - (p + q) + 1
あとは通常通り復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * with open('output.txt', 'r') as f: params = f.read().splitlines() n = int(params[0].split(' ')[-1]) e = int(params[1].split(' ')[-1], 16) c = int(params[2].split(' ')[-1]) sum_pq = int(params[3].split(' ')[-1]) phi = n - sum_pq + 1 d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
aupCTF{3a5y_tw0_3quat10n5_and_hax3d_3}
Swiss Army Knife (Cryptography)
"X"を"0"に、"Y"を"1"に置換しデコードする。
base64文字列になるので、デコードする。
モールス信号になるので、デコードする。
base32文字列になるので、デコードする。
シーザー暗号で暗号化されているので、復号する。
#!/usr/bin/env python3 from base64 import * from string import * morse = {'.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G', '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N', '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R', '...': 'S', '-': 'T', '..-': 'U', '...-': 'V', '.--': 'W', '-..-':'X' , '-.--': 'Y', '--..': 'Z', '-----': '0', '.----': '1', '..---': '2', '...--': '3', '....-': '4', '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9', '-...-': '=' } with open('decode.txt', 'r') as f: enc = f.read() enc = enc.replace('X', '0').replace('Y', '1') enc = enc.split(' ') msg = '' for c in enc: msg += chr(int(c, 2)) print('decoded 1:', msg) dec = b64decode(msg).decode() print('decoded 2:', dec) codes = dec.split(' ') msg = '' for code in codes: msg += morse[code] print('decoded 3:', msg) dec = b32decode(msg).decode() print('decoded 4:', dec) flag = '' for c in dec: if c in ascii_uppercase: index = (ascii_uppercase.index(c) + 7) % 26 flag += ascii_uppercase[index] elif c in ascii_lowercase: index = (ascii_lowercase.index(c) + 7) % 26 flag += ascii_lowercase[index] else: flag += c print('flag:', flag)
実行結果は以下の通り。
decoded 1: LS0tIC4tLiAtLi4tIC0tLiAuLi4gLi4uLSAuLi4gLS4gLi0uLiAuLi0uIC4uLi4uIC4tLSAtLSAuLi4tLSAuLS4gLi0uIC0uIC4uLi0gLi0uIC0tLiAuLi4gLS0gLi0tLSAtIC4uLS4gLi4tIC0tLi4gLi0tIC0tLSAuLi4uLiAuLS4gLS0uLSAtLS0gLi4uLi0gLS4tLSAuLS0gLS0tIC0uLi4uIC4tLiAuLi4tIC4uLS4gLi4uLSAtLi4tIC0uLiAtLi0gLS0gLi4uLS0gLS4uLSAuLS0uIC4uLSAtLi4uLSAtLi4uLSAtLi4uLSAtLi4uLSAtLi4uLSAtLi4uLQ== decoded 2: --- .-. -..- --. ... ...- ... -. .-.. ..-. ..... .-- -- ...-- .-. .-. -. ...- .-. --. ... -- .--- - ..-. ..- --.. .-- --- ..... .-. --.- --- ....- -.-- .-- --- -.... .-. ...- ..-. ...- -..- -.. -.- -- ...-- -..- .--. ..- -...- -...- -...- -...- -...- -...- decoded 3: ORXGSVSNLF5WM3RRNVRGSMJTFUZWO5RQO4YWO6RVFVXDKM3XPU====== decoded 4: tniVMY{fn1mbi13-3gv0w1gz5-n53w} flag: aupCTF{mu1tip13-3nc0d1ng5-u53d}
aupCTF{mu1tip13-3nc0d1ng5-u53d}
Battista's Bet (Cryptography)
Vigenere暗号と推測し、https://www.dcode.fr/vigenere-cipherで復号する。
鍵はSECRETでフラグの形式になった。
aupCTF{B3lla50W0uldB3Pr0ud}
Servay (Misc)
アンケートに答えたら、フラグが表示された。
aupCTF{th4nk5_f0r_y0ur_valu4bl3_f33db4ck}