GOT Overwrite - %hhnを使ってみる
GOT Overwrite
以下の二つを満たすと、ライブラリの関数アドレスを保存するGOT領域が書き込み可能となっているらしい
- 実行ファイルがライブラリと動的リンクされている
- No RELRO もしくは Partial RELRO
準備
strlenのアドレスが書き込まれる場所を探します。今回は0x0804a01cだとします。
$ readelf -r got
次にSystem関数のアドレスを探します。ASLR条件下と仮定して、以下のコマンドで調べます。今回は0xf7e52e70だとします。
$ gdb -q got gdb_peda$ b main gdb_peda$ r gdb-peda$ p system
次は入力がどのいちに反映されるか確認します。
7個目ですね。%nは指定されたアドレスを4バイト分と見てprintfが出力している文字数をそこに書き込んでくれます。また%7$nとすれば、先ほどの7番目のアドレスに対して書き込んでくれるという優れもの。%?xとすると?分の文字を出力したと同じ効果があるものも一緒に使用します。
今回は%hhnを使用するということで、1バイト分ずつ書き込んでいこうと思います。ちなみに%hnは2バイト分。
やってみる
0x0804a01c~0x0804a01f(strlenのアドレスが入っていることろ)にSystem関数のアドレス0xf7e52e70を書き込むということで、
- 0x0804a01c には 0x70
- 0x0804a01d には 0x2e
- 0x0804a01e には 0xe5
- 0x0804a01f には 0xf7
を書き込みます。(リトルエンディアン)
で、文字数ですが、
・始めのアドレスを描く部分で16バイト使用します。
・次に、0x70を書き込みために、文字数を112にします。すでに16バイト(0x10)あるので、0x70-0x10=0x60 で%96xでok(注意として、%?xは10進数)これを7番目にhhnで書き込むので、%7$hhn
・次、2eを書き出したいが、すでに文字数が0x70。実はオーバーフロー分は無視されるらしいので、0x12eを目指せばOK。3桁目の1が無視されて書き出される。
・あとは、手作業で。。。
・最後、fgetsの入力は改行でストップするため、2個目のfgetsに入れたいもの(System関数の引数になる)の前に¥nを挟むこと。
結果
しっかりlsコマンドを使用できているので、eipを奪えています。
何が言いたかったかというと、%hhnを使用するときのオーバーフロー分の計算は16進数で求めて、最後に必要な文字数を10進数で表したほうがわかりやすいよ