Sdílet prostřednictvím


/GS (kontrola zabezpečení vyrovnávací paměti)

Rozpozná některá přetečení vyrovnávací paměti, která přepisují návratovou adresu funkce, adresu obslužné rutiny výjimky nebo určité typy parametrů.Přetékání vyrovnávací paměti je technika používána hackery ke zneužití kódu, který nevynucuje omezení velikosti vyrovnávací paměti.

/GS[-]

Poznámky

Ve výchozím nastavení je možnost /GS zapnuta.Očekáváte-li od aplikace, že nebude mít žádná bezpečnostní rizika, použijte možnost /GS-.Další informace o možnosti /GS naleznete v tématu Bezpečnostní kontroly kompilátoru do hloubky.Další informace o potlačení detekce přetečení vyrovnávací paměti naleznete v tématu safebuffers.

Kontroly zabezpečení

Pro funkce, které kompilátor rozpozná jako předmět problémů přetečení vyrovnávací paměti, přidělí kompilátor místo v zásobníku před návratovou adresou.Při vstupu do funkce je do přiděleného místa načtena zabezpečovací informace cookie, která je vypočtena jednou při načtení modulu.Při ukončení funkce a během rozbalování rámce na 64bitových operačních systémech je zavolána pomocná funkce, která zjišťuje, zda se hodnota informace cookie nezměnila.Jiná hodnota naznačuje, že mohlo dojít k přepsání zásobníku.Je-li zjištěna jiná hodnota, je proces ukončen.

Vyrovnávací paměti GS

Bezpečnostní kontrola přetečení vyrovnávací paměti je prováděna ve vyrovnávací paměti GS.Vyrovnávací paměť GS může být jedno z následujících:

  • Pole, které je větší než 4 bajty, má více než dva prvky a má typ prvků, který není typem ukazatele.

  • Datová struktura, jejíž velikost je více než 8 bajtů a která neobsahuje žádné ukazatele.

  • Vyrovnávací paměť přidělaná pomocí funkce _alloca.

  • Libovolná třída nebo struktura obsahující vyrovnávací paměť GS.

Následující příkazy jsou příkladem deklarace vyrovnávacích pamětí GS.

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

Následující příkazy však vyrovnávací paměti GS nedeklarují.První dvě deklarace obsahují prvky typu ukazatel.Třetí a čtvrtý příkaz deklarují příliš malé pole.Pátý příkaz deklaruje strukturu, jejíž velikost na platformě x86 není více než 8 bajtů.

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

Možnost kompilátoru /GS vyžaduje, aby před spuštěním jakékoli funkce používající bezpečnostní informaci cookie byla tato informace inicializována.Bezpečnostní informace cookie musí být inicializována při vstupu do souboru EXE nebo DLL.To je prováděno automaticky, jsou-li použity výchozí vstupní body CRT (mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup nebo _DllMainCRTStartup).Používáte-li alternativní vstupní bod, je zapotřebí bezpečnostní informaci cookie inicializovat ručně zavoláním funkce __security_init_cookie.

Chráněné položky

Možnost kompilátoru /GS chrání následující položky:

  • Návratová adresa volání funkce.

  • Adresa obslužné rutiny výjimky pro funkci.

  • Ohrožené parametry funkce.

Na všech platformách se možnost /GS pokusí rozpoznat přetečení zásobníku na návratovou adresu.Přetečení vyrovnávací paměti lze snadněji zneužít na platformách jako x86 a x64, které využívají konvence volání ukládající návratovou adresu volání funkce do zásobníku.

Pokud na platformě x86 funkce používá obslužnou rutinu výjimky, kompilátor pro ochranu adresu rutiny zavede bezpečnostní informaci cookie.Informace cookie je kontrolována během odvíjení rámce.

Možnost /GS chrání ohrožené parametry předávané funkci.Ohroženým parametrem je ukazatel, odkaz C++, struktura jazyka C (typ C++ POD) obsahující ukazatel či vyrovnávací paměť GS.

Ohrožený parametr je přidělen před informací cookie nebo místními proměnnými.Přetečení vyrovnávací paměti může tyto parametry přepsat.Kód ve funkci, která tyto parametry používá, by mohl způsobit útok dříve, než funkce vrátí hodnotu a je provedena bezpečnostní kontrola.Aby bylo nebezpečí minimalizováno, kompilátor během prologu funkce vytváří kopii ohrožených parametrů a vkládá je pod oblast úložiště pro jakoukoli vyrovnávací paměť.

Kompilátor kopie ohrožených parametrů nevytváří v následujících situacích:

  • Funkce, které neobsahují vyrovnávací paměť GS.

  • Nejsou povoleny optimalizace (možnosti /O).

  • Funkce s proměnlivým seznamem argumentů (...).

  • Funkce označené příznakem naked.

  • Funkce obsahující jako první příkaz vložený kód sestavení.

  • Parametr je používán pouze způsobem, jehož zneužití je v případě přetečení vyrovnávací paměti méně pravděpodobné.

Nechráněné položky

Možnost kompilátoru /GS nechrání před všemi bezpečnostními útoky založenými na přetečení vyrovnávací paměti.Obsahuje-li například objekt vyrovnávací paměť a tabulku vtable, přetečení vyrovnávací paměti by mohlo tabulku vtable poškodit.

I při použití možnosti /GS se vždy snažte psát bezpečný kód, v němž nedochází k přetečení vyrovnávací paměti.

Chcete-li nastavit tuto možnost kompilátoru v aplikaci Visual Studio

  1. V Průzkumníku řešení klikněte pravým tlačítkem myši na projekt a potom klikněte na Vlastnosti.

    Další informace naleznete v tématu Postupy: Otevření stránek vlastností projektu.

  2. V dialogovém okně Stránky vlastností klikněte na složku C/C++.

  3. Klikněte na stránku vlastností Generování kódu.

  4. Upravte vlastnost Bezpečnostní kontrola vyrovnávací paměti.

Chcete-li tuto možnost kompilátoru nastavit v programu

Příklad

V této ukázce dojde k přetečení vyrovnávací paměti.Díky tomu dojde za běhu aplikace k chybě.

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

Viz také

Referenční dokumentace

Možnosti kompilátoru

Nastavení možností kompilátoru