FireShell CTF 2019 Writeup
- はじめに
- [RECON 60pts] Welcome (546 solves)
- [RECON 60pts] Social (240 solves)
- [RECON 60pts] Where is the IRC? (306 solves)
- [MISC 60pts] babycryptoweb (168 solves)
- [CRYPTO 60pts] Alphabet (159 solves)
- [REVERSING 60pts] Blackbox-0 (52 solves)
- [REVERSING 164pts] Blackbox-1 (35 solves)
- [REVERSING 478pts] BlackBox Cypher (9 solves)
- おわりに
はじめに
こんにちは。cute_otterです。
2019/01/27 01:00~2019/01/28 02:30(JST)にかけて開催されたFireShell CTF 2019に、一人チーム「cute_otter」で参加しました。
結果は1002ptsで28位(点を取った570チーム中)でした。
問題ファイルは、FireShell CTF 2019のDiscordの#homeで公開されています。
[RECON 60pts] Welcome (546 solves)
問題文
Well done!
添付ファイル
なし
解法
Rulesのページ(https://ctf.fireshellsecurity.team/rules)の項目10の所にフラグがありました。
フラグ
F#{w3lc0m3_gUyS!!!!!FIr35h#L_ctF_@)!(}
[RECON 60pts] Social (240 solves)
問題文
なし
添付ファイル
なし
解法
FireShellのこちらのツイートに添付された画像のQRコードを読み込むとフラグを得られました。
フラグ
F#{4re_Y0u_r3c0n?!!_:)}
[RECON 60pts] Where is the IRC? (306 solves)
問題文
なし
添付ファイル
なし
解法
FireShell CTF 2019のDiscordの#reconチャンネルのチャンネルトピックにフラグが書いてありました。
フラグ
F#{D1sc0rd_b3tt3r_th4n_1RC}
[MISC 60pts] babycryptoweb (168 solves)
問題文
Can you help me recover the flag? https://babycryptoweb.challs.fireshellsecurity.team/
添付ファイル
なし
解法
問題文のリンク先にアクセスすると以下のソースコードが与えられました。
<?php $code = '$kkk=5;$s="e1iwZaNolJeuqWiUp6pmo2iZlKKulJqjmKeupalmnmWjVrI=";$s=base64_decode($s);$res="";for($i=0,$j=strlen($s);$i<$j;$i++){$ch=substr($s,$i,1);$kch=substr($kkk,($i%strlen($kkk))-1,1);$ch=chr(ord($ch)+ord($kch));$res.=$ch;};echo $res;'; if (isset($_GET['p']) && isset($_GET['b']) && strlen($_GET['b']) === 1 && is_numeric($_GET['p']) && (int) $_GET['p'] < strlen($code)) { $p = (int) $_GET['p']; $code[$p] = $_GET['b']; eval($code); } else { show_source(__FILE__); } ?>
$code
に代入されているコードを読みやすくすると以下のようになります。
<?php $kkk=5; $s="e1iwZaNolJeuqWiUp6pmo2iZlKKulJqjmKeupalmnmWjVrI="; $s=base64_decode($s); $res=""; for($i=0,$j=strlen($s);$i<$j;$i++) { $ch=substr($s,$i,1); $kch=substr($kkk,($i%strlen($kkk))-1,1); $ch=chr(ord($ch)+ord($kch)); $res.=$ch; }; echo $res; ?>
$s
の文字列がフラグだと仮定して、for文の最後に、echo ord($ch);
というコードを追加し、各文字のASCII値を確認すると、最初の3文字が123 88 176
となっていました。
フラグの書式はF#{...}
なので、最初の3文字をASCII値に変換すると70 35 123
となります。
以上のことから、各文字のASCII値を-53すると、フラグが得られそうです。
上記のコードを以下のように書き換えました。
<?php $kkk=5; $s="e1iwZaNolJeuqWiUp6pmo2iZlKKulJqjmKeupalmnmWjVrI="; $s=base64_decode($s); $res=""; for($i=0,$j=strlen($s);$i<$j;$i++) { $ch=substr($s,$i,1); $kch=substr($kkk,($i%strlen($kkk))-1,1); $ch=chr(ord($ch)-53); // 書き換えた部分 $res.=$ch; }; echo "[+] Flag: ".$res."\n"; // 書き換えた部分 ?>
以上のコードを実行するとフラグを得られました。
php decrypt.php [+] Flag: F#{0n3_byt3_ru1n3d_my_encrypt1i0n!}
フラグ
F#{0n3_byt3_ru1n3d_my_encrypt1i0n!}
[CRYPTO 60pts] Alphabet (159 solves)
問題文
If you know your keyboard, you know the flag
添付ファイル
submit_the_flag_that_is_here.txt
解法
与えられたsubmit_the_flag_that_is_here.txt
には、大量のMD5ハッシュ値とSHA256ハッシュ値が含まれていました。
以下のサイトで、いくつかのハッシュ値を復号すると、アルファベット、数字、記号が一文字づつハッシュ化されていることが分かりました。
hashtoolkit.com md5hashing.net
そこで、以下の復号アルゴリズムを考えました。
- ファイル内に存在すると思われる文字のMD5ハッシュ値とSHA256ハッシュ値を算出し、文字とハッシュ値が対応する辞書を作る。
- ファイルのハッシュ値と一致するハッシュ値が辞書内にあれば、辞書のキー(ハッシュ値の元の文字)を出力する。
以上の復号アルゴリズムをPythonで実装したものは以下の通りです。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import string import hashlib import re FILE_PATH = './submit_the_flag_that_is_here.txt' def create_hash_list() : printable_letters = string.printable md5_hash_list = {} sha256_hash_list = {} for char in printable_letters : md5_hash_list[char] = hashlib.md5(char.encode('utf-8')).hexdigest() sha256_hash_list[char] = hashlib.sha256(char.encode('utf-8')).hexdigest() return md5_hash_list, sha256_hash_list def load_ciphertext_file() : with open(FILE_PATH, 'r') as f : ciphertext = f.read() return ciphertext def decrypt_hash(ciphertext, md5_hash_list, sha256_hash_list) : plaintext = '' for idx in range(len(ciphertext)) : if len(ciphertext[idx]) == 32 : for char in md5_hash_list.keys() : if ciphertext[idx] == md5_hash_list[char] : plaintext += char break elif len(ciphertext[idx]) == 64 : for char in sha256_hash_list.keys() : if ciphertext[idx] == sha256_hash_list[char] : plaintext += char break return plaintext def main() : md5_hash_list, sha256_hash_list = create_hash_list() ciphertext = load_ciphertext_file() ciphertext = ciphertext.split(' ') plaintext = decrypt_hash(ciphertext, md5_hash_list, sha256_hash_list) flag = re.search('F#{.*}', plaintext) if flag : print('[+] Flag: {0}'.format(flag.group())) else : print('[+] Flag was not found.') if __name__ == '__main__' : main()
以上のコードを実行するとフラグを得られました。
python decrypt.py [+] Flag: F#{Y3aH_Y0u_kN0w_mD5_4Nd_Sh4256}
フラグ
F#{Y3aH_Y0u_kN0w_mD5_4Nd_Sh4256}
[REVERSING 60pts] Blackbox-0 (52 solves)
問題文
If i were you, i would not try to reverse engineer the code of this binary.
添付ファイル
Blackbox-0.exe.zip
解法
ダウンロードしたファイルを解凍して出てきたBlackbox-0.exe
のファイル形式を確認すると、PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
でした。
dnSpyでBlackbox-0.exe
をデコンパイルし、コードを見ると、コードが難読化されていました。
怪しい処理をしている部分を探していると、\u000F\u2009
の354行目で変数text
をリターンしている部分を見つけました。
ここにブレークポイントを設定して何度かContinueすると、変数text
に以下の文字列が代入されました。
-D RiN7TmljZV9hbmFsaXN5c19icm9fPV1ffQo=
RiN7TmljZV9hbmFsaXN5c19icm9fPV1ffQo=
をBase64でデコードするとフラグが表示されました。
echo RiN7TmljZV9hbmFsaXN5c19icm9fPV1ffQo= | base64 -d F#{Nice_analisys_bro_=]_}
フラグ
F#{Nice_analisys_bro_=]_}
[REVERSING 164pts] Blackbox-1 (35 solves)
問題文
If this were an ELF, you would solve the challenge by running ltrace blackbox | grep "F#{"
添付ファイル
Blackbox-1.exe.zip
解法
ダウンロードしたファイルを解凍して出てきたBlackbox-1.exe
のファイル形式を確認すると、PE32+ executable (console) x86-64 Mono/.Net assembly, for MS Windows
でした。
Blackbox-0と同じく、dnSpyでBlackbox-1.exe
をデコンパイルし、コードを見ると、コードが難読化されていました。
怪しい処理をしている部分を探していると、\u000F\u2009
の358行目で変数text
をリターンしている部分を見つけました。
ここにブレークポイントを設定して何度かContinueすると、変数text
にフラグが代入されました。
フラグ
F#{That_was_simple,_huh?_:P}
[REVERSING 478pts] BlackBox Cypher (9 solves)
問題文
なし
添付ファイル
BlackBox-Cypher.exe.zip
解法
ダウンロードしたファイルを解凍して出てきたBlackBox-Cypher.exe
のファイル形式を確認すると、PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
でした。
dnSpyでBlackBox-Cypher.exe
をデコンパイルし、コードを見ると、コードが難読化されていました。
怪しい処理をしている部分を探していると、\u0002\u200A
の80行目で変数result
をリターンしている部分を見つけました。
ここにブレークポイントを設定して何度かContinueすると、変数result
に以下の文字列が代入されました。
RiN7SXQnc19hbGxfYWJvdXRfbWVtb3J5X2ZvcmVuc2ljc30K
これをBase64でデコードするとフラグが表示されました。
echo RiN7SXQnc19hbGxfYWJvdXRfbWVtb3J5X2ZvcmVuc2ljc30K | base64 -d F#{It's_all_about_memory_forensics}
フラグ
F#{It's_all_about_memory_forensics}
おわりに
PwnとWebの60pts問題を解けなかったので、今後の課題として勉強していきたいです。
gg
FireShell CTF 2019のWriteupは以上です。