2010-11-26 10 views
3
{ 
char bufBef[32]; 
char buf[8]; 
char bufAfter[32]; 
sprintf(buf,"AAAAAAA\0"); 
buf[8]='\0'; 
printf("%s\n",buf); 
} 

Windows 7では、Visual Studio 2008でデバッグプロジェクトとしてプログラムをコンパイルしました。 3つのバッファが隣接している。私は以下のように、デバッガを使用してそれらのアドレスを見つける:ランタイムはバッファオーバーフローをどのように検出しますか?

bufBef   0x001afa50 

buf     0x001afa40 

bufAfter   0x001afa18 

声明 "BUF [8] = '\ 0' が" BUFのうちのアドレスを書き込みます。私がプログラムを実行すると、オペレーションシステムは「デバッグエラー:ランタイムチェック失敗#2 - 変数 'buf'の周りのスタックが壊れていた」と報告しました。

その後、リリースプロジェクトとしてコンパイルしました。静かに実行され、エラー報告は発生しません。

私の質問は、どのようにランタイムバッファオーバーフローを検出ですか?

+0

恐ろしい書式設定(やや) – abelenky

+0

ありがとうございました! – remainn

+3

正確な重複(同じユーザー):[実行時にバッファオーバーフローが検出される方法](http://stackoverflow.com/questions/4282628/how-run-time-detects-buffer-overflow)またおそらく[sprintf関数のバッファオーバーフロー?](http://stackoverflow.com/questions/4282281/sprintf-functions-buffer-overflow)も参照してください。 –

答えて

3

/RTCsの効果が見える場合は何を参照してください。

John Robbinsの書籍Debugging Applications for Microsoft .NET and Microsoft Windowsでは、これについて深く説明しています。

関連抜粋:このスイッチはのみ最適化されていないビルド(デバッグビルド)で動作することを

Fortunately for us, Microsoft extended the /RTCs switch to also do overrun and underrun checking of all multibyte local variables such as arrays. It does this by adding four bytes to the front and end of those arrays and checking them at the end of the function to ensure those extra bytes are still set to 0xCC.

注意。

+0

はい、これは "返信先の前"になります。関連する領域は 'buf'と' bufBef'の間です。 –

+0

@Matthew、fixed。 –

0

Cでは、バッファをオーバーランさせることを明示的に許可します。

実行時(リリースビルド時)にバッファオーバーフローを検出する簡単で簡単な方法はありません。

+2

「明示的に許可」していません。それは未定義の行動だと言います。 C99§6.5.3.2/ 4。 –

+0

「自分の責任で」はそれをカバーしています。それが未定義の動作であるという事実はあなたがそれをすることを許されていることを意味します。関連するリスクを受け入れるだけです。 – abelenky

+0

の標準は反対です。 "移植不可能な**または**間違った**プログラム構造か、**間違った**データの"未定義の動作が起こる(§3.4.3)。プログラムがこれを行うかもしれないと明示的に(スペルアウト)言い表せてください。 –

2

Electric Fenceに関するWikipediaの記事では、バッファオーバーランがどのようにキャッチされるのか、そしてそのようなメカニズムをプロダクションコードで使用しない理由について説明しています。

3

一般に、あなたはしません。バッファーを決してオーバーランしないようにするために、適切なチェックを行う防御コードを記述する必要があります。

デバッグランタイムは、このような種類のバグ(およびその他の一般的なメモリ関連のバグ)を見つけるのに役立つ多数のチェックを追加します。これらのチェックは非常に高価なことが多いため、デバッグビルドにのみ含まれているか、デバッガに接続して実行されています。また、すべての可能なエラーを検出することはできないので、絶対に誤りではありません。彼らは単なるデバッグエイドです。

2

通常、実行時間は、変数間に余分なスペースを割り当て、そのスペースを既知のビットパターンで満たすことによって、オーバーフローを検出します。コードが実行されると、そのスペースのビットパターンが表示されます。変数の外にあるので、は同じビットパターンを保持する必要があります。内容が変更された場合は、あなたが持ってはいけない場所に書きました。

2

3つのバッファは、ではなく、隣接です。 bufの開始とbufBef(スタックの次の項目)の開始の差は16バイトですが、bufの長さはわずか8バイトです。

中間の8バイトは、おそらく8バイトの "カナリア"値で埋められています。ランタイムは、あなたのワイルド・ライトによってカナリアが変更されたことを検出すると、あなたが見たエラーを発生させます。

buf[8]への書き込みは、0x001afa48のアドレスbufbufBefの間にあります)。

2

デバッグモードのコンパイラは、操作の範囲チェックを追加します。

1

スタック構造を理解する必要があります。通常、コンパイラは配列の周りにランダムなクッキーを持つ余分なガードバイトを配置します。関数の最後の値が一致しない場合、オーバーフローが発生します。

1

ウェル0x001afa50 - 0x001afa40 = 0x10 = 16および0x001afa40 - 0x001afa18 = 0x28 = 40です。したがって、いくつかの既知のダミーデータを残すために、バッファ間にスペースがあります。関数が終了するまでにそれが変更された場合、バッファの最後を超えていることがわかります。私はちょうど推測している - 彼らは別の方法でそれをやったかもしれないが、それは1つの可能性があるようだ。

0

あなたはいくつかの言語は、「間違った」ある事を行うため、特定のエラー動作を定義する、今までに可能なプログラムの動作を定義C.から別の言語を探しています。一方、Cは "間違った"コードの動作を残しますは定義されていません、つまりプログラマは、決して未定義の動作を引き起こすような方法でその言語を使用しないことを保証します。いくつかの実装は、デバッグ指向であるか、エラーを見つけるのを支援するデバッグモードを持っています。これは、リリース/プロダクションでコードをデプロイする前に修正する必要があります。

関連する問題