cute_otter’s blog

ハニーポットの観察日記を付けています

FireShell CTF 2019 Writeup

はじめに

こんにちは。cute_otterです。
2019/01/27 01:00~2019/01/28 02:30(JST)にかけて開催されたFireShell CTF 2019に、一人チーム「cute_otter」で参加しました。
結果は1002ptsで28位(点を取った570チーム中)でした。

f:id:cute_0tter:20190128153206p:plain

問題ファイルは、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

そこで、以下の復号アルゴリズムを考えました。

  1. ファイル内に存在すると思われる文字のMD5ハッシュ値とSHA256ハッシュ値を算出し、文字とハッシュ値が対応する辞書を作る。
  2. ファイルのハッシュ値と一致するハッシュ値が辞書内にあれば、辞書のキー(ハッシュ値の元の文字)を出力する。

以上の復号アルゴリズム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は以上です。