任意の関数の相対アドレスは配布されたlibcからわかるんだろうなー。想像したところで特に何も思いつかず、競技中はここで思考停止で終了しました。上記で紹介した2つのリンク先に、解法や流れ・解説がとても詳しく載っていたので、こちらでは特に解説なしでコードだけ下の方に載せておきます。ライブラリはpwntoolのみを使っているので、環境が作りやすいはず。さんの記事のコードをほぼそのまま流用させていただきました。下記、初心者すぎてわからなかったマジックナンバーなどの調べ方メモ。one-gadgetというのが出てきたので調べました。こちらでちょっとお勉強。NULL)を実行してくれる親切なgadgetが存在します。アドレスを特定するツールとして下記が紹介されていたので、これを使ってみます。ruby環境があればちゃっと使えそうです。NULLなんだかとってもカラフルな出力だった。installから使い方までとっても簡単でよき。3つ候補が出てきましたがどれを使うんでしょう?それぞれシェルが起動される条件が異なるみたいです。(constraintsに書いてある)One-gadgetの候補が十分少ないので、gdbで確かめながら絞り込むよりも、片っ端から試せばいいよねというのが僕の感想です。結果を先に書くと、2、3試したらうまくいきました。いうことで、3つとも試してみてうまく行くのを探すのが良さそう。疑問が解明したので、exploitコードを紹介記事のシーケンスのとおりに書いてみます。flag.txtctf4b{h07b3d_0f_51mpl3_h34p_3xpl017}Babyって言ってるし、この前初めてpicoCTFの復習でheap問題やってみたし、手を付けてみちゃったんですけど全然駄目でした。再度確認したら13チームしか解いてなかったですね。競技中に「よかった、ちゃんとbabyだった」と言う誰かのつぶやきを見て「ほほう?」と思ってたんですけど、プロから見たらbabyだったってことですかね。ちなみに今回、write-upを見つつわからないところを調べつつ、だったのですが、下記サイトがheap系の知識として読むのに良かったです。本当は体系だってお勉強するのが一番なんでしょうけど、紹介まで。OneLineこの問題も競技中は全く見ませんでしたが、BabyHeapでちょっと調べた内容も使いそうだったので他の方のwrite-upも見つつやってみました。10000配布されたファイルを解凍してみます。こちらも実行ファイルとlibcが入っていました。lsace01bbd1b0165f0c0f43426d7716721_oneline.tar.gzlibc-2.27.sooneline動作確認。testtest2回ほどユーザー入力を受け付けて、入力をそのまま出力してくれるようです。最後の方にちょろっと変な出力が...。faultそして、ちょっと眺めの文字列を入れると、一回目で落ちちゃいました。radare2でmain関数を見てみます。retよくわからない処理があります。rdxここでwrite関数のポインタをstack上に書き出してくれているようです。書かれているようなので、上書きしなければ最後にwrite関数のアドレスが出力されそう。試しに空の文字列を一発目に送ってみます。アドレスが計算できます。バイトに書かれたアドレスを実行しています。入力時にwrite関数のアドレス部分を上書きしていなければ、write関数が実行されるんですね。長めの適当な文字列を突っ込むと、このwrite関数のアドレスが変に上書き→実行され、SegmentationFaultで落ちちゃったってことですね。アドレスがわかるので、任意の関数のアドレスを計算。2回目の入力時に最後に任意の関数のアドレスをくっつけて実行してもらう、というのが良さそう。利用してshellを起動させます。one-gadgetを探してみます。NULL配布されたlibcのバージョンが同じだったからか、結果はBabyHeapのときと同じになりました。あとはこのアドレスを、2回目のinput時の最後8バイト部分に書き込むだけ。感想など沢山の方のwrite-upや作問者の解説を参考にさせていただきました。ありがとうございました!やはり実際に手を動かして、他の方の解き方をなぞるだけでも、かなり理解が深まりますね。(読むだけでは全く頭に入ってこないポンコツだからという話もある)最近はpicoCTFの復習をメインにやっていましたが、picoCTFの最後の方の問題の難易度と同じくらいなイメージでした。次はもう少し点の高い問題も解けると良いなぁ。問題サーバー落ちる予定なので諦めました。手はつけてみたのですが、私の理解度ではとっても時間がかかりそうだったので...。