/guard:ehcont (EH 연속 메타데이터 사용)

컴파일러에서 EHCONT(EH Continuation) 메타데이터를 생성할 수 있도록 합니다.

구문

/guard:ehcont[-]

설명

/guard:ehcont 옵션을 사용하면 컴파일러가 이진 파일에 대한 모든 유효한 예외 처리 연속 대상의 RVA(상대 가상 주소) 정렬된 목록을 생성합니다. 런타임 동안 및 명령 포인터 유효성 검사에 NtContinueSetThreadContext 사용됩니다. 기본적으로 /guard:ehcont 해제되어 있으며 명시적으로 사용하도록 설정해야 합니다. 이 옵션을 명시적으로 사용하지 않도록 설정하려면 .를 사용합니다 /guard:ehcont-.

/guard:ehcont 옵션은 Visual Studio 2019 버전 16.7 이상에서 사용할 수 있습니다. 이 기능은 64비트 OS의 64비트 프로세스에 대해 지원됩니다.

CET(제어 흐름 적용 기술) 는 ROP(반환 지향 프로그래밍) 기반 공격으로부터 보호하는 하드웨어 기반 보안 기능입니다. 기본 제어 흐름 무결성을 적용하기 위해 모든 호출 스택에 대해 "섀도 스택"을 지정합니다.

ROP 공격을 방지하기 위해 섀도 스택을 사용할 수 있는 경우 공격자는 다른 악용 기술을 사용합니다. 사용할 수 있는 한 가지 방법은 CONTEXT 구조 내의 명령 포인터 값을 손상시키는 것입니다. 이 구조체는 스레드 실행을 리디렉션하는 시스템 호출(예: , RtlRestoreContextSetThreadContext)에 NtContinue전달됩니다. 구조체 CONTEXT 는 메모리에 저장됩니다. 포함된 명령 포인터가 손상되면 시스템 호출이 실행을 공격자 제어 주소로 전송할 수 있습니다. 현재 모든 NTContinue 연속 지점을 사용하여 호출할 수 있습니다. 따라서 섀도 스택을 사용할 때 명령 포인터의 유효성을 검사해야 합니다.

RtlRestoreContextNtContinue SEH(구조적 예외 처리) 예외 해제 중에 블록을 포함하는 __except 대상 프레임으로 해제하는 데 사용됩니다. 명령 포인터 유효성 검사에 __except 실패하므로 블록의 명령 포인터가 섀도 스택에 있을 것으로 예상되지 않습니다. 컴파일러 스위치는 /guard:ehcont "EH 연속 테이블"을 생성합니다. 이진 파일에 있는 모든 유효한 예외 처리 연속 대상의 RVA에 대한 정렬된 목록이 포함됩니다. NtContinue먼저 사용자가 제공한 명령 포인터에 대한 섀도 스택을 검사 명령 포인터를 찾을 수 없으면 명령 포인터가 포함된 이진 파일에서 EH Continuation Table을 검사 진행합니다. 포함된 이진 파일이 테이블과 컴파일되지 않은 경우 레거시 이진 NtContinue 파일과의 호환성을 위해 계속 진행할 수 있습니다. EHCONT 데이터가 없는 레거시 이진 파일과 EHCONT 데이터를 포함하지만 테이블 항목이 없는 이진 파일을 구분하는 것이 중요합니다. 전자는 이진 파일 내의 모든 주소를 유효한 연속 대상으로 허용합니다. 후자는 이진 파일 내의 주소를 유효한 연속 대상으로 허용하지 않습니다.

/guard:ehcont 진 파일에 대한 EH 연속 대상 RVA를 생성하려면 이 옵션을 컴파일러와 링커 모두에 전달해야 합니다. 단일 cl 명령을 사용하여 이진 파일이 빌드된 경우 컴파일러는 옵션을 링커에 전달합니다. 또한 컴파일러는 링커에 /guard:cf 옵션을 전달합니다. 별도로 컴파일하고 연결하는 경우 컴파일러 및 링커 명령 모두에서 이러한 옵션을 설정해야 합니다.

컴파일된 코드를 사용하지 않고 컴파일된 /guard:ehcont 라이브러리 및 개체 파일에 연결할 수 있습니다. 링커는 다음 시나리오에서 치명적인 오류를 반환합니다.

  • 코드 섹션에는 "로컬 해제"가 있습니다. 자세한 내용은 try-finally 문에서 비정상적인 종료를 참조하세요.

  • EH(xdata) 섹션에는 코드 섹션에 대한 포인터가 포함되어 있으며 SEH용이 아닙니다.

  • 포인터는 SEH용이지만 COMDAT를 생성하기 위해 함수 수준 연결(/Gy)을 사용하여 개체 파일이 컴파일되지 않았습니다.

링커는 이러한 시나리오에서 메타데이터를 생성할 수 없으므로 심각한 오류를 반환합니다. 즉, 예외를 throw하면 런타임에 충돌이 발생할 수 있습니다.

COMDAT에서 찾을 수 있지만 사용하여 /guard:ehcont컴파일되지 않은 SEH 섹션 정보의 경우 링커는 경고 LNK4291 내보낸다. 이 경우 링커는 섹션에 대해 정확하지만 보수적인 메타데이터를 생성합니다. 이 경고를 무시하려면 /IGNORE(특정 경고 무시)를 사용합니다.

링커가 메타데이터를 생성할 수 없는 경우 다음 오류 중 하나를 내보낸다.

  • 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.

이진 파일에 EHCONT 데이터가 포함되어 있는지 검사 하려면 이진 파일의 부하 구성을 덤프할 때 다음 요소를 찾습니다.

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
...

Visual Studio 개발 환경에서 이 컴파일러 옵션을 설정하려면

  1. 프로젝트의 속성 페이지 대화 상자를 엽니다. 자세한 내용은 Visual Studio에서 C++ 컴파일러 및 빌드 속성 설정을 참조하세요.

  2. 구성 속성>C/C++>코드 생성 속성 페이지를 선택합니다.

  3. EH 연속 메타데이터 사용 속성을 선택합니다.

  4. 드롭다운 컨트롤에서 예(/guard:ehcont)를 선택하여 EH 연속 메타데이터를 사용하도록 설정하거나 아니요(/guard:ehcont-)를 선택하여 사용하지 않도록 설정합니다.

참고 항목

/guard(제어 흐름 보호 사용)
MSVC 컴파일러 옵션
MSVC 컴파일러 명령줄 구문