ちょっとずつ成長日記

強くなりたいと願いつつ少しずつ頑張る日記

TWCTF 3rd simple_note

この問題は64bitのELFファイルでできているheap問題だった。本番環境では実際に試していないため、どのくらい差異があるのかわからないが、自分の備忘録として記録しておく。まずはセキュリティチェック
f:id:shimasyaro:20170913142139p:plain
バイナリを解析していると以下のようなことが分かった。

  • Mallocするsizeが0x80より下であった場合強制終了

  • editの部分でstrlenが使われているが、off-by-one errorがある。

  • mallocされたポインタはlistで管理されている。

つまり、off-by-oneを利用してsizeをうまく書き換えて、systemを起動させることが必要である。しかし、Sizeが制限されているため、fastbinsの使用は許されない。そこで今回はunsafe unlink attackをやっていく。
まずは、下準備として、libcの特定をやっていく。特定の仕方としては、まず最初に、最低2つのadd(malloc)されたものを用意し、その中で一番最初にadd(malloc)されたものをdelete(free)する。その状態を以下に示す。
f:id:shimasyaro:20170913144156p:plain
次に、再び、同じサイズでadd(malloc)をする。このとき、改行文字を含めて全部で8byte分だけ、書き込む。すると以下のようになる。
f:id:shimasyaro:20170913144347p:plain
これで、showを行うと、main_arena+88のアドレス(unsorted bins)をleakすることができる。これにより、libcの特定ができる。
libcは特定できたため、次はunlink attackである。freeする対象のlistは5番目(index 4)である。なぜ、index 4をfreeするのかをunlink attackの復習を兼ねて見てみよう。
f:id:shimasyaro:20170913150054p:plain
unlinkのされ方としてまず、freeされる自身の上方がfree chunkであるかどうかを確かめて、freeであったら(つまり、previn_use bitが立ってなければ)unlinkの処理に入る。今回は上方がfreeされている状態をわざとchunk(fake chunk)を作る。まずは、fake chunkが作られる前である。
f:id:shimasyaro:20170913150347p:plain
fake chunkを作った後は以下のようになる。 f:id:shimasyaro:20170913150739p:plain
注目してほしいのは赤枠で囲っている二つである。まず、一番上で囲っているものはfake chunkである。fdとbkを用意し、unlinkをするために意識して準備したものである。今回はlistの1番目(index 0)のアドレスをfake chunkとつなげる。まずは、unlinkの処理を見てみよう。
f:id:shimasyaro:20170913151820p:plain
Pの部分にはfreeされる上方のchunkつまり、fake chunkが入っている。するとまず、1個目のcheckがある。これは、fake chunkのサイズとfreeされるprev_size(index 4のprev_size)が同じかどうかを確かめている。このチェックは14.04ではなかったが、16.04のglibcでは追加されているのでバージョンの違いに注意してほしい。今回の問題は16.04でもいけるようにprev_sizeを用意する。
次の問題であるが、P->fd->bkとP->bk->fdがPと一致しなければならない。つまり、fake chunkのfd+24とbk+16がPを指していなければエラーとなる。
最後に書き換わる順番であるが、まず、bkに入っているものに書き換わり、次にfdとなるので、fdを中心に考えていかなければならない。 以上をまとめると以下のようになる。

  • listのindex 3がfake chunkのprev_size(つまりP)になるようにしてfake chunkを用意する。

  • fake chunkのfd,bkはfd == (fake chunkとつなげたい場所) - 24, bk == (fake chunkとつなげたい場所) - 16とする。※今回、つなげたい場所はindex 0

最終的に書き換わると以下のように変化する。まずは変化前である。
f:id:shimasyaro:20170913154544p:plain
まだ、赤枠で囲っているindex 3は書き換わっていないことが分かる。次は、書き換わった後である。
f:id:shimasyaro:20170913155302p:plain
赤枠で囲っているindex 3がindex 0のアドレスに書き換わっていることが分かるだろうか。つまり、index 3に書き込もうとするとindex 0のアドレスに書き込もうとする。このことを利用して、index 3でeditを行い、atoiのgotに書き換え、index 0でeditを行い、atoiのgotに対して、systemのアドレスを(GOT overwrite)書き込む。
最後に、次の選択で/bin/shを書きこめば、shellが取れる。
とても、参考になったexploitコードが以下にあるので、よかったらどうぞ。

gist.github.com

なにかしら、説明に間違えあったら教えてください。

【総評】今のPwnのeasy levelがこれってマジですか?