마이크로소프트의 예외 처리 메커니즘

마이크로소프트 윈도우 운영 체제는 운영 체제 특성에 기반한 예외 처리 메커니즘을 사용한다. 마이크로소프트 구조화된 예외 처리 (Microsoft Structured Exception Handling)는 윈도우를 위한 네이티브 예외 처리 메커니즘이며 VEH의 전신이다. 이것은 표준 C++ 예외에는 존재하지 않는 finally 메커니즘을 특징으로 갖는다(그러나 대부분의 명령형 프로그래밍 언어들에서는 이후 소개되었다). SEH는 실행의 각 스레드를 위해 독립적으로 설치되고 처리된다. SEH의 마이크로소프트 구현은 볼랜드, 미국 특허 5,628,016  라이선스의 특허권에 기반한다. 오픈소스 운영 체제 시스템들은 이 특허권 때문에 SEH 기반 메커니즘을 채택하는 것을 꺼린다. 마이크로소프트는 SEH를 단지 컴파일러 수준에서의 프로그래밍 기법으로 지원한다. MS 비주얼 C++ 컴파일러는 이 목적을 위해 세개의 표준화되지 않은 키워드: __try, __except 그리고 __finally 라는 특징을 갖는다. 다른 예외 처리 측면들은 수많은 윈도우 API 함수들의 지원을 받는다. 예를 들면 SEH 예외를 직접 일으키기 위한 RaiseException가 있다. 윈도우에서 실행의 각 스레드는 자신의 스레드 정보 블록의 시작에서 문서화되지 않은 _EXCEPTION_REGISTRATION_RECORD 리스트와의 연결을 갖는다. __try 선언은 근본적으로 컴파일러에서 정의된 EH_prolog 함수를 호출한다. 이 함수는 스택에서 _EXCEPTION_REGISTRATION_RECORD를 할당하며, 이것은 msvcrt.dll에서 __except_handler3 함수를 가리키고, 리스트의 헤드에 레코드를 추가한다. __try 블록의 끝에서 컴파일러에서 정의된 역 연산을 수행하는 EH_epilog 함수가 호출된다. 이 컴파일러에서 정의된 루틴들은 인라인화될 수 있다. 모든 프로그래머가 정의한 __except 와 __finally 블록들은 __except_handler3 내부에서 호출된다. 만약 이러한 블록들이 존재한다면 생성된 _EXCEPTION_REGISTRATION_RECORD는 소수의 추가적인 필드들로 확장되며, 이것은 __except_handler3에 의해 사용된다. 사용자 모드 코드에서의 예외의 경우, 운영 체제는  핸들러 신호가 예외를 처리하거나 리스트가 끝날 때까지 스레드의 _EXCEPTION_REGISTRATION_RECORD 리스트를 분석하고 순서에 따라 각 예외 처리기를 호출한다. 리스트의 마지막은 항상 일반 보호 장애를 표시하는 kernel32!UnhandledExceptionFilter이다. 그 후 리스트는 처리기에게 사용된 자원들을 청소할 기회를 주며 한번 더 순회된다. 마지막으로 실행은 커널 모드로 반환되는데 여기는 프로세스가 재개되거나 종료되는 곳이다. 벡터화된 예외 처리(Vectored Exception Handling)는 윈도우 XP에서 도입되었다. VEH는 C++과 비주얼 베이직 같은 언어를 사용하는 윈도우 프로그래머에게 사용 가능하게 만들어졌다. VEH는 SEH를 대체하는 것이 아니라 VEH가 SEH보다 더 높은 우선 순위를 가짐으로써 공존한다. SEH와 비교해서, VEH는 더 전통적인 알림 콜백 스킴과 닮았다. 이름은 VC 런타임의 버전들에 따라 다르다. VC 런타임과 정적으로 링크된 다른 프로그램들 뿐만 아니라 ntdll.dll와 kernel32.dll는 컴파일된 이 함수를 갖는다. 더 구체적으로, ntdll!RtlDispatchException 시스템 루틴은 이후 nt!KiDispatchException 커널 함수에서 호출되는 ntdll!KiUserExceptionDispatcher로부터 호출된다.(Ken Johnson (2007년 11월 16일). “A catalog of NTDLL kernel mode to user mode callbacks, part 2: KiUserExceptionDispatcher”.  for details) 이 메시지는 프로세스의 error mode를 변경함으로써 조용해진다; 기본 마지막 처리기는 SetUnhandledExceptionFilter로 대체될 수 있다. ntdll!KiUserExceptionDispatcher은 nt!ZwContinue 또는 nt!ZwRaiseException를 호출한다. “Vectored Exception Handling in Windows Server 2003 (Through Internet Archive)”. 2008년 1월 18일에 원본 문서에서 보존된 문서. 2006년 10월 7일에 확인함.  Matt Miller [aka skape] (September 2006). “Preventing the Exploitation of SEH Overwrites”. Uninformed Journal. 2016년 3월 4일에 원본 문서에서 보존된 문서. 2016년 1월 2일에 확인함.  Microsoft Corp. (2009년 11월 12일). “Structured Exception Handling Functions”. 《MSDN Library》. 2009년 11월 17일에 확인함.  Peter Kleissner (February 2009). “Windows Exception Handling”. 2009년 11월 21일에 확인함.  “New Vectored Exception Handling in Windows XP”.  “Windows Server 2003 Discover Improved System Info, New Kernel, Debugging, Security, and UI APIs”.  Microsoft Corp. (2009년 11월 12일). “Structured Exception Handling”. 《MSDN Library》. 2009년 11월 17일에 확인함.  Matt Pietrek (Jan 1997). “A Crash Course on the Depths of Win32 Structured Exception Handling”. 《MSJ》 12 (1). 2015년 9월 29일에 원본 문서에서 보존된 문서. 2016년 1월 2일에 확인함.  Note that the examples given there do not work as-is on modern Windows systems (post XP SP2) due to the changes Microsoft made to address the security issues present in the early SEH design. The examples still work on later versions of Windows if compiled with /link /safeseh:no. “win32: Safe Structured Exception Handling”. Yasm manual.  US patent 7,480,919 - Safe exceptions  Johannes Passing (2008년 5월 20일). “Fun with low level SEH”.  Covers the obscure details needed to get low-level SEH (and particularly SafeSEH) code to work on more modern Windows. Igor Skochinsky (Monday, March 6, 2006 12:02.38 CST). “Reversing Microsoft Visual C++ Part I: Exception Handling”. OpenRCE. 2009년 11월 17일에 확인함.  다음 날짜 값 확인 필요: |date= (도움말) Matt Miller (2009년 2월 2일). “Preventing the Exploitation of Structured Exception Handler (SEH) Overwrites with SEHOP”. Technet. 2014년 7월 1일에 원본 문서에서 보존된 문서. 2016년 1월 2일에 확인함.  Stéfan Le Berre, Damien Cauquil (2009년 12월 22일). “Bypassing SEHOP” (PDF). Sysdream. 2012년 9월 7일에 원본 문서 (PDF)에서 보존된 문서. 2014년 7월 8일에 확인함.  Joshua J. Drake (2012년 1월 10일). “Old Meets New: Microsoft Windows SafeSEH Incompatibility”. 2014년 7월 14일에 원본 문서에서 보존된 문서. 2016년 1월 2일에 확인함.  An article explaining why Windows 7 SP1 ignores SafeSEH for some older binaries, while Windows XP SP3 honors it.