/guard:ehcont
(Habilitar metadados de continuação do EH)
Habilita a geração de metadados de Continuação do EH (EHCONT) pelo compilador.
Sintaxe
/guard:ehcont
[-
]
Comentários
A opção /guard:ehcont
faz com que o compilador gere uma lista classificada dos RVAs (endereços virtuais relativos) de todos os destinos de continuação de tratamento de exceção válidos para um binário. Ela é usada durante o runtime para a validação do ponteiro de instrução NtContinue
e SetThreadContext
. Por padrão, /guard:ehcont
está desativado e deve ser habilitado explicitamente. Para desabilitar explicitamente essa opção, use /guard:ehcont-
.
A opção /guard:ehcont
está disponível no Visual Studio 2019 versão 16.7 e posteriores. O recurso tem suporte para processos de 64 bits em um sistema operacional de 64 bits.
A CET (Control-flow Enforcement Technology) é um recurso de segurança baseado em hardware que protege contra ataques baseados em ROP (programação orientada ao retorno). Ele mantém uma "pilha de sombra" para cada pilha de chamadas para impor a integridade do fluxo de controle.
Quando as pilhas de sombra estão disponíveis para evitar ataques ROP, os invasores passam a usar outras técnicas de exploração. Uma técnica que eles podem usar é corromper o valor do ponteiro de instrução dentro da estrutura CONTEXT. Essa estrutura é passada para chamadas do sistema que redirecionam a execução de um thread, como NtContinue
, RtlRestoreContext
e SetThreadContext
. A estrutura CONTEXT
é armazenada na memória. Corromper o ponteiro de instrução que ela contém pode fazer com que as chamadas do sistema transfiram a execução para um endereço controlado pelo invasor. Atualmente, NTContinue
pode ser chamado com qualquer ponto de continuação. É por isso que é essencial validar o ponteiro de instrução quando as pilhas de sombra estão habilitadas.
RtlRestoreContext
e NtContinue
são usados durante o desenrolamento da exceção do SEH (Tratamento de Exceções Estruturado) para desenrolar o quadro alvo que contém o bloco __except
. Não se espera que o ponteiro de instrução do bloco __except
esteja na pilha de sombra, pois ela falharia na validação do ponteiro de instrução. A opção do compilador /guard:ehcont
gera uma "Tabela de Continuação de EH". Ela contém uma lista classificada dos RVAs de todos os destinos de continuação de tratamento de exceção válidos no binário. O NtContinue
primeiro verifica se o ponteiro de instrução fornecido pelo usuário está na pilha de sombra e, se ele não for encontrado lá, continuará verificando na Tabela de Continuação de EH do binário que contém o ponteiro de instrução. Se o binário que o contém não tiver sido compilado com a tabela, então, por questão de compatibilidade com binários herdados, o NtContinue
terá permissão para continuar. É importante distinguir entre binários herdados que não têm dados EHCONT e binários que contêm dados EHCONT, mas sem entradas na tabela. Os primeiros permitem todos os endereços dentro do binário como destinos de continuação válidos. Os últimos não permitem nenhum endereço dentro do binário como destino de continuação válido.
A opção /guard:ehcont
deve ser passada para o compilador e o vinculador para gerar RVAs de destino de continuação de EH para um binário. Se o binário for criado usando um único comandocl
, o compilador passará a opção para o vinculador. O compilador também passa a opção /guard:cf
para o vinculador. Se você compilar e vincular separadamente, essas opções deverão ser definidas nos comandos do compilador e do vinculador.
Você pode vincular o código compilado usando /guard:ehcont
para bibliotecas e arquivos de objeto compilados sem ele. O vinculador retorna um erro fatal em qualquer um desses cenários:
Uma seção do código tem "desenrolamento local". Para obter mais informações, confira Encerramento anormal na Instrução try-finally.
Uma seção EH (xdata) contém ponteiros para uma seção do código e eles não são para o SEH.
Os ponteiros são para o SEH, mas o arquivo de objeto não foi compilado usando a vinculação no nível da função (/Gy) para produzir COMDATs.
O vinculador retorna um erro fatal porque não consegue gerar metadados nesses cenários. Isso significa que gerar uma exceção provavelmente causará uma falha no runtime.
Para informações da seção do SEH encontradas em COMDATs, mas não compiladas usando /guard:ehcont
, o vinculador emite o aviso LNK4291. Nesse caso, o vinculador gera metadados corretos, mas conservadores, para a seção. Para ignorar esse aviso, use /IGNORE (Ignorar avisos específicos).
Se o vinculador não puder gerar metadados, ele emitirá um dos seguintes erros:
LNK2046: module contains _local_unwind but was not compiled with /guard:ehcont
LNK2047: module contains C++ EH or complex EH metadata but was not compiled with /guard:ehcont.
Para verificar se um binário contém dados EHCONT, procure os seguintes elementos ao despejar a configuração da carga do binário:
e:\>link /dump /loadconfig CETTest.exe
...
10417500 Guard Flags
...
EH Continuation table present // EHCONT guard flag present
...
0000000180018640 Guard EH continuation table
37 Guard EH continuation count // May be 0 if no exception handling is used in the binary. Still counts has having EHCONT data.
...
Guard EH Continuation Table // List of RVAs
Address
--------
0000000180002CF5
0000000180002F03
0000000180002F0A
...
Para definir esta opção do compilador no ambiente de desenvolvimento do Visual Studio
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.
Selecione a página de propriedades Propriedades da Configuração>C/C++>Geração de Código.
Selecione a propriedade Habilitar Metadados de Continuação de EH.
No controle suspenso, escolha Sim (/guard:ehcont) para habilitar metadados de continuação de EH ou Não (/guard:ehcont-) para desabilitá-los.
Confira também
/guard (habilitar proteção de fluxo de controle)
Opções do compilador MSVC
Sintaxe da linha de comando do compilador MSVC