Partilhar via


/GS (Verificação de Segurança de Buffer)

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

Sintaxe

/GS[-]

Observações

/GS está ativado por padrão. Se você espera que seu aplicativo não tenha exposição à segurança, use /GS-. Para obter mais informações sobre como suprimir a deteção de saturação de buffer, consulte safebuffers.

Verificações de segurança

Em 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 pode ter ocorrido uma substituição da pilha. Se um valor diferente for detetado, o processo será encerrado.

GS Buffers

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, tem mais de dois elementos e tem um tipo de elemento que não é um tipo de ponteiro.
  • Uma estrutura de dados cujo tamanho é superior a 8 bytes e 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 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 de compilador /GS requer 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 após a entrada em um EXE ou DLL. Isso é feito automaticamente se você usar os pontos de entrada padrão VCRuntime: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup, ou _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 de 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, /GS tenta detetar 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.

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ções. O cookie é verificado durante o desenrolamento do quadro.

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

Um parâmetro vulnerável é alocado antes do cookie e das variáveis locais. Uma 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 prolog da função e os coloca abaixo da área de armazenamento para quaisquer buffers.

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 que são menos prováveis de serem exploráveis no caso de uma saturação de buffer.

O que não está protegido

A opção de 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 um vtable em um objeto, uma saturação de buffer pode corromper o vtable.

Mesmo se você usar /GS, sempre tente escrever código seguro que não tenha saturações de buffer.

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

  1. Abra a caixa de diálogo Property Pages do projeto. Para obter detalhes, consulte Definir compilador C++ e criar propriedades no Visual Studio.
  2. Selecione a página de propriedades Configuration Properties>C/C++>Code Generation página de propriedades.
  3. Modifique a propriedade Verificação de Segurança do Buffer .

Para definir essa opção do compilador programaticamente

Exemplo

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

Ver também

de opções do compilador MSVC
Compilador MSVC Command-Line de sintaxe