
sprintfを用いたフォーマット文字列攻撃に関する質問です。
main文の中で
---------------------
int main(void){
char str[50];
sprintf(str,"%s");
puts(str);
}
---------------------
を実行すると(null)で帰ってきます。
しかし関数呼び出しを行うと結果が変わってきます。
---------------------
void f(){
char str[50];
sprintf(str,"%s");
puts(str);
}
int main(void){
f();
}
---------------------
これを実行すると" ・L "のような文字化けしたものに変わりました。
sprintf(str,"%s%s");と記述することによって" ・L (null) "と、本来呼び出される箇所のものが格納されています。
なぜ関数呼び出しにすると変なところを参照してしまうのか(第3引数があると勘違いしてしまうのか)教えてください。
また、これによりどのような悪影響があるのか教えてください。
自分はプログラマが意図しない箇所を参照するため攻撃者のプログラムアドレスを格納してしまう恐れがあると考えています。
No.1ベストアンサー
- 回答日時:
>なぜ関数呼び出しにすると変なところを参照してしまうのか(第3引数があると勘違いしてしまうのか)教えてください。
勘違いなどしていません。
sprintfのフォーマット指定"%s"で第3引数があり、それは文字列へのポインタと書いてあります。
同様にsprintfのフォーマット指定"%s%s"は第3引数,第4引数があり、それは文字列へのポインタということになります。
C,C++で可変長引数はどのようにして実装するのか調べてみてください。
>自分はプログラマが意図しない箇所を参照するため攻撃者のプログラムアドレスを格納してしまう恐れがあると考えています。
フォーマットをユーザーに入力させたりするなら、その可能性はあります。
ですが通常そのようなケースはないのではないでしょうか。
この回答への補足
回答ありがとうございます。
char str[50];
sprintf(str,"%s");
puts(str);
上記のプログラムをmain文内で実行したところ、第3引数の%sは(null)になったのに、関数に記述すると第3引数に文字化けしたものが入るのか理由がわかりません。
同じ処理の流れだと思うのですが、なぜ%sに格納される内容が変わるのか教えていただけないでしょうか。
>フォーマットをユーザーに入力させたりするなら、その可能性はあります。
>ですが通常そのようなケースはないのではないでしょうか。
確かにそうですね。
これは現実的ではないですよね。
ありがとうございます。
No.6
- 回答日時:
関数呼出しだから内容が変わったわけではありません。
strには何も書き込まれていないので、
コンパイルされた時点でchar str[50]で確保されたメモリに存在したデータが見えているだけしょう。
sprintf( str, "%s" );では、strに何も書き込まれていません。
sprintf( str, "%s", "ABC" ); とか
sprintf( str, "%s%s", "ABC", "XYZ");
とすることでstrにABCやABCXYZの文字列が書き込まれます。
No.5
- 回答日時:
>同じ処理の流れだと思うのですが、なぜ%sに格納される内容が変わるのか教えていただけないでしょうか。
未定義動作だしたまたまそうなっただけです。
前にも書きましたけど可変長引数の関数をどうやってつくるのか調べてみてください。
No.4
- 回答日時:
この質問は、残念ながら”コンパイラの実装依存”であるため、誰も回答できません。
まず、int sprintf(char *str, const char *format, ...) は、
format に渡されたフォーマット文字列から、可変個の引数を読みに行こうとします。
ですので、
sprintf(str, "%s"); と書けば引数を2つしか渡さなくても3番目の引数の値を読みに行き、
sprintf(str, "%s%s"); なら3番目と4番目の引数を読みに行くわけです。
(質問に”第3引数があると勘違いしてしまうのか”とありますが、そうではなく、
sprintf(str, "%s") は、必ず第3引数を読みにいくと考えてください。)
この渡されなかった”3番目の引数がどのように読みだされるのか?”
について、一般的なことは、誰にも回答できません。
大抵は、コンパイラや sprintf(str, "%s"); の前にあるコード群と
そのコードの実行結果によって、様々に変わってしまうと思います。
ですので、質問にあるどちらの結果も”たまたまそうなった”に過ぎず、
・少しコードを変えたら結果も変わった。
・コンパイルオプションを変更したら結果が変わった。
・他のコンパイラでコンパイルしたら結果が変わった。
だとしても、全く不思議ではないです。
もし、あなたがアセンブラを読めるなら、どのように引数が渡され、sprintf 側で
どのように読みこまれたか調査することは可能でしょう。
でも、それもあなたが使用したコンパイラがたまたまそのように実装していたという
話に過ぎません。
No.2
- 回答日時:
#1にもありますが「可変長引数 C言語 実装」で検索するとか、上級者向けの参考書を読むとかして、どんなカラクリになっているか、調べてください。
結果が違うのは「たまたま」です。
例えば、次のものは、また違った結果になるのではないでしょうか。
#include <stdio.h>
int main(void){
char *a= "A";
char str[50];
char *b= "B";
sprintf(str,"%s");
puts(str);
return 0;
}
また、どのコンパイラを使っているかわかりませんが、Release/Debugビルド、最適化オプション等でも変わる可能性があります
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- Visual Basic(VBA) VBA ユーザーフォームからSubプロージャ―に値を引き渡す方法 3 2023/04/09 01:54
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
C++ で、「)」が必要 というエ...
-
C言語のワーニングメッセージの...
-
プリコンパイラとは?
-
wavファイルの波形データについて
-
コンパイルできない
-
QBasicをWindowsXPで使いたい!
-
「.c」拡張子でC++文法を使...
-
C++でアボート(Abort)で処理が...
-
コンパイラについて
-
Delphiの逆コンパイル
-
COBOLのEVALUATE文について
-
__extension__
-
IF文の先のCONTINUEの意味(...
-
変数(関数)名の頭に_
-
C言語での変数宣言の場所
-
Eclipseの環境設定について
-
あるプログラムのコマンドライ...
-
VBAで仕様書は書きますか?
-
EXCELなどで「返す」という表現
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
C++ で、「)」が必要 というエ...
-
C++でアボート(Abort)で処理が...
-
io.hをincludeするとそのような...
-
コンパイラについて
-
コンパイルできない
-
Delphiの逆コンパイル
-
Eclipseの環境設定について
-
変数(関数)名の頭に_
-
関数の戻り値による変数の初期化
-
Visual C++とVisual C++.NETの違い
-
初心者はIDE使わないほうが良く...
-
fortranでのNaNについて
-
コンパイラフラグ(compiler fla...
-
sprintfを用いたフォーマット文...
-
C言語のワーニングメッセージの...
-
非商用のインテルコンパイラ
-
不要なインクルードファイルの検出
-
ccコマンドの使い方
-
ABAQUS ユーザーサブルーチン...
おすすめ情報