ksnctf Q.4


write up 見ずに頑張ろうと思ってまる 24 時間くらい費やしたけど、どうにも行き詰まり、最終的に、解答方針を見ることになってしまった。

最終的な方針

https://www.slideshare.net/tecsk07/20191005lt slideshare で公開されていた write up を参考にした。

objdump して、fopen を使っている。しかし、esp+418 が 1 になっている限りたどり着かないようになっている。

そこで、ここの処理をまるまる fopen の処理のところまで飛ばしてしまおうというわけ。

具体的には、フォーマット文字列攻撃を使って GOT を書き換えることで jmp する。

下のコードで FLAG を奪取できた。 書き換えた対象アドレス: 0x80499e0 対象アドレスに入れる値(jmp したいアドレス): 0x8048691

python -c "print('\xe0\x99\x04\x08\xe2\x99\x04\x08%34441c%6\$hn%33139c%7\$hn')" | ./q4

これは、書き換え先のメモリアドレス(0x080499e0 ~ 0x080499e3)を最初にメモリに載せといて、 %n はこれまでかきこんだバイト数を指定したアドレスに書き込むフォーマット指定子だ。 %h を付け加えると 2 バイト分書き込むようになる。 %6$hn  ここで参照してメモリを上書きする。 上の例では、これを 2 バイトごとに、二回繰り返している。(リトルエンディアンであることに注意)

上書きする値は%34441cここで調節する。 %Nc は、N 回文字を書きこんでくれる。

ここで、34441 = 0x8689 になっている。 前述の通り、%n はそれまでかきこんだバイト数をアドレスに書き込むため、 すでに書き込まれているはずの\xe0\x99\x04\x08\xe2\x99\x04\x08の 8 バイト分を引いておく。 つまり、0x8691 - 8 の結果。

33139c  も同様に、0x10804 - 0x8691  の結果となっている。

こうして、0x80499e0 のポインタの示してるアドレスにジャンプする処理が入ったら、 0x8048691 にジャンプするようになる。

ゴールに行き着くまで

かなり最初の時点で、fopen で flag.txt を開いていることはわかっていた。 そのため、gdb でメモリの値を書き換えて、処理にたどり着こうとする。 すると、処理の途中でセグフォオで落ちてしまう。 再度 objdump を確認すると、fopen してもそのファイルの中身を読み込んでいないと勘違い。 (fgets は標準入出力限定だと思い込んでいた) そのため、この処理はダミー的な何かじゃないかと思い込んでしまった。 最大の敗因はここである。 正直なんで gdb でメモリを書き換えてやって上手くいかなかったのかわからない。

続いて、フォーマット文字列攻撃であることはわかるところまで進む。 僕は策謀本でフォーマット文字列攻撃を通して shell を起動する exploit を参考にして手を動かし始めた。

しかし、いくらやっても上手くいかない。 100 万回ぐたいアドレスを計算しなおして、やっぱり上手くいかない。 具体的には、puts の GOT を書き換える試みだった。

失敗すればするほど、視野が狭まってしまうのが身に染みてわかった問題だった…。

知識的には、独力で解ける問題だったと思います。残念だぁぁぁぁ…

ほんとうになんで gdb でメモリいじった時は上手くいかなかったのかわからない。