32問中16問解けた。合計得点は188点で84位。あと数時間あれば…
あまり参考にならないかもしれないがwriteupを置いておく。
※解きながらwriteupを書いていたので、結局解けなかった問題についても記述してある。
Crypto
Information of Certificate (10)
Easy.crt ファイルは自己署名証明書です。証明書の発行者 (Issuer) のコモンネーム (CN) 全体を flag{} で囲んだものがフラグです。
証明書を開き、発行者欄のCN
を見ればよい。
flag{QRK7rNJ3hShV.vlc-cybercontest.invalid}
Forensics
NTFS Data Hide (10)
NTFSDataHide フォルダに保存されている Sample.pptx を利用して、攻撃者が実行予定のスクリプトを隠しているようです。 仮想ディスクファイル NTFS.vhd を解析して、攻撃者が実行しようとしているスクリプトの内容を明らかにしてください。
この手の問題ははじめてだったので、よく使用されるツールから調べていく。
どうやら「FTK Imager」を使えばいいらしい。
起動したらウィンドウ左上の緑のボタンAdd Evidence Item
を押してImage File
を選択、NTFS.vhd
を指定してFinish
を押す。これで左側のEvidence Tree
に仮想ディスクのファイル構造が表示されるようになった。
…と思っていたがFTK Imagerでは解けなかった(ヒントを見てADSが鍵になっているとわかったものの、このツールではADSを確認できなかった)。代わりに「AutoPsy」というフォレンジックツールを導入したところ、NTFSDataHide/Sample.pptx:script
というADSファイルが見つかった。中身を次に示す。
[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('ZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ=='))
このZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ==
という部分をbase64でデコードすればflagが得られる。
flag{data_can_be_hidden_in_ads}
NTFS File Delete (10)
NTFSFileDelete フォルダにフラグを記載した txt ファイルを保存したのですが、どうやら何者かによって消されてしまったようです。 問題「NTFS Data Hide」に引き続き、仮想ディスクファイル NTFS.vhd を解析して、削除された flag.txt に書かれていた内容を見つけ出してください。
FTK Imagerを利用し、NTFSFileDelete/flag.txt
を確認すればよい。
flag{resident_in_mft}
HiddEN Variable (20)
このメモリダンプが取得された環境にはフラグが隠されています。 memdump.raw を解析して、フラグを見つけ出してください。
時間がなかったので即ヒントを開ける。Volatilityというツールで環境変数を確認すればよいとわかったのでpython3 vol.py -f ../memdump/memdump.raw windows.envars
を実行、大量のログの中にFLAG BDkPUNzMM3VHthkj2cVEjdRBqTJcfLMJaxT9si67RgJZ45PS
とあったのでこれをbase58でデコード。
flag{volatile_environment_variable}
NTFS File Rename (20)
NTFSFileRename フォルダに保存されている Renamed.docx は、以前は別のファイル名で保存されていました。 問題「NTFS File Delete」に引き続き、仮想ディスクファイル NTFS.vhdを解析して、 Renamed.docx の元のファイル名を明らかにしてください。
FTK Imagerを利用。
(追記:AutoPsyだと瞬殺できると思う)
[root]/$LogFile
にファイルの変更履歴が記されている(参考リンク)。
そのため$LogFile
をエクスポートし、「LogFileParser」で詳しく調べる。
LogFileParserを実行すると複数のファイルが出力されるが、そのうちLogFileParser_vXXX\LogFile_XXX\LogFile_FileNames.csv
にファイル名の変遷が記されている。
このファイルをExcelで開く。MftRef
がMFTのレコード番号、つまりMFT(マスターファイルテーブル)におけるファイルの通し番号を示す。大雑把に言えば、この問題においては、MftRef
が同じであれば同じファイルであるといってよい。
Renamed.docx
と同じMftRef
を持つファイルはjournaling_system_is_powerful.docx
であるから、このファイルがリネームされてRenamed.docx
になったと考えられる。
flag{journaling_system_is_powerful}
My Secret (30、解けなかった)
問題「HiddEN Variable」に引き続き、メモリダンプファイル memdump.raw を解析して、秘密(Secret)を明らかにしてください。
即ヒント開ける。7zip関連のプロセスを見ればよいとのことなので
$ python3 vol.py -f ../memdump/memdump.raw windows.pstree.PsTree | grep 7z **** 5516 100.03468 7z.exean0xe206bb303080 4 - 1 False 2023-12-26 00:51:23.000000 N/A \Device\HarddiskVolume3\Program Files\7-Zip\7z.exe 7z x -pY0uCanF1ndTh1sPa$$w0rd C:\Users\vauser\Documents\Secrets.7z -od:\ C:\Program Files\7-Zip\7z.exe
このSecrets.7z
をダンプする。
$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --pid="5516" Volatility 3 Framework 2.6.1 Progress: 100.00 PDB scanning finished Cache FileObject FileName Result DataSectionObject 0xe206bbc4a2f0 Secrets.7z Error dumping file SharedCacheMap 0xe206bbc4a2f0 Secrets.7z file.0xe206bbc4a2f0.0xe206bbabada0.SharedCacheMap.Secrets.7z.vacb ImageSectionObject 0xe206bbc491c0 7z.dll file.0xe206bbc491c0.0xe206bb46d770.ImageSectionObject.7z.dll.img ImageSectionObject 0xe206bba6c490 7z.exe file.0xe206bba6c490.0xe206b8b49730.ImageSectionObject.7z.exe.img ImageSectionObject 0xe206b6121570 KernelBase.dll file.0xe206b6121570.0xe206b610dc10.ImageSectionObject.KernelBase.dll.img ImageSectionObject 0xe206b61210c0 win32u.dll file.0xe206b61210c0.0xe206b62e17c0.ImageSectionObject.win32u.dll.img ImageSectionObject 0xe206b9139e80 cryptbase.dll file.0xe206b9139e80.0xe206b912bcc0.ImageSectionObject.cryptbase.dll.img ImageSectionObject 0xe206b6122380 msvcp_win.dll file.0xe206b6122380.0xe206b610e460.ImageSectionObject.msvcp_win.dll.img ImageSectionObject 0xe206b6122ce0 gdi32full.dll file.0xe206b6122ce0.0xe206b610e9a0.ImageSectionObject.gdi32full.dll.img ImageSectionObject 0xe206b611bed0 oleaut32.dll file.0xe206b611bed0.0xe206b62d5a50.ImageSectionObject.oleaut32.dll.img ImageSectionObject 0xe206b61213e0 combase.dll file.0xe206b61213e0.0xe206b62d6a20.ImageSectionObject.combase.dll.img ImageSectionObject 0xe206b6122e70 ucrtbase.dll file.0xe206b6122e70.0xe206b62da2b0.ImageSectionObject.ucrtbase.dll.img ImageSectionObject 0xe206b61229c0 sechost.dll file.0xe206b61229c0.0xe206b62d6cf0.ImageSectionObject.sechost.dll.img ImageSectionObject 0xe206b611b3e0 advapi32.dll file.0xe206b611b3e0.0xe206b62e1010.ImageSectionObject.advapi32.dll.img ImageSectionObject 0xe206b6121250 imm32.dll file.0xe206b6121250.0xe206b62d7cc0.ImageSectionObject.imm32.dll.img ImageSectionObject 0xe206b611c380 rpcrt4.dll file.0xe206b611c380.0xe206b62e3cd0.ImageSectionObject.rpcrt4.dll.img ImageSectionObject 0xe206b611c830 user32.dll file.0xe206b611c830.0xe206b62d5d00.ImageSectionObject.user32.dll.img ImageSectionObject 0xe206b611c9c0 gdi32.dll file.0xe206b611c9c0.0xe206b62e3a20.ImageSectionObject.gdi32.dll.img ImageSectionObject 0xe206b611c510 msvcrt.dll file.0xe206b611c510.0xe206b62e06c0.ImageSectionObject.msvcrt.dll.img ImageSectionObject 0xe206b611ce70 kernel32.dll file.0xe206b611ce70.0xe206b62e3520.ImageSectionObject.kernel32.dll.img ImageSectionObject 0xe206b0ef9940 ntdll.dll file.0xe206b0ef9940.0xe206b0bc5010.ImageSectionObject.ntdll.dll.img
file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat
を7zで解凍したがエラーが出る。パスワードが違う?
$ 7z x -pY0uCanF1ndTh1sPa$$w0rd file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat 7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz (906EA),ASM,AES-NI) Scanning the drive for archives: 1 file, 4096 bytes (4 KiB) Extracting archive: file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat WARNINGS: There are data after the end of archive -- Path = file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat Type = 7z WARNINGS: There are data after the end of archive Physical Size = 418 Tail Size = 3678 Headers Size = 146 Method = LZMA2:12 7zAES Solid = - Blocks = 1 ERROR: Data Error in encrypted file. Wrong password? : Secrets.rtf Sub items Errors: 1 Archives with Errors: 1 Warnings: 1 Sub items Errors: 1
別の方法でダンプを試みたがダメだった。
$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --physaddr 0xe206bbc4a2f0 Volatility 3 Framework 2.6.1 Progress: 100.00 PDB scanning finished Cache FileObject FileName Result (※注:何も出力されなかった)
Miscellaneous
Une Maison (10)
画像 maison.jpg の中にフラグが隠されています。探してみてください。
stringsでもfileでも異常なし。steghideも違った。 わからずヒント1を開くと、
メタデータやバイナリの解析は必要ありません。
とのこと。とりあえず画像検索してみると似た画像が出てきたが、一部異なる部分がある。よく見るとバーコードになっていたため、そこを切り出してGoogle Lensに投げるとflagが得られた。
flag{$50M!}
String Obfuscation (10)
難読化された Python コード
string_obfuscation.py
ファイルからフラグを抽出してください。
ソースコードを見ると
FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51)
との表記があるので、これをそのままprintしてやればよい。
$ python3 Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51) >>> print(FLAG) 3FxYFm4uTYDFFzmb3
flag{3FxYFm4uTYDFFzmb3}
Where Is the Legit Flag? (20)
fakeflag.py
を実行しても偽のフラグが出力されてしまいます。難読化されたコードを解読し、本物のフラグを見つけ出してください。
fakeflag.py
の難読化を解除すると、次のようになる。
exec(chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(32)+chr(122)+chr(108)+chr(105)+chr(98)+chr(44)+chr(32)+chr(98)+chr(97)+chr(115)+chr(101)+chr(54)+chr(52)) # ↳ exec("import zlib, base64") TANAKA = "eJyNVG1320QT/Z5z8h+GhNYvcR35JZZdaCGhT6D0gQTiFKjjlpU0ljZe7272xYpoy2/vrJRA+MA56IOPrJ29e+feO7sP84JJ2CohsEqYELBlktsCWM64tA6E3+gKEjSm6u/uXBzPz+AZtBY/vRx91Unffv908vOrw9PXz7/E23h/nf2mtp9/Gz05fn9zbv8sB18f/P7DWa9o/5/1f/Hf6KMlhzfJ9YvZ/x4NKzk185PNF6vud3uf/Xjx0eV/PLsUvz4ev/tw1bq6au3u7MNxorYIK5Yi4K0WRAhWyoAuKstTJiDDlFuuZB9C9WvOwEq2RpBsg2CUlxk4Is5XPIXEMGubwlNqVpVc5mB9nqN1BAG2LjeYM5OFpRVumCAUTPF+31yVtAhb+oB0OLcsN4ikjUTmCih8jqCVoSODUpdvLl+9JK0W8fhJdBD1dnfg7pnG3UGPS9ceT7vdQYdW9uFstQLtjVYWQTBiwiwYb6hJ65jDDUpHoPcIYfP03ahTo4yG/Sg8zb/WaNwKkPel8QQeQ3R7etqLh/CB3qKoF8/gbfO2mBwtF9GypvDCm9D4WipHbYsKLCP1S4MuLTADmzISw6gyiHGP3h52euMY+ArmxpNLguhHNY/B8JBaG0TwCAaDnjJZOy1MezjpPCQ3ig6O7pQ4HHYJa9adLQMXOBfeglMIFp0jH0pOCm8ZBZJSialrHIGLQJECnFmwBQqSvqk0zLkKtFGZT5GEo9Iz7yzPSF3MLUhynYw0NpximLzxXISmWchCU39soWRiDZqRHE04eF64lRfAsi0n2JrCCdaomlXBowBGKU0qMtFQHNYYpmYfzgPzBAu25SHAiv65Jk1esoT6K9TmDhCON4psoLhT7FO1aXKfKhnOqR3ykjwq6Zs3pslFG8K+hqXVzKzJLWVSmuJ6gqxWQY7cMF0fEqRvtWjLpSTIJr3XWFKo00Jp6oXoZaiRVqklmh8RNAy7+uHnWhGhf33ai7/9DQ5xWfeRlJiA4wiKkl544yjYoZu7S2XBl38h/Ldd4SbglAZoJu3hoRRHDs9hHA+nT/9Bhp7EIFs//OhoRoej8WQSQxemo3h69HBV02mu7Q5H46M4no46tUPzgqTOC7jxiBIytiF6YAXXGk1Ve8YMt3WQls2OkyqEKQyzUXRBhYwqT83QQKGjJVtQbVN6pike3CFUoVIijV7SZMx6wk/CjUzXcfCxIbe3Eip/P91e46z0MtGz6fjjHmHt7nwCLpe/Qg==" TAKAHASHI = [0x7a,0x7a,0x7a,0x12,0x18,0x12,0x1d,0x12,0x07,0x7b,0x36,0x37,0x3c,0x30,0x36,0x37,0x67,0x65,0x31,0x7d,0x67,0x65,0x36,0x20,0x32,0x31,0x7b,0x20,0x20,0x36,0x21,0x23,0x3e,0x3c,0x30,0x36,0x37,0x7d,0x31,0x3a,0x3f,0x29,0x7b,0x30,0x36,0x2b,0x36] exec(bytes([WATANABE ^ 0b01010011 for WATANABE in reversed(TAKAHASHI)])) # ↳ exec(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')
ここでexec(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')
を実行すると、以下のコードが実行される。
# Than volleyball vanish against lumpy berry. SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\' # Above face explain for physical decision. # Via snake name round terrific brass. # Following suggestion sound regarding female recess. # Toward vessel disagree beneath huge porter. SUZUKI = [74-0+0, 87*1,int(48**1), # Off purpose land as rural statement. int(8_3),int(32.00000),int('34'), 76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0], # During knot rely save wretched scarecrow. (2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)), 30+5,int(48/2*2),9*9] # Plus toe settle with vast insect. # Save hands shelter with ratty produce. # Outside legs nest versus tranquil relation. # As walk pat round rightful advice. # Beside payment train by large key. # Past behavior post toward unable home. # Among place complain considering unknown current. ( # Around spark scorch above spotty grape. ''# Underneath jewel chop past dependent rifle. . join ([ # Since cobweb tie off hurt string. SATO[i] # Since cobweb tie off hurt string. for i in SUZUKI # if i > 4728: # break # t = 234667 * 83785 # print(t/3457783) # Through queen dam of slippery comparison. ]) # By wall stroke without secret wash. ) # Opposite yoke need beside superb lumber. print("flog{8vje9wunbp984}")
これを整形したコードを次に示す。
SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\' SUZUKI = [74-0+0,87*1,int(48**1),int(8_3),int(32.00000),int('34'),76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0],(2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)),30+5,int(48/2*2),9*9] (''.join([SATO[i] for i in SUZUKI])) print("flog{8vje9wunbp984}")
注目すべきなのは3行目の(''.join([SATO[i] for i in SUZUKI]))
である。この処理の結果はどこからも参照されていないので、試しにprintしてみる。するとflagが得られた。
flag{PHmN2ILK6vsa}
Network
FileExtract (10)
添付の FileExtract.pcapng ファイルからフラグを見つけ出し、解答してください。
wiresharkで添付ファイルを開く。ファイル -> オブジェクトをエクスポート → FTP-DATA
をクリックすると、s3cr3t.zip
なるファイルをエクスポートできる。しかしパスワードがかかっており解凍できない。
パケットを眺めると230 Login successful
という記述が見つかったため、この前後のパケットを見ると、Request: PASS br2fWWJjjab3
という記述を発見。br2fWWJjjab3
をパスワードとしたところ、s3cr3t.zip
を解凍することができ、中身のファイルfl@g
を確認できた。
flag{6qhFJSHAP4A4}
Programming
Logistic Map (10)
下記のロジスティック写像について、x_0 = 0.3 を与えた時の x_9999 の値を求め、小数第7位までの値を答えてください(例:flag{0.1234567})。なお、値の保持と計算には倍精度浮動小数点数を使用してください。 x_{n+1} = 3.99 x_n (1 - x_n)
Pythonで解いた。
x: float = 0.3 for i in range(1, 10000): # x_1 ... x_9999 x = 3.99 * x * (1 - x) print(x) # -> 0.8112735...
flag{0.8112735}
Trivia
The Original Name of AES (10)
Advanced Encryption Standard (AES) は、公募によって策定された標準暗号です。 現在採用されているアルゴリズムの候補名は何だったでしょうか?
wikipediaを見る。
Advanced Encryption Standard (AES) は、アメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである。アメリカ国立標準技術研究所(NIST)が公募し、Rijndael(ラインダール)がAESとして採用された。 (https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard より引用)
flag{Rijndael}
CVE Record of Lowest Number (10)
最も番号が若い CVE レコードのソフトウェアパッケージにおいて、脆弱性が指摘された行を含むソースファイル名は何でしょう?
最も番号が若いCVEレコード
は、GitHubに上がっているCVEリストより、CVE-1999-0001
であるとわかる。
この脆弱性の詳細を調べると、
BSD 由来の TCP/IP 実装の ip_input.c により、リモート攻撃者は細工されたパケットを介してサービス拒否 (クラッシュまたはハング) を引き起こすことができます。 (https://www.cvedetails.com/cve/CVE-1999-0001/ より引用、google翻訳使用)
とあるので、脆弱性が指摘された行を含むソースファイル名
はip_input.c
である。
flag{ip_input.c}
MFA Factors (10)
多要素認証に使われる本人確認のための3種類の情報の名前は何でしょう?それぞれ漢字2文字で、50音の辞書順で並べて「・」で区切ってお答えください。
IPAによると、多要素認証に使われる本人確認のための3種類の情報
は記憶情報、所持情報、生体情報である。
flag{記憶・所持・生体}
Web
Browsers Have Local Storage (10)
http://10.10.10.30 にアクセスしてフラグを見つけ出し、解答してください。
問題タイトルにあるように、ローカルストレージにflagが書いてある。ブラウザのF12キーを押して開発者ツールを起動し、アプリケーション -> ストレージ -> ローカルストレージ
で確認できる。
FLAG{Th1s_1s_The_fIrst_flag}
Are You Introspective? (10、解けなかった)
http://10.10.10.31 にアクセスしてフラグを見つけ出し、解答してください。 このサイトでは GraphQL が使用されているため、まずは endpoint を探す必要があります。
そもそもエンドポイントとは何かというと、APIの呼び出しが行われる場所やAPIにアクセスするためのURIのことらしい。
エンドポイントを探す必要があるが、goctopus(docker run --rm -it escapetech/goctopus:latest -a 10.10.10.31
)を使用しても見つからなかった。
Insecure (20)
あなたは社内ポータルサイト(http://10.10.10.33)の管理者に依頼されて、profile ページが安全に保護されているかチェックすることになりました。 以下のログイン情報を用いてサイトにログインし、管理者の profile ページに記載されている秘密の情報を見つけてください。 なお、依頼の際に「管理者ページのidは0だよ」というヒントをもらっています。
testUser
としてログイン後、ページ下部の「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリックすると、プロフィールページ(http://10.10.10.33/profile_success.php)に遷移した。
次に、管理者のidが0であるというヒントを利用し、管理者のプロフィール(http://10.10.10.33/show_profile.php?id=0)にアクセスしてみたが、エラーページ(http://10.10.10.33/profile_error.php)に遷移してしまった。
そこで、BurpSuiteを用いて強引に管理者プロフィールにアクセスする。具体的には、
- BurpSuiteを起動、InterceptをONにしてから「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリック
- BurpSuiteで
id=0
をid=1
に書き換えてForward
- http://10.10.10.33/profile_error.phpにリダイレクトされるので、同じくBurpSuiteで遷移先を
profile_error.php
からprofile_success.php
に書き換えてForward
以上のプロセスを踏むことで管理者プロフィールにアクセスでき、フラグを得られる。
FLAG{1qaz7ujmbgt5}
Variation (20、解けなかった)
http://10.10.10.32 のWebサーバーで下記形式の XSS を発生させ、フラグを入手してください。
<script>alert(1)</script>
与えられたWebページでNameを入力してSubmitボタンを押すと、入力したNameが表示されるという問題。
試しに<script>alert(1)</script>
を入力したところ、Hey, scriptalert(1)/script
と表示された。
<>
が削除されているため、パーセントエンコーディングして%3Cscript%3Ealert(1)%3C/script%3E
を入力してみたが、そのままHey, %3Cscript%3Ealert(1)%3C/script%3E
と出力されてしまう。