|
| 1 | +--- |
| 2 | +title: "/guard:ehcont (Enable EH Continuation Metadata)" |
| 3 | +ms.date: "03/30/2020" |
| 4 | +f1_keywords: ["/guard:ehcont", "VC.Project.VCCLCompilerTool.GuardEHContMetadata"] |
| 5 | +--- |
| 6 | +# /guard:ehcont (Enable EH Continuation metadata) |
| 7 | + |
| 8 | +Enables generation of EH Continuation metadata by the compiler. |
| 9 | + |
| 10 | +## Syntax |
| 11 | + |
| 12 | +``` |
| 13 | +/guard:ehcont[-] |
| 14 | +``` |
| 15 | + |
| 16 | +## Remarks |
| 17 | + |
| 18 | +The **/guard:ehcont** option enables compiler to generate a sorted list of the relative virtual addresses(RVA) of all the valid exception handling continuation targets for a binary, used during runtime for NtContinue/SetThreadContext RIP validation. By default, **/guard:ehcont** is off and must be explicitly enabled. To explicitly disable this option, use **/guard:ehcont-**. |
| 19 | + |
| 20 | +[Control-flow Enforcement Technology(CET)](https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf) is a hardware-based security feature that eliminates Return-Oriented Programming(ROP) based attacks, by maintaining a "Shadow Stack" for every call stack to enforce control flow integrity. |
| 21 | + |
| 22 | +Once shadow stacks are available to prevent ROP attacks, one of the next exploit techniques that attackers may use is corrupting the RIP value inside the CONTEXT structure passed into system calls that redirect the execution of a thread, such as NtContinue, RtlRestoreContext and SetThreadContext. The CONTEXT structure is stored in memory, and corrupting the RIP value in it can cause these syscalls to transfer execution to the attacker-controlled RIP. Currently, NTContinue can be called with any continuation point. Therefore, it's essential to perform RIP validation when shadow stacks are enabled. |
| 23 | + |
| 24 | +RtlRestoreContext/NtContinue is used during SEH exception unwinding to unwind to the target frame for executing the except block. Since the RIP of the except block is not expected to be on the shadow stack (which would result in the RIP validation failing), **/guard:ehcont** compiler switch will generate an "EH Continuation Table" that contains a sorted list of the RVAs of all valid exception handling continuation targets in the binary. NtContinue first checks the shadow stack for the user-supplied RIP, and if the RIP is not found there, it will proceed to check the EH Continuation Table from the RIP's containing binary. If the containing binary was not compiled with the table, then NtContinue will be allowed to proceed, for compatibility with legacy binaries. It is important to distinguish between a binary that does not contain EHCONT data (legacy binary), and a binary that contains EHCONT data but the table has zero entries. The former allows all addresses inside the binary as valid continuation targets, whereas the latter does not allow any address inside the binary as a valid continuation target. |
| 25 | +Starting **Visual Studio 2019 version 16.7 and later**, this feature will be supported for 64-bit processes on a 64-bit OS. |
| 26 | + |
| 27 | +The **/guard:ehcont** option must be passed to both the compiler and linker to generate EH coninuation target RVAs for a binary. If your binary is built by using a single `cl` command, the compiler passes the option to the linker. Compiler also passes [/guard:cf](guard-enable-control-flow-guard.md) option to the linker. If you compile and link separately, the option must be set on both the compiler and linker commands. |
| 28 | + |
| 29 | +Code compiled by using **/guard:ehcont** can be linked to libraries and object files that are not compiled by using the option. When the library/object file is not compiled for /guard:ehcont, the linker will fatal if any of these scenarios are true: |
| 30 | + |
| 31 | +1. A code section has "local unwind" ([try-finally Statement](../../cpp/try-finally-statement.md) under Abnormal Termination section) |
| 32 | +1. An EH (xdata) section contains pointers to code section and they aren't for structured exception handling (SEH) |
| 33 | +1. The pointers are for SEH but the object file was not compiled with comdats (/Gy) |
| 34 | + |
| 35 | +The linker will fatal, because it cannot generate metadata in these scenarios, which means throwing an exception will likely crash at runtime. |
| 36 | + |
| 37 | +For SEH section info that is in comdats but not compiled with /guard:ehcont, the linker will emit a warning, but will generate correct but conservative metadata for the section. To ignore warnings, open project's **property pages->Configuration Properties->Linker->Advanced-> Ignore Warning LNK4291(EHCont metadata)** |
| 38 | + |
| 39 | + |
| 40 | +To check if a binary contains EHCONT data, look for the following when dumping the binary's load config: |
| 41 | + |
| 42 | +``` |
| 43 | +e:\>link /dump /loadconfig CETTest.exe |
| 44 | +... |
| 45 | + 10417500 Guard Flags |
| 46 | +... |
| 47 | + EH Continuation table present // EHCONT guard flag present |
| 48 | +... |
| 49 | + 0000000180018640 Guard EH continuation table |
| 50 | + 37 Guard EH continuation count // May be 0 if no exception handling is used in the binary. Still counts has having EHCONT data. |
| 51 | +... |
| 52 | + Guard EH Continuation Table // List of RVAs |
| 53 | +
|
| 54 | + Address |
| 55 | + -------- |
| 56 | + 0000000180002CF5 |
| 57 | + 0000000180002F03 |
| 58 | + 0000000180002F0A |
| 59 | +... |
| 60 | +``` |
| 61 | + |
| 62 | +### To set this compiler option in the Visual Studio development environment |
| 63 | + |
| 64 | +1. Open the project's **Property Pages** dialog box. For details, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md). |
| 65 | + |
| 66 | +1. Select **Configuration Properties**, **C/C++**, **Code Generation**. |
| 67 | + |
| 68 | +1. Select the **Enable EH Continuation Metadata** property. |
| 69 | + |
| 70 | +1. In the dropdown control, choose **Yes(/guard:ehcont)** to enable EH continuation metadata, or **No(/guard:ehcont-)** to disable it. |
| 71 | + |
| 72 | +## See also |
| 73 | + |
| 74 | +[/guard (Enable Control Flow Guard)](guard-enable-control-flow-guard.md)<br/> |
| 75 | +[MSVC Compiler Options](compiler-options.md)<br/> |
| 76 | +[MSVC Compiler Command-Line Syntax](compiler-command-line-syntax.md) |
0 commit comments