2023 年 1 月に開催されていた KnightCTF 2023 に参加しました。
難易度はそこまで高くなさそうだったので Rev 全完狙えそうでしたが、開始時間を間違えていたために時間が足りなく、4 Solvでフィニッシュしました。
今回解いた問題について簡単に 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)
比較的素直に解ける ELF 問題でした。
バイナリを実行させるためには実行時の引数に適当な値を設定して 5 つにする必要がありました。
また、そのあとの入力には 0x27 文字を入力する必要があります。
文字列の入力に成功したら、入力文字列は以下の箇所で 4 つのパートに分けて 9 文字ずつ検証されます。
最終的に各パートの検証処理を行っている処理のデコンパイル結果から 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)
虎に食われるか海賊に襲われるか、どうあがいても絶望な Jimmy 君の運命を変える必要があります。
ファイルを解析してみると、デコンパイル結果には反映されていないものの、ディスアセンブルした結果から謎の関数にジャンプするパスがあることが確認できます。
gdb でこの位置にブレークポイントをセットし、 ZF を書き換えてこの関数にとばしてあげることで Flag を取得できました。
The Activator(Rev)
デコンパイル結果を見ると、かなり複雑な入力検証処理をしていましたが、正しいパスワードが入力されたときに実行される関数が Flag を出力していることがわかりました。
そのため、gdb を使ってこのアドレスにジャンプすることで Flag を取得できました。
The Defuser(Rev)
デコンパイル結果を詳しく追っていくと、環境変数に特定の文字列がセットされているかどうかをチェックしていることがわかりました。
そのため、正しい環境変数をセットしてバイナリを実行することで Flag を取得できました。
Hello(Network)
簡単そうだったのでついでに解きました。
問題のパケットキャプチャを展開すると、謎のサブドメインに対する DNS クエリが複数発行されていることを確認しました。
時系列で並べた時の最後の文字が == だったので Base64 であることを特定し、VVBCTHtvMV9tcjNhX2VuMF9oazNfaTBofQ==
という文字列を抜き出すことができました。
これを Base64 デコードすると、UPBL{o1_mr3a_en0_hk3_i0h}
という文字列がでてきます。
しかし、フラグフォーマットが異なるため、何らかの暗号化が行われていることがわかります。
ROT13 かとも思ったのですが、マッチするキーはありませんでした。
正規のフラグフォーマットはKCTF
なので、これを暗号化した結果UPBL
になりそうな暗号方式としては、直感で換字暗号だろうと当たりをつけました。
最終的に、換字暗号の一種であるヴィジュネル暗号の変換表で、K が U になり、C が P になる文字・・・を順に特定していきました。
最終的に KNIG をキーとしたところでUPBL
がKCTF
に置き換わりましたが、今回は KNIGT CTF であるため、キーをKNIGT
とした場合の復号結果であるKCTF{v1_ce3s_yu0_xx3_a0b}
が Flag になりました。