質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.90%

意図的にスタックオーバーフローを起こす

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,433

strike1217

score 583

   #include<stdio.h>
   #include<string.h>
   #include<stdlib.h>

   int main(int argc, char* argv[]){
           int i = 0;
           int x[4] = {0}
           char text[32] = {0};

          strcpy(text, argv[1]);

          for(i = 0; i < 6; i++) //☆
                  x[i] = i;
          printf("x[0] = %d, x[3] = %d, i = %d\n", x[0], x[3], i);
          return 0;
  }


-fno-stack-protectorでスタックプロテクタを無効にしました。

segmentation faultです。
なぜでしょうか??

☆マークがついているところが脆弱性です。

スタックオーバーフローを起こして int i = 0; の値を書き換えたいです。
他になんのセキュリティ機能で保護されているのでしょうか??

linux 64bit gccです。

[追記]
ちなみに、strcpy()にも脆弱性が入っているので、

./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
これもsegmentation faultでした。

[追記2]

算術オーバーフローも別の変数に値が入ってしまうことはあるのでしょうか?

int i = 0;
int gh = 0;
int ff = 0;

int型のmaxの値を超える値を入れます。
warningが出てきます。
warning: overflow in implicit constant conversion

gh = 7483294672645692748739827964726579478927927424252526; ← 算術オーバーフローですよね??

int i と int ff の値は書き換わらないのですが・・・・・・・・
どういうことでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • naomi3

    2017/05/14 15:51

    スタックオーバーフローではなく、バッファオーバーフローでは?strike1217さんのコードではスタックオーバーフローにはなりません。

    キャンセル

  • strike1217

    2017/05/14 15:55

    スタックオーバーフローとバッファオーバーフローとは何が違うんでしょうか??

    キャンセル

回答 4

checkベストアンサー

+2

-fstack-protectorの効果はこのページに書かれています。

つまり、「スタックを破壊したことで関数の戻り値アドレスが書き換わってしまったことを検出して、不当なアドレスへリターンせずにプログラムを異常終了させる」のが目的です。なおスタックを破壊することと「スタックオーバーフロー」は別の話です。スタックオーバーフローとは「関数の呼び出しの入れ子が深くなりすぎて実行スタックが足りなくなる」ことです。

このオプションを有効にした際にうれしいのは次のようなプログラムコードを実行した場合です。

int f() {
  int x[4];

  int index = 0;
  for (int i = 0; i < 10; i++) {
    x[index++] = 0;
  }
  return 0;
}

int main(int argc, char* argv[]){
  f();
}

上記をgcc -fstack-protector-allでコンパイルして実行すると、f()からリターンする際にエラーが検出され以下のようなメッセージとともにプログラムが異常終了してくれます。

*** stack smashing detected ***: ./a.out terminated

最初に挙げたページに書かれているように、この動作はスタックフレーム上の関数のリターンアドレス付近に「値が破壊されていることを検出するためのカナリア」と呼ばれるデータを配置し、リターン時にこのカナリアが破壊されていないことをチェックして破壊されていたら異常終了するという手法で実現されているようです。

つまりこのオプションは「スタックを破壊されること自体を防ぐものではなく」「破壊されている状態で不当アドレスへ分岐することだけを防ぐ」ものです。それをもって「バッファーオーバーランを利用して不当なコードを実行する」ようなセキュリティー上の脅威に対抗するものといえるのでしょう。

-fno-stack-protector

を指定すると、上記のカナリア破壊検出が生成されなくなるだけです。

他になんのセキュリティ機能で保護されているのでしょうか??

そもそもC言語で普通にコンパイルしても特にセキュリティー機能はないと考えてもよいと思いますよ。プログラマーがそうしようと意図すればメモリーは破壊し放題です。どこがどう破壊されるかによってプログラムは異常終了することもあればデータが不正のまま何食わぬ顔をして正常終了することもあります。

何かを意図的に起こしたいなら「スタック上のローカル変数がどう割り当てられて自分のコードが正確にどこをどういう値に書き換えるのか」を把握してください。ご質問に書かれているようなざっくりした情報ではそれを確認したとはいえないと思います。スタックフレーム上にローカル変数や関数の引数、関数の戻り値などがどう配置されているかまでを厳密に調べると、どう動くかが予測できます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/14 18:29

    算術オーバーフローの場合は、変数型の最大より大きな値を入れると起こるものですよね?

    キャンセル

  • 2017/05/14 18:37

    オーバーフローという言葉は同じですが、普通プログラマーはそれらを同じ問題とは捉えないと思います。バッファーオーバーランはメモリー領域の範囲を超えたアクセスのことを言いますし、算術オーバーフローは演算結果が値域の範囲外となることを指します。プログラミング上は別種の問題であり本件と関係するとは言えません。

    キャンセル

  • 2017/05/14 18:54

    そうですね。
    算術に関しては再度質問いたします。

    とりあえず、問題は解決しましたので、解決済みにしますね。

    キャンセル

+1

スタックオーバーフローとは、オートマチック変数(staticでないローカル変数)、オートマチック配列変数要素の大量確保または関数の度重なる呼び出しなどによる、スタック領域の不足を言います。

バッファオーバーフローとは、バッファオーバーランとも呼び、配列で宣言された範囲外への書き込みによる不正なアクセスを言います。C/C++では配列の範囲外アクセスの自動検出を行いません。言語仕様では、不定すなわち、配列の範囲外アクセスが行われても動作は一切保障されません。実際は、他の変数へのアクセスが発生して誤動作したり、プロセスに対して割り当てられていないメモリ領域へのアクセスが発生してsegmentation fault、すなわちOSによって強制終了させられます。strike1217さんのケースでは、プロセスに対して割り当てられていないメモリ領域へのアクセスが発生したことになります。

スタックオーバーフローの例は、以下のような終わりのない再帰呼び出しで作れます。:

int main(int argc, char* argv[]) {
    main(argc, argv);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/14 17:11

    スタックオーバーフローは、スタック領域内が満杯になって、他の領域に漏れ出してしまう

    ということでしょうか?

    キャンセル

0

できました。
よくからないのですが、再度プログラムを作り直して、

strcpy(text, argv[1]);をfor文の後に置いて、

./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

とやると普通に変数の値が書き換わりました。

何がダメだったのか分からないんですが・・・・
もう少し探求してみます。

./stack_overflow $(for n in {0..32}; echo -n "A"; echo;)
こちらの方が簡易的てわかりやすいです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/14 17:19

    何がダメだったのかまだ分からないのですが、-fno-stack-protector
    なしでも、オーバーフローを起こせました。

    キャンセル

  • 2017/05/14 17:39 編集

    for文の方もできました。

    そもそも同じint i に対してオーバーフローを起こそうとしたのが間違えでした。

    アライメントを考慮しながら、再度やり直しました。

       int i = 0;
    int ff = 0;
    int x[4] = {0};
    char text[32] = {0};

    for(i = 0; i < 7; i++) //☆
    x[i] = i;

    キャンセル

0

スタックオーバーフローとバッファオーバーフローの違いを簡単に調べただけのにわかの意見なんだけど、スタックオーバーフローは、10個の箱が用意してあって幻の11個目の箱に荷物を入れようとして起こるもの。バッファオーバーフローは、10個の箱にまんぱんに詰め、同じ10個の箱にさらに荷物をつめようとして起こるもの。このように判断しました。wikiにはスタックオーバーフローはバッファオーバーフローの一種だって書いてありますね。

スタックってなあに?(2) | 学校では教えてくれないこと | [技術コラム集]組込みの門 | ユークエスト株式会社

バッファオーバーランとは - IT用語辞典 Weblio辞書

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/14 17:49

    スタックオーバーフローはバッファオーバーフローの一種
    そうですか!
    分かりました。

    キャンセル

  • 2017/05/14 18:18

    んー、本質的に「正常な領域を超えてメモリーへアクセスすること」という意味ではバッファーオーバーランの一種ですが、wikiでいうバッファーオーバーランの一種という説明でのバッファーとは実行スタック全体のことを指していると思います。ゆえに、単一の関数内にある配列アクセスに対するオーバーランのことをスタックオーバーフローとは呼びません。naomi3さんがこの2つを違うものとして回答しているのはそういう意味だと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.90%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る