/GS (バッファーのセキュリティ チェック)/GS (Buffer Security Check)

関数のリターン アドレス、例外ハンドラーのアドレス、または特定の型のパラメーターを上書きするバッファー オーバーランを検出します。Detects some buffer overruns that overwrite a function's return address, exception handler address, or certain types of parameters. ハッカーは、バッファー オーバーランを発生させるという方法を使用して、バッファー サイズ制限を強制しないコードを攻撃します。Causing a buffer overrun is a technique used by hackers to exploit code that does not enforce buffer size restrictions.

構文Syntax

/GS[-]

RemarksRemarks

/GSが既定でオンです。/GS is on by default. アプリケーションにセキュリティを損なうがない場合を使用して、 /GS- します。If you expect your application to have no security exposure, use /GS-. バッファー オーバーランの検出を抑制する詳細については、次を参照してください。 safebuffersします。For more information about suppressing buffer overrun detection, see safebuffers.

セキュリティ チェックSecurity Checks

バッファー オーバーランの問題を起こしやすいとコンパイラが判断した関数には、スタックのリターン アドレスの前に記憶領域が割り当てられます。On functions that the compiler recognizes as subject to buffer overrun problems, the compiler allocates space on the stack before the return address. 関数のエントリを割り当てられた領域が読み込まれて、セキュリティ クッキーモジュールの読み込み時に 1 回計算するがします。On function entry, the allocated space is loaded with a security cookie that is computed once at module load. 関数の実行の終了時に、および 64 ビット オペレーティング システムでのフレームのアンワインド時に、ヘルパー関数が呼び出されてクッキーの値が変更されていないかどうかが確認されます。On function exit, and during frame unwinding on 64-bit operating systems, a helper function is called to make sure that the value of the cookie is still the same. 異なる値は、スタックの上書きが発生した可能性があることを示します。A different value indicates that an overwrite of the stack may have occurred. 異なる値が検出された場合、プロセスは終了します。If a different value is detected, the process is terminated.

GS バッファーGS Buffers

バッファー オーバーラン セキュリティ チェックが実行される、 GS バッファーします。A buffer overrun security check is performed on a GS buffer. GS バッファーは、次のいずれかを使用できます。A GS buffer can be one of these:

  • 4 バイトを超える配列で、3 つ以上の要素を持ち、要素型がポインター型ではない配列。An array that is larger than 4 bytes, has more than two elements, and has an element type that is not a pointer type.

  • サイズが 8 バイトを超え、ポインターを含まないデータ構造体。A data structure whose size is more than 8 bytes and contains no pointers.

  • 使用して割り当てられたバッファー、 _alloca関数。A buffer allocated by using the _alloca function.

  • GS バッファーを含むクラスまたは構造体。Any class or structure that contains a GS buffer.

たとえば、次のステートメントで GS バッファーを宣言します。For example, the following statements declare GS buffers.

char buffer[20];
int buffer[20];
struct { int a; int b; int c; int d; } myStruct;
struct { int a; char buf[20]; };

ただし、次のステートメントでは GS バッファーは宣言されません。However, the following statements do not declare GS buffers. 最初の 2 つの宣言には、ポインター型の要素が含まれます。The first two declarations contain elements of pointer type. 3 番目と 4 番目のステートメントでは、サイズが非常に小さい配列を宣言しています。The third and fourth statements declare arrays whose size is too small. 5 番目のステートメントでは、x86 プラットフォームでサイズが 8 バイトを超えない構造体を宣言しています。The fifth statement declares a structure whose size on an x86 platform is not more than 8 bytes.

char *pBuf[20];
void *pv[20];
char buf[4];
int buf[2];
struct { int a; int b; };

/GSコンパイラ オプションは、cookie を使用する任意の関数の実行前に、セキュリティ クッキーが初期化されることが必要です。The /GS compiler option requires that the security cookie be initialized before any function that uses the cookie is run. セキュリティ クッキーは、EXE または DLL にエントリをすぐに初期化する必要があります。The security cookie must be initialized immediately on entry to an EXE or DLL. 既定の VCRuntime エントリ ポイントを使用する場合に自動的にこれは、: mainCRTStartup、wmainCRTStartup、WinMainCRTStartup、wWinMainCRTStartup、または _DllMainCRTStartup します。This is done automatically if you use the default VCRuntime entry points: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup, or _DllMainCRTStartup. 呼び出して、セキュリティ クッキーを手動で初期化する必要があります、別のエントリ ポイントを使用する場合 __security_init_cookie です。If you use an alternate entry point, you must manually initialize the security cookie by calling __security_init_cookie.

保護される対象What Is Protected

/GSコンパイラ オプションは、次の項目を保護します。The /GS compiler option protects the following items:

  • 関数呼び出しの戻りアドレス。The return address of a function call.

  • 関数の例外ハンドラーのアドレス。The address of an exception handler for a function.

  • Vulnerable 関数パラメーター。Vulnerable function parameters.

すべてのプラットフォームで /GSリターン アドレスへのバッファー オーバーランの検出を試みます。On all platforms, /GS attempts to detect buffer overruns into the return address. バッファー オーバーランは、関数呼び出しのリターン アドレスをスタックに格納する呼び出し規則を使用する、x86、x64 などのプラットフォームでの方が簡単に攻撃されます。Buffer overruns are more easily exploited on platforms such as x86 and x64, which use calling conventions that store the return address of a function call on the stack.

x86 で、関数が例外ハンドラーを使用する場合、コンパイラはセキュリティ クッキーを挿入して、例外ハンドラーのアドレスを保護します。On x86, if a function uses an exception handler, the compiler injects a security cookie to protect the address of the exception handler. このクッキーは、フレームのアンワインド時にチェックされます。The cookie is checked during frame unwinding.

/GS保護脆弱なパラメーター関数に渡すことです。/GS protects vulnerable parameters that are passed into a function. 脆弱なパラメーターとは、ポインター、C++ 参照、内部にポインターを含む C 構造体 (C++ POD 型)、または GS バッファーです。A vulnerable parameter is a pointer, a C++ reference, a C-structure (C++ POD type) that contains a pointer, or a GS buffer.

脆弱なパラメーターは、クッキーおよびローカル変数より前に割り当てられます。A vulnerable parameter is allocated before the cookie and local variables. バッファー オーバーランによって、これらのパラメーターが上書きされることがあります。A buffer overrun can overwrite these parameters. また、これらのパラメーターを使用する関数のコードでは、関数から制御が戻る前、およびセキュリティ チェックが実行される前に、攻撃を受ける可能性があります。And code in the function that uses these parameters could cause an attack before the function returns and the security check is performed. この危険を最小化するために、コンパイラは、関数プロローグで、脆弱なパラメーターのコピーを作成し、任意のバッファーのストレージ領域の下に配置します。To minimize this danger, the compiler makes a copy of the vulnerable parameters during the function prolog and puts them below the storage area for any buffers.

コンパイラは、次の場合は脆弱なパラメーターのコピーを作成しません。The compiler does not make copies of vulnerable parameters in the following situations:

  • GS バッファーを含まない関数の場合。Functions that do not contain a GS buffer.

  • 最適化 (/O オプション) 有効ではありません。Optimizations (/O options) are not enabled.

  • 可変個引数リスト (...) を持つ関数の場合。Functions that have a variable argument list (...).

  • マークされている関数nakedします。Functions that are marked with naked.

  • 最初のステートメントにインライン アセンブラー コードを含む関数の場合。Functions that contain inline assembly code in the first statement.

  • パラメーターが、バッファー オーバーランが発生したときに攻撃される可能性が低い方法でのみ使用されている場合。A parameter is used only in ways that are less likely to be exploitable in the event of a buffer overrun.

保護されない対象What Is Not Protected

/GSコンパイラ オプションはすべてのバッファー オーバーラン セキュリティ攻撃から保護されません。The /GS compiler option does not protect against all buffer overrun security attacks. たとえば、バッファーと vtable が同じオブジェクトにある場合、バッファー オーバーランによって vtable が破損する可能性があります。For example, if you have a buffer and a vtable in an object, a buffer overrun could corrupt the vtable.

使用する場合でも /GS、常にバッファー オーバーランがない、セキュリティで保護されたコードを記述してください。Even if you use /GS, always try to write secure code that has no buffer overruns.

このコンパイラ オプションを Visual Studio で使用するにはTo set this compiler option in Visual Studio

  1. ソリューション エクスプ ローラープロジェクトを右クリックし、クリックしてプロパティします。In Solution Explorer, right-click the project and then click Properties.

    詳細については、次を参照してください。 Visual Studio での設定の C++ コンパイラとビルド プロパティします。For more information, see Set C++ compiler and build properties in Visual Studio.

  2. プロパティ ページダイアログ ボックスで、をクリックして、 C/C++ フォルダー。In the Property Pages dialog box, click the C/C++ folder.

  3. をクリックして、コード生成プロパティ ページ。Click the Code Generation property page.

  4. 変更、バッファー セキュリティ チェックプロパティ。Modify the Buffer Security Check property.

このコンパイラ オプションをコードから設定するにはTo set this compiler option programmatically

Example

この例では、バッファー オーバーランが発生します。This sample overruns a buffer. このため、実行時にアプリケーションで障害が発生します。This causes the application to fail at runtime.

// compile with: /c /W1
#include <cstring>
#include <stdlib.h>
#pragma warning(disable : 4996)   // for strcpy use

// Vulnerable function
void vulnerable(const char *str) {
   char buffer[10];
   strcpy(buffer, str); // overrun buffer !!!

   // use a secure CRT function to help prevent buffer overruns
   // truncate string to fit a 10 byte buffer
   // strncpy_s(buffer, _countof(buffer), str, _TRUNCATE);
}

int main() {
   // declare buffer that is bigger than expected
   char large_buffer[] = "This string is longer than 10 characters!!";
   vulnerable(large_buffer);
}

関連項目See also

MSVC コンパイラ オプションMSVC Compiler Options
MSVC コンパイラ コマンドラインの構文MSVC Compiler Command-Line Syntax