/GS (Sprawdzanie zabezpieczeń bufora)

Wykrywa niektóre przepełnienia buforów, które zastępują adres zwrotny funkcji, adres aparatu obsługi wyjątków lub niektóre typy parametrów. Przepełnianie buforu to technika używana przez hakerów do wykorzystywania luk w kodzie, który nie wymusza ograniczeń rozmiaru buforu.

Składnia

/GS[-]

Uwagi

/GS jest domyślnie włączony. Jeśli spodziewasz się, że aplikacja nie ma zagrożenia bezpieczeństwa, użyj / GS-. Aby uzyskać więcej informacji na temat pomijania wykrywania przepełniania buforu, zobacz safebuffers.

Sprawdzanie zabezpieczeń

W funkcjach, które kompilator uznaje za zagrożone problemem przepełnienia buforu, przydziela miejsce w stosie przed adresem zwrotnym. Podczas wprowadzania funkcji przydzielone miejsce jest ładowane z plikiem cookie zabezpieczeń obliczanym raz przy ładowaniu modułu. Podczas zamykania funkcji oraz podczas usuwania ramek ze stosu (unwinding) w 64-bitowych systemach operacyjnych następuje wywołanie funkcji pomocnika, która sprawdza, czy wartość pliku cookie jest wciąż taka sama. Inna wartość wskazuje, że mogło dojść do zastąpienia stosu. Wykrycie innej wartości powoduje przerwanie procesu.

Bufory GS

Sprawdzanie zabezpieczeń przepełnień buforu jest wykonywane na buforze GS. Buforem GS może być jeden z następujących obiektów:

  • Tablica, która jest większa niż 4 bajty, ma więcej niż dwa elementy oraz zawiera element typu innego niż wskaźnik.

  • Struktura danych, która ma więcej niż 8 bajtów i nie zawiera żadnych wskaźników.

  • Bufor przydzielony przy użyciu funkcji _alloca .

  • Dowolna klasa lub struktura zawierająca bufor GS.

Na przykład poniższe instrukcje deklarują bufory GS.

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

Natomiast następujące instrukcje nie deklarują buforów GS. Dwie pierwsze deklaracje zawierają elementy będące wskaźnikami. Instrukcje trzecia i czwarta deklarują tablice, które są za małe. Piąta instrukcja deklaruje strukturę, której rozmiar na platformie x86 jest nie większy niż 8 bajtów.

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

Opcja /GS kompilatora wymaga zainicjowania pliku cookie zabezpieczeń przed uruchomieniem dowolnej funkcji używającej pliku cookie. Plik cookie zabezpieczeń musi być inicjowany natychmiast po wpisie do pliku EXE lub DLL. Jest to wykonywane automatycznie, jeśli używasz domyślnych punktów wejścia VCRuntime: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup lub _DllMainCRTStartup. Jeśli używasz alternatywnego punktu wejścia, musisz ręcznie zainicjować plik cookie zabezpieczeń, wywołując __security_init_cookie.

Co obejmuje ochrona

Opcja /GS kompilatora chroni następujące elementy:

  • Adres zwrotny wywołania funkcji.

  • Adres aparatu obsługi wyjątków funkcji.

  • Zagrożone parametry funkcji.

Na wszystkich platformach /GS próbuje wykryć przepełnienie buforu do adresu zwrotnego. Przepełnienia buforów łatwiej wykonać na platformach takich jak x86 i x64, ponieważ używają one konwencji wywoływania, które przechowują adresy zwrotne wywołań funkcji w stosach.

Jeśli na platformie x86 funkcja używa aparatu obsługi wyjątków, kompilator wprowadza plik cookie zabezpieczeń chroniący adres tego aparatu. Plik cookie jest sprawdzany w trakcie usuwania ramek ze stosu.

/GS chroni wrażliwe parametry , które są przekazywane do funkcji. Do takich parametrów zalicza się wskaźniki, odwołania do składni języka C++, struktury języka C (typu C++ POD) zawierające wskaźniki oraz bufory GS.

Parametr zagrożony jest przydzielany przed plikiem cookie i lokalnymi zmiennymi. Przepełnienie buforu może spowodować zastąpienie tych parametrów. Wtedy kod w funkcji wykorzystującej te parametry może doprowadzić do ataku, zanim funkcja zwróci wartość i zostanie wykonane sprawdzanie zabezpieczeń. Aby ograniczyć to zagrożenie, kompilator tworzy kopię zagrożonych parametrów w trakcie prologu funkcji i umieszcza je w obszarze pamięci masowej wykorzystywanym przez bufory.

Kompilator nie tworzy kopii zagrożonych parametrów w następujących sytuacjach:

  • Funkcje, które nie zawierają buforu GS.

  • Optymalizacje (/opcje) nie są włączone.

  • Funkcje o zmiennej liczbie argumentów (...).

  • Funkcje oznaczone nagim.

  • Funkcje, które w pierwszej instrukcji zawierają wbudowany kod zestawu.

  • Parametr jest wykorzystywany tylko na sposoby stanowiące mniejsze zagrożenie w razie przepełnienia buforu.

Czego nie obejmuje ochrona

Opcja /GS kompilatora nie chroni przed wszystkimi atakami bezpieczeństwa przepełniania buforu. Jeśli na przykład istnieje bufor oraz tabela wirtualna w obiekcie, przepełnienie buforu może spowodować uszkodzenie tabeli.

Nawet jeśli używasz /GS, zawsze spróbuj napisać bezpieczny kod, który nie ma przepełnień buforu.

Aby ustawić tę opcję kompilatora w programie Visual Studio

  1. Otwórz okno dialogowe Strony właściwości projektu. Aby uzyskać szczegółowe informacje, zobacz Set C++ compiler and build properties in Visual Studio (Ustawianie właściwości kompilatora języka C++ i kompilowania w programie Visual Studio).

  2. Wybierz stronę właściwości Właściwości>konfiguracji C/C++>Code Generation.

  3. Zmodyfikuj właściwość Sprawdzanie zabezpieczeń buforu.

Aby programowo ustawić tę opcję kompilatora

Przykład

W tym przykładzie nastąpi przepełnienie buforu. Spowoduje to błąd aplikacji podczas wykonywania.

// 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);
}

Zobacz też

Opcje kompilatora MSVC
Składnia wiersza polecenia kompilatora MSVC