Partilhar via


Controle de Flow Guard para segurança da plataforma

O que é o Control Flow Guard?

O Control Flow Guard (CFG) é um recurso de segurança de plataforma altamente otimizado que foi criado para combater vulnerabilidades de corrupção de memória. Ao colocar restrições rígidas sobre de onde um aplicativo pode executar código, torna muito mais difícil para os exploits executar código arbitrário por meio de vulnerabilidades, como estouros de buffer. O CFG estende as tecnologias de mitigação de exploração anteriores, como /GS (Buffer Security Check), de Prevenção de Execução de Dados (DEP) e ASLR (Address Space Layout Randomization).

Usar o CFG pode ajudar a:

  • Previna a corrupção de memória e ataques de ransomware.
  • Restrinja os recursos do servidor apenas ao que é necessário em um determinado momento para reduzir a superfície de ataque.
  • Torne mais difícil explorar código arbitrário por meio de vulnerabilidades, como estouros de buffer.

Esse recurso está disponível no Microsoft Visual Studio e é executado em versões CFG-Aware do Windows; Windows 10 e Windows 11 no cliente e Windows Server 2019 e posterior no servidor.

Os desenvolvedores são fortemente encorajados a habilitar o CFG para seus aplicativos. Você não precisa habilitar o CFG para cada parte do seu código, pois código com e sem CFG habilitado será executado corretamente. No entanto, não habilitar o CFG para todos os códigos pode abrir lacunas na proteção. Além disso, o código habilitado para CFG funciona bem em versões CFG-Unaware do Windows e, portanto, é totalmente compatível com elas.

Como posso habilitar o CFG?

Na maioria dos casos, não há necessidade de alterar o código-fonte. Tudo o que você precisa fazer é adicionar uma opção ao seu projeto do Visual Studio, e o compilador e o vinculador habilitarão o CFG.

O método mais simples é navegar até Project | Propriedades | Propriedades de configuração | C/C++ | Geração de código e escolha Sim (/guard:cf) para Control Flow Guard.

Uma captura de tela da propriedade Control Flow Guard na configuração de compilação de geração de código do Visual Studio.

Como alternativa, adicione /guard:cf ao Project | Propriedades | Propriedades de configuração | C/C++ | Linha de comando | Opções adicionais (para o compilador) e /guard:cf para Project | Propriedades | Propriedades de configuração | Vinculador | Linha de comando | Opções adicionais (para o vinculador).

Uma captura de tela da configuração de compilação de Opções Adicionais da Linha de Comando C/C++ no Visual Studio com a propriedade definida como /guard:cf

Uma captura de ecrã da configuração de compilação de Opções Adicionais da Linha de Comando do Linker no Visual Studio com a propriedade definida como /guard:cf

Consulte /guard (Enable Control Flow Guard) para obter informações adicionais.

Se você estiver criando seu projeto a partir da linha de comando, poderá adicionar as mesmas opções. Por exemplo, se estiveres a compilar um projeto chamado test.cpp, utiliza cl /guard:cf test.cpp /link /guard:cf.

Você também tem a opção de controlar dinamicamente o conjunto de endereços de destino icall que são considerados válidos pelo CFG usando o SetProcessValidCallTargets da API de Gerenciamento de Memória. A mesma API pode ser usada para especificar se as páginas são alvos inválidos ou válidos para CFG. As funções VirtualProtect e VirtualAlloc tratarão por padrão uma região especificada de páginas executáveis e confirmadas como destinos de chamada indiretos válidos. É possível substituir esse comportamento, como ao implementar um compilador Just-in-Time, especificando PAGE_TARGETS_INVALID ao chamar VirtualAlloc ou PAGE_TARGETS_NO_UPDATE ao chamar VirtualProtect conforme detalhado em Constantes de proteção de memória.

Como faço para saber se um binário está sob controle Flow Guard?

Execute o da ferramenta dumpbin (incluído na instalação do Visual Studio) no prompt de comando do Visual Studio com o /headers e /loadconfig opções: dumpbin /headers /loadconfig test.exe. A saída para um binário em CFG deve mostrar que os valores de cabeçalho incluem "Guard" e que os valores de configuração de carga incluem "CF Instrumented" e "FID table present".

Uma captura de tela da saída gerada pelo comando dumpbin /headers

Uma captura de tela da saída do dumpbin /loadconfig

Como o CFG realmente funciona?

As vulnerabilidades de software são frequentemente exploradas fornecendo dados improváveis, incomuns ou extremos a um programa em execução. Por exemplo, um atacante pode explorar uma vulnerabilidade de estouro de buffer ao fornecer mais dados de entrada a um programa do que o esperado, excedendo assim a área reservada pelo programa para armazenar uma resposta. Isso pode corromper a memória adjacente que possivelmente contém um ponteiro de função. Quando o programa chama através desta função, ele pode então saltar para um local não intencional especificado pelo invasor.

No entanto, uma combinação potente de suporte de compilação e tempo de execução do CFG implementa a integridade do fluxo de controle que restringe fortemente onde as instruções de chamada indireta podem ser executadas.

O compilador faz o seguinte:

  1. Adiciona verificações de segurança leves ao código compilado.
  2. Identifica o conjunto de funções no aplicativo que são alvos válidos para chamadas indiretas.

O suporte de tempo de execução, fornecido pelo kernel do Windows:

  1. Mantém eficientemente o estado que identifica alvos de chamada indireta válidos.
  2. Implementa a lógica que verifica se um destino de chamada indireta é válido.

Para ilustrar:

Um diagrama ilustrando as verificações CFG inseridas pelo compilador.

Quando uma verificação CFG falha em tempo de execução, o Windows encerra imediatamente o programa, interrompendo assim qualquer exploração que tente chamar indiretamente um endereço inválido.

/guard (Ativar protetor de fluxo de controle)

/GUARD (Ativar verificações de guarda)