196の日記

セキュリティ系の勉強、その他開発メモとか雑談、忘れそうな計算式などを書き溜める場所になっています. githhubはUnity触っていた頃ものがメイン https://github.com/196kakinuma

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 

次は入力がどのいちに反映されるか確認します。

f:id:thinline196:20180712223719p:plain

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を挟むこと。

結果

f:id:thinline196:20180712225818p:plain

しっかりlsコマンドを使用できているので、eipを奪えています。




何が言いたかったかというと、%hhnを使用するときのオーバーフロー分の計算は16進数で求めて、最後に必要な文字数を10進数で表したほうがわかりやすいよ