Compartilhar via


/GS (verificação de segurança do buffer)

Detecta algumas excesso de buffer que substituem um endereço de retorno de função, um endereço de manipulador de exceção, ou alguns tipos de parâmetros. Fazer um excesso de buffer é uma técnica usada por cabouqueiros para explorar o código que não impõe restrições de tamanho do buffer.

/GS[-]

Comentários

/GS é ativada por padrão. Se você espera que seu aplicativo não há nenhuma possibilidade de segurança, use /GS-. Para obter mais informações sobre como /GS, consulte Verificações de segurança do compilador detalhados. Para obter mais informações sobre como suprimir a detecção de excesso de buffer, consulte safebuffers.

Verificações de segurança

Em funções que o compilador reconhece como o assunto para o buffer vá para problemas, o compilador atribui o espaço na pilha antes do endereço do remetente. Na entrada da função, o espaço alocado é carregado com um cookie de segurança que é calculada uma vez na carga do módulo. Na saída da função, e durante o tableau que desenrola em sistemas operacionais de 64 bits, uma função auxiliar é chamada para ter certeza de que o valor do cookie ainda é o mesmo. Um valor indica que substituir diferente da pilha pode ter ocorrido. Se um valor diferente for detectado, o processo será encerrado.

Buffers de GS

Uma verificação de segurança de excesso de buffer é executado em um buffer de GS. Um buffer de GS pode ser um destes:

  • Uma matriz que é maior que 4 bytes, tem mais de dois elementos, e tem um tipo de elemento que não é um tipo de ponteiro.

  • Uma estrutura de dados cujo tamanho seja mais de 8 bytes e não contém nenhum ponteiro.

  • Um buffer alocado usando a função de _alloca .

  • Alguns classe ou estrutura que contém um buffer de GS.

Por exemplo, as instruções a seguir declaram buffers de GS.

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

No entanto, as seguintes instruções não declaram buffers de GS. As primeiras duas instruções contêm elementos de tipo de ponteiro. A terceira e a quarta instruções declaram as matrizes cujo tamanho for muito pequeno. A quinta instrução a seguir declara uma estrutura cujo tamanho em uma plataforma x86 não seja mais de 8 bytes.

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

A opção do compilador de /GS requer que o cookie de segurança foi inicializada antes de qualquer função que usar o cookie é executada. O cookie de segurança deve ser inicializada na entrada com EXE ou para uma DLL. Isso será feito automaticamente se você usar os pontos de entrada de CRT da opção (mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup, ou _DllMainCRTStartup). Se você usar um ponto de entrada alternativa, você deve inicializar manualmente o cookie de segurança chamando __security_init_cookie.

O que é protegido

A opção do compilador de /GS protege os seguintes itens:

  • O endereço do remetente de uma chamada de função.

  • O endereço de um manipulador de exceção para uma função.

  • Parâmetros vulneráveis da função.

Em todas as plataformas, as tentativas de /GS de detectar que haja excesso de buffer no endereço do remetente. As excesso de buffer são exploradas mais facilmente em plataformas como x86 e x64, que usam as convenções de chamada que armazenam o endereço do remetente de uma chamada de função na pilha.

Em x86, se uma função usa um manipulador de exceção, o compilador injeta um cookie de segurança para proteger o endereço do manipulador de exceção. O cookie é verificada no desenrolamento do quadro.

/GS protege parâmetros vulneráveis que são passados em uma função. Um parâmetro é vulnerável um ponteiro referência, criando c, c estrutura (tipo de VAGEM C++) que contém um ponteiro, ou um buffer de GS.

Um parâmetro é vulnerável atribuído antes do cookie e variáveis locais. Uma excesso de buffer pode substituir esses parâmetros. E o código da função que usa esses parâmetros poderá causar um ataque antes do retornar de função e de verificação de segurança é executado. Para minimizar este perigo, o compilador faz uma cópia dos parâmetros vulneráveis durante o prólogo da função e coloque-as abaixo da área de armazenamento para todos os buffers.

O compilador não faça cópias de parâmetros vulneráveis nas seguintes situações:

  • Funções que não contêm um buffer de GS.

  • As otimizaçõesopções de /O() não são habilitadas.

  • Funções que têm uma lista de argumento de variável (...).

  • Funções que são marcadas com despido.

  • Funções que contém o código do assembly embutido na primeira instrução.

  • Um parâmetro é usado somente em modos que são menos probabilidade de ser exploráveis no caso de uma excesso de buffer.

O que não é seguro

A opção do compilador de /GS não protege contra todos os ataques de segurança de excesso de buffer. Por exemplo, se você tiver um buffer e um vtable em um objeto, uma excesso de buffer pode corromper o vtable.

Mesmo se você usar /GS, tente sempre escrever o código seguro que não tem nenhum buffer passa.

Para definir esta opção do compilador no Visual Studio

  1. Em Gerenciador de Soluções, clique com o botão direito do mouse no projeto e clique em Propriedades.

    Para obter mais informações, consulte Como abrir páginas de propriedade do projeto.

  2. Na caixa de diálogo de Páginas de Propriedades , clique na pasta de C/C++ .

  3. Clique na página de propriedades de Geração de Código .

  4. Modifique a propriedade de Verificação de Segurança de Buffer .

Para definir essa opção do compilador via programação

Exemplo

Este exemplo passa um buffer. Isso faz com que o aplicativo falhar em tempo de execução.

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

Consulte também

Referência

Opções do compilador

Definindo opções do compilador