昨日まででCTFの概要が大体分かったので、今日からは実際に問題を解きながら必要だった知識などをまとめていきたいと思います。今日は Daily AlpacaHack を3問解きました!
- Day3については、まだ解答が発表されていないので明日書きます (Mediumなのに激ムズでした...)
Day 1
これは「Welcomeレベル」ということでただ指定のページに飛べばいいだけでした。とは言っても、指定のページというのがサイト内カレンダーの「2100年」のページなので、手作業で「次の月」ボタンを押していたら時間がかかってしまいます。これはmonth=2026-01というクエリパラメータを編集することで解けました。
Day 2
問題
これはCrypto (暗号解読) の問題でした。暗号化を実施するPythonコードと、flagを暗号化した結果が与えられて、元のflagはなんでしたか?を問う問題です。
暗号化の内容としては、flagの各文字をunicode番号に変換し、それぞれを異なる素数の冪乗の指数部分に割り当てることで一つの大きな整数に変換していました。
[15, 112, 4] という整数の列を $2^{15} + 3^{112} + 5^4$ という一つの整数へと変換する感じです。底となる素数の種類が分かれば、この逆変換は素因数分解の一意性により一意に定まりますね。
書いたコード
# output.txt は、flagの各文字のUnicode番号を素因数の冪乗部分に当てることで
# string->intと変換したものをhex表現している
# 素因数分解の一意性により、このstring->intの変換は一意に定まる
# 0. output.txtを読み取り
with open("output.txt", "r") as file:
flag_hex = file.read()
# 1. hex -> int
flag_int = int(flag_hex, 16)
# 2. この数をそれぞれの素数で何回割り切れるかを記録する
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293]
flag_unicode_vals = []
for prime in primes:
if prime == 1:
break
div_count = 0
while flag_int % prime == 0:
div_count += 1
flag_int //= prime
flag_unicode_vals.append(div_count)
# 3. Unicode番号をstringへと変換する
flag = ""
for val in flag_unicode_vals:
flag += chr(val)
# flagが求められたはず!
print(flag)
結果
このPythonファイルを実行したら、ターミナルに
Alpaca{本当の答え} (ネタバレ防止で隠してます)
と出てきました!
答えが見つかった時の快感がすごいです
まとめ
今日はここまでです。実際に問題を解いてみて、CTFのプログラミング・コンピュータの総合格闘技としての難しさを感じました!一つの分野だけ知ってれば良いということではなく、本当に幅広くなんでも知っていないといけない...
特にDay3から色々学べたのですが、こちらについては明日書きます!
