免責事項:私はこの質問を教育目的でのみ行っています。
strcpy()
を使用する脆弱なバイナリを利用して、リターン指向のプログラミングを使用していくつかの関数呼び出しを連鎖させようとしています。これらの関数呼び出しの1つは、system()
への呼び出しでなければなりません(シェルコマンドを実行するため)。残念ながら、system()
のアドレスにはNULL
バイトが含まれているため、このバイトが確認されるとstrcpy()
がペイロードのコピーを停止します。
したがって私の質問は、この問題を解決するための最良のアプローチは何ですか?
Libcでsystem()
に類似した関数を確認しましたが、何も見つかりませんでした。私の別のアイデアは、fork()
、exec()
、およびwait()
を後で呼び出すことです。ただし、これによりペイロードの複雑さが増します。
シェルコードの実行時に元のプロセスを残しておく必要がある理由はありますか?直接execve
を呼び出すだけで(スタックを十分に制御できる場合)、または そのヘルパー関数の1つ を呼び出すと、現在のプロセスがターゲットプロセスになります。
うまくいくかもしれないよりトリッキーなアプローチは、dlsym
を使用してsystem
へのポインターを取得することです。これは、ターゲットコマンドで呼び出すことができます。ただし、mightは最初にdlopen
を呼び出す必要があります。 dlsym
のセマンティクスはわかりません。対応するWindows関数GetProcAddress
は、ロードされたモジュール(ライブラリーまたは実行可能ファイル)のベースアドレスを最初のポインターとして使用します。dlsymでも同じことができます。 ROPを使用しているため、おそらくASLRに悩まされることはなく、アドレスは予測可能です。
最後に、ROPを使用しているため、目的のアドレスを算術的に生成できる1つ以上のガジェットを見つけることができます。特定の値を生成するために使用できるオペランド(エクスプロイト時の既知の値を持つシェルコード、レジスターまたはアドレスの定数など)と操作(加算、減算、またはxorなど)の多くの組み合わせがあります。 1つを含まない部分からのNULLバイトが含まれ、ALU演算が短いため、適切なガジェットを見つけるのは難しくありません。