Ricerca CTF 2023 writeup
投稿日: 更新日:
コンテストサイト:https://2023.ctf.ricsec.co.jp/
結果
6問解けて589pts(55th)でした!
welcome
Discordに参加して#announcementを見る。
crackme
与えられたファイルを実行すると、パスワードを要求されたのでIDAを使って見てみる。
それっぽい文字列があるので入力してみる。

$./crackme
Password: N1pp0n-Ich!_s3cuR3_p45$w0rD
[+] Authenticated
The flag is "RicSec{}"
あたり!
Revolving Letters
配布されたコードを見ると文字列をずらしていることが分かる。
result += LOWER_ALPHABET[(LOWER_ALPHABET.index(secret[i]) + LOWER_ALPHABET.index(key[i])) % 26]
逆にずらせば良いので、+
を-
にかえ、flag
のとこに暗号化された文字列をいれる
LOWER_ALPHABET = "abcdefghijklmnopqrstuvwxyz"
def encrypt(secret, key):
assert len(secret) <= len(key)
result = ""
for i in range(len(secret)):
if secret[i] not in LOWER_ALPHABET: # Don't encode symbols and capital letters (e.g. "A", " ", "_", "!", "{", "}")
result += secret[i]
else:
result += LOWER_ALPHABET[(LOWER_ALPHABET.index(secret[i]) - LOWER_ALPHABET.index(key[i])) % 26]#変更
return result
flag = "RpgSyk{qsvop_dcr_wmc_rj_rgfxsime!}"# 変更
key = "thequickbrownfoxjumpsoverthelazydog"
example = "lorem ipsum dolor sit amet"
example_encrypted = encrypt(example, key)
flag_encrypted = encrypt(flag, key)
print(f"{key=}")
print(f"{example=}")
print(f"encrypt(example, key): {example_encrypted}")
print(f"encrypt(flag, key): {flag_encrypted}")
Cat Café
猫が沢山出てくる。
与えられたファイルを見てみると、flag.txt
がある。ディレクトリトラバーサルする方針がたつ。
app.py
をみてみると、/imgのf
パラメータがパスになってアクセスできることが分かる。
filename = flask.request.args.get("f", "").replace("../", "")
path = f'images/{filename}'
よって../flag.txt
を渡したいが、replace
によって阻止される。replace
された後../flag.txt
となる文字列を作れば良いので....//flag.txt
をパラメータに渡す。
BOFSec
与えられたコードを見てみる。name
は固定長にもかかわらず、そのままscanf
で入力を受け取っているのでバッファーオーバーランが使えそう。
typedef struct {
char name[0x100];
int is_admin;
} auth_t;
...
scanf("%s", user.name);
0x100
は256
なので、適当に260文字くらい入力してみると、フラグを得た。
tinyDB
とりあえずコードを読む。すると以下の箇所を発見。
if (userDB.size > 10) {
// Too many users, clear the database
userDB.clear();
auth.username = "admin";
auth.password = getAdminPW();
userDB.set(auth, "admin");
auth.password = "*".repeat(auth.password.length);
}
適当にユーザーを追加する。
10人以上になるとdbかクリアされ、再びadminが追加される。その時、参照渡し(?)によってadminのパスワードが*
に書き換えられる。
rollback
関数が呼び出される前にadminのページに行きパスワードを打てば良い。