web-dev-qa-db-ja.com

なぜret2libc攻撃は「system()、exit()、command」の順序に従う必要があるのですか?

Ret2libc攻撃では、コマンド文字列を引数として取るシステムコマンドのアドレスで戻りアドレスを上書きできることを理解しています。この場合、コマンド文字列のアドレスはsystem()のアドレスの直後に来るべきではありませんか?ただし、私が見たほとんどのチュートリアルは次の形式に従います:system()。address of exit()。address of command stringのアドレス。

なぜexit()のアドレスを含める必要があるのですか? exit()が除外されている場合でも攻撃は機能しますか?

8
Lew Wei Hao

Ret2libc(およびリターン指向プログラミング(ROP))手法は、スタックの上書きに依存して、システム関数を呼び出す新しいスタックフレームを作成します。このウィキペディアの記事では、スタックフレームについて詳しく説明しています: https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers

スタックフレームは、関数呼び出しとパラメーターが書き込まれる順序を指示します。

_function address return address parameters_

したがって、あなたの例では、system()cmdstringで呼び出し、exit()呼び出しが戻ったときにsystem()関数に戻ります。したがって、次のスタックフレームを記述します。

_system_addr exit_addr cmdstring_addr_

出口アドレスを削除すると、スタックフレームが次のように変更されます。

_system_addr cmdstring_addr existingdataonstack_aka_junk_

つまり、ジャンクアドレス引数を指定してsystem()を呼び出し、関数が完了したらコマンド文字列に戻ろうとしています。それが失敗する理由です。 exit()アドレスを_0x41414141_などの他のデータに置き換えると、system()呼び出しが完了するとsegfaultが発生します。または、_pop pop ret_の場所のアドレスに置き換えて、その下にさらにスタックフレームを書き込むこともできます。これはROPペイロードになりました。これがスタックでどのように見えるかの基本的な例です:

_system_addr poppopret_addr cmdstring_addr printf_addr exit_addr addr_of_string_to_printf_

これにより、終了する前に_You got hacked_のようなものを出力できます。

7
wireghoul

exit()が含まれている理由は、プログラムを終了するためです優雅に。チェーンの最後にexit()がない場合、プログラムは奇妙に実行し続けるか、セグメンテーション違反で終了する可能性があります。 exit()への呼び出しを含めることは必須ではありません。理想的には、その後もプログラムが通常どおり実行されるようにエクスプロイトを構築し、サービスが実行されなくなったために疑わしい人がいないようにします。

2
mroman