All Articles

KnightCTF CTF 2022 Writeup

2023 年 1 月に開催されていた KnightCTF 2023 に参加しました。

難易度はそこまで高くなさそうだったので Rev 全完狙えそうでしたが、開始時間を間違えていたために時間が足りなく、4 Solvでフィニッシュしました。

image-20230121235349947

今回解いた問題について簡単に Writeup を書きます。

今回解いた Rev 問のバイナリを実行するためには glibc2.3.4 が必要だったので、以下の Dockerfile で作成した Docker イメージを使いました。

# glibc2_3_4-ubuntu20_10
FROM ubuntu:21.10
ENV TZ=Europe/London
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN sed -i -e 's/archive.ubuntu.com\|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list
RUN apt update && apt upgrade -y
RUN apt install gdb strace ltrace vim unzip zip git -y

RUN mkdir -p /app
ENV HOME=/app
WORKDIR $HOME

KrackMe 1.0(Rev)

image-20230121115824664

比較的素直に解ける ELF 問題でした。

バイナリを実行させるためには実行時の引数に適当な値を設定して 5 つにする必要がありました。

また、そのあとの入力には 0x27 文字を入力する必要があります。

image-20230122175857705

文字列の入力に成功したら、入力文字列は以下の箇所で 4 つのパートに分けて 9 文字ずつ検証されます。

image-20230122175041238

最終的に各パートの検証処理を行っている処理のデコンパイル結果から Flag を復号する以下のスクリプトを作成ししました。

# -0x9
unknown = [0x6d,0x65,0x72,0x60,0x5d,0x4d,0x74,0x47,0x65]
c100 = 100
# 0x6142202c 776f6e6b
c60 = 
for u in unknown:
    print(chr(
        u ^ c100 ^ c60
    ), end="")

>> KCTF{kRaC

# 0x1b -
unknown = [0x76,0x7d,0x51,0x6c,0x4f,0x74,0x6f,0x7c,0x73]
c108 = 0x6f
c130 = 0x61
for u in unknown:
    print(chr(
        u ^ c108 ^ c130
    ), end="")

>> xs_bAzar}

# 0x9-0x11
unknown = [0x61,0x55,0x47,0x39,0x55,0x65,0x44,0x6f,0x55]
u1 = 0x65
c138 = 0x6f
for u in unknown:
    print(chr(
        u ^ u1 ^ c138
    ), end="")

>> k_M3_oNe_


# 0x12-0x19
unknown = [0x28,0x47,0x7e,0x54,0x79,0x5f,0x47,0x7b,0x28]
u1 = 0x65
c152 = 0x7d
for u in unknown:
    print(chr(
        u ^ u1 ^ c152
    ), end="")

>> 0_fLaG_c0

Help Jimmy(Rev)

image-20230121153544694

虎に食われるか海賊に襲われるか、どうあがいても絶望な Jimmy 君の運命を変える必要があります。

image-20230122182305522

ファイルを解析してみると、デコンパイル結果には反映されていないものの、ディスアセンブルした結果から謎の関数にジャンプするパスがあることが確認できます。

image-20230122182342802

gdb でこの位置にブレークポイントをセットし、 ZF を書き換えてこの関数にとばしてあげることで Flag を取得できました。

The Activator(Rev)

image-20230121192130229

デコンパイル結果を見ると、かなり複雑な入力検証処理をしていましたが、正しいパスワードが入力されたときに実行される関数が Flag を出力していることがわかりました。

そのため、gdb を使ってこのアドレスにジャンプすることで Flag を取得できました。

The Defuser(Rev)

image-20230121192032089

デコンパイル結果を詳しく追っていくと、環境変数に特定の文字列がセットされているかどうかをチェックしていることがわかりました。

そのため、正しい環境変数をセットしてバイナリを実行することで Flag を取得できました。

Hello(Network)

image-20230122182944951

簡単そうだったのでついでに解きました。

問題のパケットキャプチャを展開すると、謎のサブドメインに対する DNS クエリが複数発行されていることを確認しました。

image-20230122183101094

時系列で並べた時の最後の文字が == だったので Base64 であることを特定し、VVBCTHtvMV9tcjNhX2VuMF9oazNfaTBofQ==という文字列を抜き出すことができました。

これを Base64 デコードすると、UPBL{o1_mr3a_en0_hk3_i0h}という文字列がでてきます。

しかし、フラグフォーマットが異なるため、何らかの暗号化が行われていることがわかります。

ROT13 かとも思ったのですが、マッチするキーはありませんでした。

正規のフラグフォーマットはKCTFなので、これを暗号化した結果UPBLになりそうな暗号方式としては、直感で換字暗号だろうと当たりをつけました。

最終的に、換字暗号の一種であるヴィジュネル暗号の変換表で、K が U になり、C が P になる文字・・・を順に特定していきました。

image-20230122183758082

参考:ヴィジュネル暗号 - Wikipedia

最終的に KNIG をキーとしたところでUPBLKCTFに置き換わりましたが、今回は KNIGT CTF であるため、キーをKNIGTとした場合の復号結果であるKCTF{v1_ce3s_yu0_xx3_a0b}が Flag になりました。

image-20230122184001932