SEH(Structured Exception Handling).pdf

SEH의 설명은 첨부파일의 내용을 참조하면 이해하기 쉽다.

컴파일러의 도움 없이 에러처리를 수행하는 예제코드의 디버깅

디버깅에 사용된 전체소스 ↓ (더보기 클릭, 출처: Windows 구조와 원리)

예제 소스는?
1. SEH 설치: 스택과 FS:[0]에 에러 핸들링을 수행할 nHandler함수를 등록
2. SEH 발생: 0번 주소의 메모리에 접근하여 에러가 발생하였을 때
3. 예외 처리: 이미 등록한 nHandler에서 받아 에러가 발생할 당시의 참조 레지스터 eax를 프로그래머가 정의한 전역 변수의 주소 값 G_nValid로 바꾸어 준 후 에어가 발생했던 코드를 다시 실행시키도록 하는 코드


1. SEH의 설치

ULONG nHandler = (ULONG)except_handler;

 __asm
 {
  MOV eax, FS:[0]
  push nHandler
  push FS:[0]
  MOV  FS:[0], ESP
  MOV eax, FS:[0]
 }

1) FS:[0] 값 확인 : MOV eax, FS:[0]
FS[각주:1]:[0]에는 해당 스레드의 EXCEPTION_REGISTATION_RECORD의 포인터가 저장되어 있어 사용자가 지정한 에러 핸들러를 찾을 수 있도록 하고 있다.

eax에 FS:[0] 값을 넣어 FS:[0]값을 확인해보면,


2) nHandler의 값을 스택에 Push : push nHandler
ESP 레지스터 값을 통해 현재 스택위치에 nHandler가 잘 들어갔는지 확인할 수 있다.
push nHandler 명령을 수행한후 실제 디버깅을 해보면 다음과 같은 결과가 나온다.


3) 기존의 FS:[0]을 스택에 Push : push FS:[0]
ESP 레지스터 값을 통해 현재 스택위치를  쫓아가보면, 1)에서 EAX에 넣어서 확인해 보았던 FS:[0]값이 잘 들어가 있음을 알수 있다.


SEH의 구조에 따라  FS:[0], FS[4]: FS:[8]의 메모리를 확인해보면,


4) SEH 설치:MOV  FS:[0], ESP, MOV eax, FS:[0]
FS:[0]에 현재 ESP를 넣고, 변경된 FS:[0]을 확인하기 위해 EAX에 넣어 다시 확인을 해보았다.


위와 같이  스택과 FS:[0]의 값을 변경하여 예외가 발생 되었을 때 Windows가 처리 할 수 있는 구조를 만들어주는 것이다.

2. SEH 발생

 __asm
 {
  mov eax, 0
  mov [eax], 'a'  // SEH 발생
 }



3. 예외처리

SEH가 발생하면 아까 1번에서 설치하였던 SEH에 따라 해당 에러 핸들러를 호출한다.




1) 에러핸들러의 리턴값[각주:2]


2) 에러핸들러의 파라미터값


- ExceptionCode: Error Code 값[각주:3]
여기서 0xc0000005는 헤더파일을 찾아보면 STATUS_ACCEESS_VIOLATION이라고 나온다.
- EstablisherFrame: SEH를 설치할 때 코드에서 설치한 ESP값을 저장하고 있다.
- ContextRecord: Exception이 발생할 당시의 레지스터 값을 가지고 있다.

4. SEH 제거

 // 3. SEH 제거하기
 __asm
 {
  mov eax,[ESP]
  mov FS:[0], EAX
  add esp, 8
 }

설치할때 변경했던 스택과 FS:[0]을 원상복귀 하는 코드이며, 디버깅 하면 아래와 같다.








  1. FS: 프로그램에 보조적인 용도로 사용할수 있도록 추가적으로 제공해주고 있는 세그먼트 윈도우 어플리케이션 레벨에서는 FS레지스터를 TIB(Thread Information Block)의 영역을 지시 [본문으로]
  2. EXCPT.H에 저장되어 있다. [본문으로]
  3. Error Code들에 대한 대부분의 정보는 NT DDK의 NTSTATUS.H에 저장되어 있다. [본문으로]