Dela via


/GS (buffertsäkerhetskontroll)

Identifierar vissa buffertöverskridanden som skriver över en funktions returadress, undantagshanteraradress eller vissa typer av parametrar. Att orsaka en buffertöverskridning är en teknik som används av hackare för att utnyttja kod som inte tillämpar begränsningar för buffertstorlek.

Syntax

/GS[-]

Anmärkningar

/GS är aktiverat som standard. Om du förväntar dig att ditt program inte har någon säkerhetsexponering använder du /GS-. Mer information om hur du utelämnar buffertöverskridningsidentifiering finns i safebuffers.

Säkerhetskontroller

På funktioner som kompilatorn identifierar som föremål för buffertöverkörningsproblem allokerar kompilatorn utrymme på stacken före returadressen. Vid funktionsposten läses det allokerade utrymmet in med en säkerhetscookie som beräknas en gång vid modulbelastning. Vid funktionsavslut och under bildruteavspolning på 64-bitars operativsystem anropas en hjälpfunktion för att se till att cookiens värde fortfarande är detsamma. Ett annat värde anger att en överskrivning av stacken kan ha inträffat. Om ett annat värde identifieras avslutas processen.

GS-buffertar

En buffertöverskriden säkerhetskontroll utförs på en GS-buffert. En GS-buffert kan vara något av följande:

  • En matris som är större än 4 byte, har fler än två element och har en elementtyp som inte är en pekartyp.
  • En datastruktur vars storlek är mer än 8 byte och som inte innehåller några pekare.
  • En buffert som allokeras med hjälp _alloca av funktionen.
  • Alla klasser eller strukturer som innehåller en GS-buffert.

Följande instruktioner deklarerar till exempel GS-buffertar.

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

Följande instruktioner deklarerar dock inte GS-buffertar. De två första deklarationerna innehåller element av pekartyp. Den tredje och fjärde instruktionen deklarerar matriser vars storlek är för liten. Den femte instruktionen deklarerar en struktur vars storlek på en x86-plattform inte är mer än 8 byte.

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

Alternativet /GS-kompilator kräver att säkerhetscookie initieras innan någon funktion som använder cookien körs. Säkerhetscookien måste initieras omedelbart vid inmatning till en EXE- eller DLL-fil. Detta görs automatiskt om du använder standardinmatningspunkterna för VCRuntime: mainCRTStartup, , wmainCRTStartupWinMainCRTStartup, wWinMainCRTStartupeller _DllMainCRTStartup. Om du använder en alternativ startpunkt måste du initiera säkerhetscookien manuellt genom att anropa __security_init_cookie.

Vad är skyddat

Alternativet /GS-kompilator skyddar följande objekt:

  • Returadressen för ett funktionsanrop.
  • Adressen till en undantagshanterare för en funktion.
  • Sårbara funktionsparametrar.

På alla plattformar försöker /GS identifiera buffertöverskridanden i returadressen. Buffertöverskridanden utnyttjas enklare på plattformar som x86 och x64, som använder anropskonventioner som lagrar returadressen för ett funktionsanrop i stacken.

Om en funktion använder en undantagshanterare på x86 matar kompilatorn in en säkerhetscookie för att skydda adressen till undantagshanteraren. Cookien kontrolleras under avspolning av ram.

/GS skyddar sårbara parametrar som skickas till en funktion. En sårbar parameter är en pekare, en C++-referens, en C-struktur (C++ POD-typ) som innehåller en pekare eller en GS-buffert.

En sårbar parameter allokeras före cookien och lokala variabler. En buffertöverskridning kan skriva över dessa parametrar. Och kod i funktionen som använder dessa parametrar kan orsaka en attack innan funktionen returneras och säkerhetskontrollen utförs. För att minimera den här faran gör kompilatorn en kopia av de sårbara parametrarna under funktionsprologen och placerar dem under lagringsområdet för eventuella buffertar.

Kompilatorn gör inte kopior av sårbara parametrar i följande situationer:

  • Funktioner som inte innehåller en GS-buffert.
  • Optimeringar (/O alternativ) är inte aktiverade.
  • Funktioner som har en variabelargumentlista (...).
  • Funktioner som är markerade med naken.
  • Funktioner som innehåller infogad sammansättningskod i den första instruktionen.
  • En parameter används endast på sätt som är mindre benägna att utnyttjas i händelse av en buffertöverskridning.

Vad är inte skyddat

Alternativet /GS-kompilator skyddar inte mot alla buffertöverskridningssäkerhetsattacker. Om du till exempel har en buffert och en vtable i ett objekt kan en buffertöverskridning skada den virtuella tabellen.

Även om du använder /GS kan du alltid försöka skriva säker kod som inte har några buffertöverskridanden.

Ange det här kompilatoralternativet i Visual Studio

  1. Öppna dialogrutan egenskapssidor för projektet. Mer information finns i Ange C++-kompilator- och byggegenskaper i Visual Studio.
  2. Välj egenskapssidan Konfigurationsegenskaper>C/C++>Kodgenerering.
  3. Ändra egenskapen Buffertsäkerhetskontroll .

Så här ställer du in det här kompilatoralternativet programmatiskt

Exempel

Det här exemplet överskrider en buffert. Detta gör att programmet misslyckas vid körning.

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

Se även

MSVC-kompilatoralternativ
MSVC-kompilator Command-Line syntax