osu!gaming CTF 2024
順位は367位/984位でした。
目次
- misc/discord
- misc/survey
- osu/sanity-check-1
- misc/Infiltrating the OSU! (I)
- crypto/base727
- web/mikufanpage
- crypto/ROSSAU
- osu/smoked
- pwn/betterthanu
- misc/Infiltrating the OSU! (II)
- forensics/nathan-on-osu
- まとめ
misc/discord
チャンネル「announcements」で開始直後(2024/3/2 2:00)にsahuangさんが発言した文章の中にflagがあります。
文章がかなり長いので今回は写真省略します。
osu{Rhy7hm_15_L1f3}
misc/survey
アンケートに答えるとflagが取得できます。
osu{push_these_poochs_off_me_like_BAU}
osu/sanity-check-1
osu{welc0me_2_osu!!}
misc/Infiltrating the OSU! (I)
この問題は以下の画像のURLを「https://assets.ppy.sh/
」の中から探し出し送信するとflagが送信されます。
ヒントとしてhoifanrdさんのosu!プレイヤー情報が提供されているのでその中から同じような画像がないか調べます。
赤い矢印で指された画像のURLを送ればよさそうです。この画像のURLは開発者ツールで見ることができます。
ちなみにここでCtrl+Shift+Cを同時押しするとその画像をクリックするだけで画像のURLがわかるのでお勧めです。
送信したらflagが出てきました。
osu{tr1v4l_5rc_1n5p3c7_1n_webs1t3}
crypto/base727
カテゴリにChatGPTと書いてあったので与えられたファイルのコード(727.py)の逆の手順をたどるコードをChatGPTに依頼したらこのようなコードが返ってきました。
import binascii
def decode_base_727(encoded_string):
base = 727
decoded_value = 0
for char in encoded_string:
decoded_value = decoded_value * base + ord(char)
decoded_string = ""
while decoded_value > 0:
decoded_string = chr(decoded_value % 256) + decoded_string
decoded_value //= 256
return decoded_string
# 与えられたBase727でエンコードするコード
encoded_hex_string = b'06c3abc49dc4b443ca9d65c8b0c386c4b0c99fc798c2bdc5bccb94c68c37c296ca9ac29ac790c4af7bc585c59d'
encoded_string = binascii.unhexlify(encoded_hex_string).decode()
decoded_string = decode_base_727(encoded_string)
print(decoded_string)
実行するとflagが出ました。
osu{wysiwysiwysiywsywiwywsi}
web/mikufanpage
ダウンロードしたファイルの中にReadme.mdがあったので開いたらflagがあったのでそのまま入力したら正解してしまった・・・
大丈夫なのかこれ。
ちなみに正攻法は
https://mikufanpage.web.osugaming.lol/image?path=miku1.jpg./../flag.txt
のように接続するとflagが出てくるディレクトリトラバーサルの問題だったらしいです。
osu{miku_miku_miku_miku_miku_miku_miku_miku_miku_miku_miku_miku_miku}
crypto/ROSSAU
これはeがかなりでかいのでwiener's attackが適用できます。
過去にwiener's attackの記事書いているみたいなのでもしよかったらどうぞ。
今回はdが分かればいいのでこのコードで行きます。
import owiener
e = 876603837240112836821145245971528442417
n = 5912718291679762008847883587848216166109
d = owiener.attack(e, n)
if d is None:
print("Failed")
else:
print("d={}".format(d))
以下のように求まりましたがこれが答えではありません。ユーザ名を特定する必要があります。
osu!のプレイヤー情報のURLのところを見てみると数字が入っているので数字をdの値に変更したプレイヤー情報にしてアクセスすると・・・
chocomintさんのプレイヤー情報になりました。したがってchocomintさんが正解です。
osu{chocomint}
osu/smoked
与えられたファイルはosrファイルでosu!のゲームのリプレイファイルとなっています。
osu!アカウントを持っていなくてもこちらでできます。
flagはリプレイしている最中にカーソルで書いているみたいです。ちなみに私はosu!をやったことないのでもしかしたらカーソルじゃなくてほかの方法でやってる可能性があります。
osu{smoked_map_fun}
pwn/betterthanu
コードは以下のようになっています。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
FILE *flag_file;
char flag[100];
int main(void) {
unsigned int pp;
unsigned long my_pp;
char buf[16];
setbuf(stdin, NULL);
setbuf(stdout, NULL);
printf("How much pp did you get? ");
fgets(buf, 100, stdin);
pp = atoi(buf);
my_pp = pp + 1;
printf("Any last words?\n");
fgets(buf, 100, stdin);
if (pp <= my_pp) {
printf("Ha! I got %d\n", my_pp);
printf("Maybe you'll beat me next time\n");
} else {
printf("What??? how did you beat me??\n");
printf("Hmm... I'll consider giving you the flag\n");
if (pp == 727) {
printf("Wait, you got %d pp?\n", pp);
printf("You can't possibly be an NPC! Here, have the flag: ");
flag_file = fopen("flag.txt", "r");
fgets(flag, sizeof(flag), flag_file);
printf("%s\n", flag);
} else {
printf("Just kidding!\n");
}
}
return 0;
}
以下の条件を満たせばflagを取得することができます。
- pp = 727であること(最初に入力する部分)
- pp > my_pp であること(ただしmy_pp = pp + 1)
1つ目の条件を守ると2つ目は
my_pp = 728
pp = 727
なので条件を満たさなくなってしまいます。
2つ目の条件を守る(unsigned int型を利用してpp = 4294967295)と入力すると
pp = 727ではないので1つ目の条件を満たさなくなります。
ここで以下の部分に注目します。
printf("Any last words?\n");
fgets(buf, 100, stdin);
この部分にたくさんの文字を入れてif (pp <= my_pp)
を無視できるように書き換えれば2つ目の条件を回避することができます。これで1つ目の条件を守りつつ2つ目の条件を回避でflagが手に入るようになります。
ちなみに私は9を16回入力して回避しました。
osu{i_cant_believe_i_saw_it}
実はpwnは外部CTFで初めて自力で解けました。
misc/Infiltrating the OSU! (II)(解けなかった)
Google画像検索するとその画像があるURLを調べられます。
その中で「i.ppy」にあり、かつ寸法が1100x280pxの画像を探してURLを送信するとflagが送信されます。
osu{d1d_y0u_p2w???0r_d1d_y0u_f2w_by_u51ng_7h3_f0rum???}
ちなみにWriteup書いている間に分かりました。misc/Infiltrating the OSU! (I)の影響を強く受けすぎてhoifanrdさんのosu!プレイヤー情報のサイトのなかをずっと探し回ってました。英語ちゃんと読めていれば・・・
forensics/nathan-on-osu(解けなかった)
スクショなのでなんか加工前の画像に復元するものあるのかなと思っていたらやっぱりありました。
こちらは「aCropalypse」という脆弱性でherietさんが詳しく解説しています。
以下のサイトで高さ1080 x 幅1920と入力して問題の写真ファイルを選択するとできるみたいです。ちなみにどうやってその高さと幅を特定するかはわかりませんでした・・・
osu{cr0pp3d_Future_Candy<3}
まとめ
後もう少しで解けた問題があったのでかなり悔しいです・・・