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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

9257閲覧

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

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/05/14 06:12

編集2017/05/14 08:58
#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 の値は書き換わらないのですが・・・・・・・・
どういうことでしょうか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naomi3

2017/05/14 06:51

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

2017/05/14 06:55

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

回答4

0

ベストアンサー

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

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

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

C

1int f() { 2 int x[4]; 3 4 int index = 0; 5 for (int i = 0; i < 10; i++) { 6 x[index++] = 0; 7 } 8 return 0; 9} 10 11int main(int argc, char* argv[]){ 12 f(); 13}

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

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

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

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

-fno-stack-protector

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

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

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

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

投稿2017/05/14 08:22

編集2017/05/14 10:22
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/14 08:35

「そもそもC言語で普通にコンパイルしても特にセキュリティー機能はないと考えてもよいと思いますよ。」左様でございますか! 分かりました。 スタックオーバーフローとバッファオーバーフローは別物なのですね! わかりました。
strike1217

2017/05/14 08:41

-fno-stack-protector 破壊の検出ということは、ただのチェック用のオプションですか??
KSwordOfHaste

2017/05/14 08:43

> ただのチェック用のオプションですか?? と、思います。チェック用の仕組みを「無効にする」オプションですね。
strike1217

2017/05/14 08:44

なんだ~~ ずーーーーっと スタックをガードしてくれている物が存在して、それを無効にしてくれる物かと思っていました。 スタックガードなんて物は存在しないんですね!
KSwordOfHaste

2017/05/14 09:02

スタックをガードするような仕組みをCに入れてしまうとそれは計算効率上大変高価なものにつくので、C言語のプログラマーとして許容しがたいものになると思います。そういう機構が必要なら最早Cで作ることを選択できないと言えましょう。Cの超高速実行が全然いかせなくなってしまいます。
strike1217

2017/05/14 09:04

なるほど・・・・ セキュリティは難しいですね・・・・ ちょっと追記してみました。
KSwordOfHaste

2017/05/14 09:21

ですから-fstack-protectorはそういうものの一種なわけです。 上のアドレスは自分の回答にあるページをごらんになったのですよね?同じページです。
strike1217

2017/05/14 09:29

あ、すいません。同じページでしたね。
strike1217

2017/05/14 09:29

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

2017/05/14 09:37

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

2017/05/14 09:54

そうですね。 算術に関しては再度質問いたします。 とりあえず、問題は解決しましたので、解決済みにしますね。
guest

0

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

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

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

C

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

投稿2017/05/14 07:34

編集2017/05/14 07:45
naomi3

総合スコア1105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/14 08:11

スタックオーバーフローは、スタック領域内が満杯になって、他の領域に漏れ出してしまう ということでしょうか?
guest

0

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

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

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

投稿2017/05/14 08:47

toutou

総合スコア2050

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/14 08:49

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

2017/05/14 09:18

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

0

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

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

./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

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

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

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

投稿2017/05/14 08:10

編集2017/05/14 08:15
strike1217

総合スコア651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/14 08:19

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

2017/05/14 08: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;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問