スタックスマッシングが問題の放棄された(コアダンプされた)原因を検出しました



Stack Smashing Detected Abandoned Cause Problem



GCCの「スタックスマッシングが検出されました」メカニズム
C / C ++言語を使用してソフトウェアを開発するプログラムでは、「スタックオーバーフロー」の問題が発生したと思います。 「スタックオーバーフロー」の問題は通常非常に隠されており、問題を再現するのが非常に難しい場合があります。ソフトウェアに不可解な問題があるときはいつでも、スタックオーバーフローの疑いが常にありますが、問題のトラブルシューティングは非常に難しいため、「スタックオーバーフロー」は大多数のC / C ++開発者にとって悪夢です。 「スタックオーバーフロー」の問題を回避または検出する一般的な方法があるかどうかを尋ねるしかありませんか?実際、「スタックオーバーフロー」の問題を回避する方法はありません。経験豊富なプログラムでさえ、「スタックオーバーフロー」の罠に陥る可能性があります。 「スタックオーバーフロー」のために、多くの有名なソフトウェアシステムについて誰もが聞いたことがあると思います。さまざまな種類のセキュリティ問題。 「スタックオーバーフロー」の可能性を減らすために、コードを書くときは通常、スタックバッファに関するさまざまな操作APIに精通しているスタック上のバ​​ッファの使用に注意を払います(文字列操作関数が最も頻繁に使用されます) )それを使用する正しい方法。しかし、人々が常に間違いを犯す場合、「スタックオーバーフロー」を検出するメカニズムはありますか?今日私が言っているのは、gccコンパイラがスタック保護のためのさまざまなメカニズムを提供しているということです。
まず、より明白なスタックオーバーフローコードセグメントを見てみましょう。このコードのコンパイルプラットフォームは次のとおりです。Ubuntu14.04Gccバージョンは4.8.4です。コードの内容は次のとおりです。

#include
#include



int main(void)
{{
char array [5] = {0}

strcpy(array, 'stackoverflow') return 0

}
このコードは、最初に配列サイズ5のchar配列を定義します。次に、strcpy関数を使用して、文字列 'stackvoerflow'を配列バッファーにコピーします。明らかに、配列バッファはオーバーフローします。 strcpyの使い方については後で紹介します。



次に、コンパイルして実行すると、結果は次のようになります。

root @ xxxxx:〜/ Technical Summary / linux / gcc $ ./buscore
***スタックスマッシングが検出されました***:./ buscoreが終了しました
放棄されました(コアダンプ)
プログラムがクラッシュしたことがわかります。いくつかのヒントがあります。

***スタックスマッシングが検出されました***:./ buscoreが終了しました
このメッセージは、gccが提供するスタックオーバーフロー保護メカニズムが、プログラムにバッファオーバーフローがあることを検出したときに出力するメッセージです。 gccが提供するスタックオーバーフロー保護メカニズムとは何ですか?



gccのマニュアルを見ると、レポートメカニズムがgccの-fstack-protectorシリーズのオプションにバッファオーバーフロー検出メカニズムを提供していることがわかります。以下は、メカニズムの原理の概要です。

-fstack-protectorを有効にすると、実行中のプログラムがバッファオーバーフロー(バッファオーバーフロー攻撃など)を検出するとすぐに終了し、バッファのオーバーフローを検出するように求められます。このメカニズムは、攻撃に対して脆弱な関数のターゲットコンテキストに保護変数を追加することによって実現されます。これらの関数には、allcoa関数と8バイトを超えるバッファーサイズの関数の使用が含まれます(これはここではあまり明確ではありません。上記の例のバッファーサイズ5もこのメカニズムをトリガーします)。これらの保護された変数は、関数に入るときに初期化され、関数が出るときに検出されます。一部の変数が検出に失敗した場合、エラーメッセージが出力され、現在のプロセスが終了します。

注:このメカニズムは、テスト中にバッファーのサイズが8バイト未満の場合にもトリガーされます。関数でアロカ関数を使用した後、バッファはオーバーフローしますが、メカニズムはトリガーされません。理由がわかりませんか?

char *stack_ptr = alloca(0) char *str = 'hello, world' strcpy(stack_ptr, str) printf('stack_ptr = %s ', stack_ptr) The above code does not trigger this mechanism?

質問が来ています、-fstack-protectorは本当に全能ですか?それは本当にすべてのスタックオーバーフローの問題を検出できますか?次の例でテストできます。

#include
#include
#include

typedef struct
{{
char str [2]
} overlay_t
int main(void)
{{
char * str = '中国へようこそ'

overflow_t v printf('sizoef(v) = %d ', sizeof(v)) memcpy(&v, str, strlen(str)) printf('v.str = %s ', v.str)

}
gcc buscore.c -o buscore、次の結果をコンパイルして実行します。
sizoef(v)= 2
v.str =中国へようこそ
プログラムが正常に実行され、スタックオーバーフローの検出をトリガーしなかったことがわかりましたか?どうしてこれなの? gccマニュアルをさらに検討すると、-fstack-protector-allオプションも提供されていることがわかります。これは次のように解釈されます。

その機能は-fstack-protectorに似ていますが、すべての機能に対してスタックオーバーフロー検出を実行します。プログラムを再コンパイルし、-fstack-protector-allオプションを追加して、次のように結果を実行します。

sizoef(v)= 2
v.str =中国へようこそ

  • スタックスマッシングが検出されました*:./ buscoreが終了しました
    放棄されました(コアがダンプされました)。プロセスがスタックオーバーフローを正常に検出したことがわかります。

したがって、ソフトウェアを開発するときは、-fstack-protector-allオプションを追加するのが最善です。これにより、スタックオーバーフローの問題の大部分が検出されます。

同時に、スタックオーバーフローが原因でプロセスがクラッシュすると、コアダンプファイルが生成されることにも注意してください。コアダンプの構成については、を参照してください。
Androidシステムはこの記事をコアダンプします。
コアダンプファイルに基づいて問題をどのように特定しますか?上記で-fstack-protectorメカニズムの原理を紹介すると、関数の終了時に検出されると言われているため、コアダンプ内の関数スタック情報からスタックオーバーフローの関数を特定できるため、問題の範囲は大幅に縮小されます。問題を調べて、スタックオーバーフローが発生している場所を特定する関数に焦点を当てることができます。

stackoverflowに関連する紹介もあります。

http://stackoverflow.com/questions/1345670/stack-smashing-detected

http://stackoverflow.com/questions/10712972/what-is-the-use-of-fno-stack-protector

サードパーティのライブラリの場合、***スタックスマッシングが検出された***エラーを回避するために、-fno-stack-protectorオプションをお勧めします