Compartilhar via


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

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

Sintaxe

/GS[-]

Comentários

/GS fica ativo por padrão. Se você espera que seu aplicativo não tenha exposição de segurança, use /GS-. Para obter mais informações sobre como suprimir a detecção de saturação de buffer, confira safebuffers.

Verificações de segurança

Nas funções que o compilador reconhece como sujeitas a problemas de saturação de buffer, o compilador aloca espaço na pilha antes do endereço de retorno. Na entrada da função, o espaço alocado é carregado com um cookie de segurança que é calculado uma vez na carga do módulo. Na saída da função e durante o desenrolamento do quadro em sistemas operacionais de 64 bits, uma função auxiliar é chamada para garantir que o valor do cookie ainda seja o mesmo. Um valor diferente indica que uma substituição da pilha possa ter ocorrido. Se um valor diferente for detectado, o processo será encerrado.

Buffers GS

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

  • Uma matriz maior que 4 bytes, com mais de dois elementos e com um tipo de elemento que não é um tipo de ponteiro.
  • Uma estrutura de dados cujo tamanho é maior que 8 bytes e que não contém ponteiros.
  • Um buffer alocado usando a _alloca função.
  • Qualquer classe ou estrutura que contenha um buffer GS.

Por exemplo, as instruções a seguir declaram buffers 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 instruções a seguir não declaram buffers GS. As duas primeiras declarações contêm elementos do tipo de ponteiro. A terceira e quarta instruções declaram matrizes cujo tamanho é muito pequeno. A quinta instrução declara uma estrutura cujo tamanho em uma plataforma x86 não é superior a 8 bytes.

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

A opção do compilador /GS exige que o cookie de segurança seja inicializado antes que qualquer função que use o cookie seja executada. O cookie de segurança deve ser inicializado imediatamente na entrada de um EXE ou DLL. Isso será feito automaticamente se você usar os pontos de entrada padrão do VCRuntime: mainCRTStartup, , wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartupou _DllMainCRTStartup. Se você usar um ponto de entrada alternativo, deverá inicializar manualmente o cookie de segurança chamando __security_init_cookie.

O que é protegido

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

  • O endereço de retorno de uma chamada de função.
  • O endereço de um manipulador de exceção para uma função.
  • Parâmetros de função vulneráveis.

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

No 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 é verificado durante o desenrolamento do quadro.

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

Um parâmetro vulnerável é alocado antes do cookie e das variáveis locais. Um saturação de buffer pode substituir esses parâmetros. E o código na função que usa esses parâmetros pode causar um ataque antes que a função retorne e a verificação de segurança seja executada. Para minimizar esse perigo, o compilador faz uma cópia dos parâmetros vulneráveis durante o prólogo da função e a coloca abaixo da área de armazenamento de qualquer buffer.

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

  • Funções que não contêm um buffer GS.
  • As otimizações (/O opções) não estão habilitadas.
  • Funções que têm uma lista de argumentos variáveis (...).
  • Funções marcadas com naked.
  • Funções que contêm código de assembly embutido na primeira instrução.
  • Um parâmetro é usado apenas de maneiras menos propensas a exploração no caso de uma saturação de buffer.

O que não é protegido

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

Mesmo que você use a /GS, sempre tente escrever um código seguro que não tenha nenhuma saturação de buffer.

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

  1. Abra a caixa de diálogo Páginas de Propriedades do projeto. Para obter detalhes, confira Definir as propriedades de build e do compilador do C++ no Visual Studio.
  2. Selecione a página de propriedades Propriedades da Configuração>C/C++>Geração de Código.
  3. Modifique a propriedade Verificação de Segurança do Buffer.

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

Exemplo

Este exemplo satura um buffer. Isso faz com que o aplicativo falhe no 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);
}

Confira também

Opções do compilador MSVC
Sintaxe da linha de comando do compilador MSVC