記事に入る前に
URLが2025!45の二乗!やった!
4/21のCPCTFに参加して、2177.31点、総合30位、新入生7位でフィニッシュでした。
参加したはじめはCTFの技をほどんと知らなかったのが、だんだんとデコンパイルなどを知っていくうちに楽しくなっていった。難易度順で解いていったのでこの記事でも最初と最後で太刀打ちの仕方が変わっているのがわかるかもしれない?
解けた問題に関して、面白かったCTF中心でいろいろ書き綴っていきます
NEWBIE
Attack! Attack! Win!
敵と戦って勝とう!という趣旨で実行ファイルと戯れる
とりあえずAttackだけしておけば勝てそうと思ったが、何せ自分の攻撃力よりも相手の攻撃のほうが痛い。Healをしても間に合わない。そこで3を入れると...?
Memory leak!
Attack : 0x564724e41070
Heal : 0x564724e41078
HocusPocus : 0x564724e41080
win : 0x564724e41058
なんとwinコマンドが!後半の数字はメモリの場所かな
数値を見る限り、行動の番号の大小関係とメモリアドレスの大小関係が同じらしい。つまり、winコマンドを実行するには1より小さい数を入れればいいのだろう。それほど数が離れているわけでもないので、0から順に入れてみると...
0: セグフォ
-1: 即死コマンドだった
-2: You got the flag!
というわけでフラグをキャプチャ
(宣言が、win、敵の攻撃、コマンド一覧の順番だったのでこうなったっぽい)
Substitution
おっシーザー暗号か?と思って試してみるも、いい感じにはならず。手がかりを探して一対一の関係を探らねば。さすがに大文字小文字で対応が違うということはないと祈りながら、文章を観察していくと、順番に気づいていったことがこんな感じ。(変換前を大文字、変換後を小文字にして整理していた)
- 末尾のETEIB{...→CPCTF{...
- B→fを見ると、最後から2文目2単語目の3文字buk→for
- coMP→codeが妥当?
- CeVV doZe!→well done!でしょ
- cpctf{Jello_crRpto_world}→cpctf{hello_crypto_world}か!
こんな感じでフラグをキャプチャ。推理楽しかった
Easy
CPCTP......
4文字printfさせるからなるべく長く出力させてね、という問題。型指定子をいい感じに当てれば未定義動作踏んでくれて解けそう。いろいろ試した結果...
Please enter some string! (max 4 character)
%a%b
Thank you!
Your input:0x0.07fda3063378p-102211101010110101010011001110010000
Length: 54
This is your reward!
CPCTF{1m_50rrY_bu7_i_Hav3_0nLy_45_ch4raCteRs}
としてみたらいけた~
終わった後に聞いた話が、`%99d`として99桁表示させればいいよね、という話を聞いた。絶対想定解じゃん...
Let's buy some array
phpの`eval`で悪いことをしてフラグをとろう、という問題。
もともと、個数には数値しか入れられないが、開発者ツールでhtmlをいじれば何でも入力できるようになっちゃう。なので、数値のみの制限を外して、
eval("echo getenv('FLAG');")
とすると、フラグが表示されて、キャプチャ。
SQLインジェクションみたいなことできて楽しかった。
Number Guesser
バイナリの要求する入力に正しい数字(明かされていない)を入れたらフラグをくれるよ、という問題。
ここで初めてバイナリのデコンパイルをしてみると、入力された数値を文字列としてみたときに答えの数字と同じ文字列かどうかの判定があった!
というわけでその文字列を打ってフラグをキャプチャ。
初めてのデコンパイル楽しかった。解くときにGhidraを使ってデコンパイルをしたが、Webでデコンパイルはできるらしい。マジかと思って検索したら本当にできちゃった。マジですか。
RSA Trial
公開鍵とRSAでおなじみ素数p,qについてのヒント(p3 +q3の値)が与えられるので、公開鍵で暗号化された鍵を復号してね、という問題。ヒントを使って式を変形して、二次方程式を解けばpとqが割れちゃう。あとは復号をすればいい。ということでフラグをキャプチャ。
RSA、暗号系の問題の典型な感じで楽しい。そしてPythonが上限ほぼなしで整数扱えるのが強すぎる。
Read Novels
配布ファイルを見ると、小説データが乗っているディレクトリの親ディレクトリにフラグのテキストがあるらしいので、どうにかしてその内容が取れればいい。
さらに調べると、どの小説を見るかはURLパラメータで指定して、それをパスの末尾にくっつけていた。であれば、パスを戻ればフラグが手に入るはず。
ということで、URLパラメータを`../flag`としてフラグをキャプチャ
turning over
まさかのBlender。配布ファイルをBlenderで開いて、モードをいじるとフラグがそのまま出てくる。それを書き写せばいいのだが....
_人人人人人人人人人人人人人人人人人_
> 1なのかIなのかlなのかわからん! <  ̄
Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
Iなら1に置き換えられてるだろうので、何とか自然な文章になるように調整して、フラグをキャプチャ。
BlenderもCTFになりうるのか....とても意外
veeeeeeery long text
SSHしてテキストからフラグを取ってくるだけ。簡単....なはずだった
実際にflag.txtを開くと、とんでもない行数が出てくる。なるほど、タイトルはこういうことか。調べてみると、6.2MBもある。バケモンだ。
とはいえ、`grep 'CPCTF{'`をすれば一発で出てきた。もうちょっと出してきてもよかったのよ?100行くらい出てきても...
ということでフラグをキャプチャ。
white has much information
名前からしてもう察しがつく。絶対whitespaceでしょ。正解!やったー!
グーグルで調べると、whitespaceを実行するWebページがあったのでそこに張り付けて、フラグをキャプチャ。
MEDIUM
which is true flag
時間内で提出できたかどうか不明だけど、これは記事を書くべきだと感じた問題。
まずは問題。メールが10000通あって、その中の一通に本物のフラグがあるから、探し出してね、という問題。想定解は、メールアドレスのホストアドレスと、ヘッダに書いてある送信元IPを照合して、整合性が取れれば本物、そうでなければ偽物、として判定するらしい。
ではこの問題で僕は何をしたか......
_人人人人人人人人人人人人人人人人人人人人人_
> 必ずフラグあるから全部送ればいいじゃん <  ̄
Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
とはいえ、さすがに間隔開けずに送るのはまずいので、ルールの禁止事項を確認。
問題サーバー及びスコアサーバー、yukicoderのサーバーに過度な負荷をかけるような行為
これはつまりプログラムによる提出は禁止しないけど、限度は守ってねということ...?と当時の僕は解釈して、すべてのフラグ候補を1秒ずつ送るプログラムを書く。
これでフラグをキャプチャしたはず.........が、なんと、送っていたのがJSONではなくただのテキストデータでキャプチャできていなかった!
これのせいで正しい答えでも不正解が返ってきてしまったらしい。その後、プログラムを書き直してもう一回プログラムを走らせると、無事フラグを特定。提出できてたのかな...?問題を見ると、提出判定になっていなかったのでBAN食らってたかなぁとも思っている。
フラグが特定し終わって初めてアナウンスに「総当たりが必要な問題はありません。」とあったことに気づいた。もっと早く気づいていればよかった...
提出の半分以上が僕の提出でダントツ一位(2万越え)だったのはこれのせいです。運営の皆様、ごめんなさい、そして失格にしないでくれてありがとうございました...