web-dev-qa-db-ja.com

スタックとヒープが実行不可能な場合、コードはどのように実行できますか?

私はバッファオーバーフローについての本を読みました、そしてそれは対処する次のことを提案します:

スタック(およびヒープ)を実行不可能にすることで、既存のプログラムに対する多くの種類のバッファオーバーフロー攻撃に対する高度な保護が提供されます。

しかし、どうすればそれができるのかわかりません-ヒープ上またはスタック上でない場合、実行がどこで行われるのでしょうか?

24
Adam Sh

私があなたの質問を正しく理解していれば、他のどの答えもそれに対処していません。答えは、実行はスタックでもヒープでもないコードセクションで行われるということです。一般的なページメモリシステムでは、プログラムファイル(Windowsの.exeなど)のコードは、実行可能であるが読み取り専用のページに読み込まれます。追加の書き込み可能(および実行可能)ページは、スタックとヒープのプロセスに割り当てられます。ここでの提案は、オペレーティングシステムとハードウェアが協力して、これらのページを書き込み可能であるが実行可能ではないことをマークする必要があるということです(rgnglの回答はWindowsでそれを行う方法を説明しています)。

実行不可能なヒープとスタックがある場合でも、Alexey Frunzeの回答に記載されているリターン指向プログラミングを使用するエクスプロイトは可能ですが、スタックスマッシング保護やアドレス空間配置のランダム化など、それらを妨害する保護手法があります。 http://en.wikipedia.org/wiki/Return-to-libc_attack#Protection_from_return-to-libc_attacks

27
Jim Balter

「リターン指向プログラミング」(別名ROP)タイプのエクスプロイトと呼ばれるものがあります。

攻撃者は、悪用されているプログラムのさまざまな部分から自分の邪悪なコードを作成する方法を見つけます。

彼は、戻り命令バイトの前に、値を場所に移動したり、値を追加したり、値を比較したりするなど、レジスタまたはメモリに対して有用な操作を実行できる使用可能なバイトシーケンス(命令)を見つけます。これらは、エクスプロイトが取得するマイクロサブルーチンです。で構築されています。

次に、コードのバグを悪用することにより、攻撃者はプログラムに、すべての邪悪な作業を行うマイクロサブルーチンのチェーンの実行を開始させます。

つまり、良いコードは悪いコードに変わります。スタックまたはヒープでは何も実行されません。

命令が複数のバイトにまたがり、可変長であるCPUでは、命令の一部である即時命令オペランド(IOW、数値定数)でさえコードになる可能性があるため、使用可能なバイトシーケンスを見つける可能性が高いことも注目に値します。 「より単純な」CPUで。

また、メモリ保護を変更する悪意のあるコードを作成することも可能であり、エクスプロイトは既存のアプリケーションのコードによる制約を受けなくなります。

10
Alexey Frunze

非常に具体的な例:戻りアドレスがsystemを指すように配置し、スタックの次のスロット(またはレジスタ通過アーチの最初の引数レジスタ)が文字列"/bin/sh"へのポインタになるように配置します。

この種の保護はOSによって提供され、アプリケーション層では実行できません。

ウィキペディアの記事を参照してください。この記事では、Windowsで有効にする方法も説明しています。 http://en.wikipedia.org/wiki/Data_Execution_Prevention

1
rgngl

コードは、スタックやヒープ(どちらもデータストレージ用)ではなく、テキストセグメントで実行されます。したがって、組織は次のとおりです。

<highest addresses>
stack
...
heap
data section (initialized data & bss - uninitialized data) 
code section (text)
<lowest addresses> 

コードセクションは実行可能ですが、不変です。このウィキペディアの記事には詳細があります: https://en.wikipedia.org/wiki/Data_segment

1
Scott C Wilson

実行可能セグメントである他の場所にジャンプして、邪悪なコードを実行することができます...

結局のところ、任意のストレージ、メモリ上のすべてのデータはビットであり、ビットは実行するCPUへの命令にすることができます。

0
0x90

オーバーフローを使用して、関数の戻りアドレスを上書きできます。これにより、コードが記述された既知のアドレスにジャンプできます。しかし、その後、アドレスコードをランダム化することで応答したOSライターは...

0
argentage