問題
解いてみた
ソース見ます。
vuln()戻りアドレスをmain()じゃなくてflag()にしたらいい問題でしょうか。
とか思ったけど、そもそもいきなりジャンプでflag()に飛ばして、if文をさらに飛ばせばflag表示されるんじゃないかと思ってやってみました。
さすがにダメなんですね。
pushとかちゃんとやらずにジャンプだけしてもやはりだめか。
当初の予定通りvuln()の戻りアドレスをflag()に書き換える作戦にします。
まずは何文字目にアドレスを入力すればよいか調べます。
んー、そういえばこの問題は戻りアドレスを出力してくれないので簡単に確認できないんでした。
前の問題が易しすぎたということか。
picoCTF 2019 OverFlow 1 - Points: 150
https://qiita.com/CTFman/items/ed6985c45bb9f909fbd2
gdbでvulnの終了直前にリターンアドレス書き換えればいいんじゃないかと思って、やってみました。
そしてflag()までは飛べたことを確認できたんですが、その先に進もうとするとやはり同じエラーが。
gdbを自分自身が実行しているから、flag.txtを開く権限がないという話な気がしてきた。
やはりリターンアドレスを確認して、普通に実行したときにオーバーフローしないといけないようです。
普通に実行したときにリターンアドレスが何になってるか調べます。
リターンアドレスは0x0804871cということがわかりました。
念のため確認するとcall vulnの直後のアドレスと同じなので合ってそうです。
長めの文字を入れてオーバーフローをしないといけないんですが、vuln()内の配列bufの長さBUFSIZEは7行目で176文字ということなので、200文字で試してみます。
適当にランダムな文字列を200文字入力してespの中身を確認してみると0x554c4d32になってたので、さっきと違います。
つまり上書きされたということ。
0x554c4d32が何かというとULM2です。
リトルエンディアンなので2MLUがランダム文字列の中にあるはずなので検索してみたところ、189文字目に出てきました。
最終的に飛ばしたいflag()の先頭アドレスは0x080485e6です。
なので2MLUのところを0x080485e6にすればよいはず。
リトルエンディアンに注意してこんな感じにします。
flag()ではif文の比較が2つあって引数も2つあるのでそれを後ろにつけます。
「ダミーデータ リターンアドレス 引数1 引数2」の順です。
これで実行してみます。
ダメでした。
たぶん普通の状態でメソッドが呼ばれたときのスタックの状態は以下のようになってるはずです。
この時に引数1を使おうとするとespから2つぶん下の段のものを使用することになります。
そして今vulnから無理やりflag()に飛ばした時の状態は以下です。
この状態でespから2つぶん下の段のものを使用しようとすると引数2が取れてしまいます。
なのでif文でうまくいかなかったんだと思います。
ということでリターンアドレスと引数1の間にダミーデータを入れる必要がありそうです。
これで再度実行してみます。
できたー。