2016. 2. 3. 18:40

Chapter 48 SEH

48.1. SEH

EEH Windows 운영체제에서 제공하는 예외 처리 시스템입니다.

48.2. SEH예제 실습

먼저 한 간단한 예제를 통해 SEH의 기본 동작 원리와 안티 디버깅에서 SEH가 어떻에 사용되는지 살펴보겠습니다.

이 예제 파일을 실행해 보고 아래 그림과 같이 메지지 박스를 나왔습니다.

이 프로그램은 정상적으로 실행된 것처럼 보이지만 사실 프로세스 내부에서 예외가 발생했습니다. 그런데 SEH를 통해 예외가 잘 처리되어서 정상 실행될 수 있습니다.

이 파일을 디버깅하고 그대로 실행하면 아래 그림과 같이 예외가 발생하면서 실행이 중지되고 status창에서 경고문이 나타납니다.

401019주소에서 EAX 레지스터의 값은 0입니다. MOV DWORD PTR DS:[EAX], 1 명령어의 의미는 메모리 주소 0에 값1을 입력하는 것입니다. 그런데 주소 0이 할당되지 않은 공간인데 마음대로 접근할 수 없어서 예외가 발생했습니다.

그래서 Shift+f9 단축 키로 계속 진행해 보고 아래의 메시지 박스가 나타납니다.

이 메시지 박스를 보면 알 수 있는데 이와 아까 그냥 실행시켰을 때 나타난 메시지 박스가 다릅니다. 그래서 두 가지 실행 방법은 예외 처리하는 방식이 서로 다릅니다.

 

48.3. OS의 예외 처리 방법

48.3.1. 일반 실행의 경우 예외 처리 방법

프로세스가 실행할 때 예외가 발생하면 OS는 그 프로세스 자신이 예외를 처리하게 만듭니다. 포로세스 코드안에 SEH같은 예외 처리하는 코드가 있으면 예외를 잘 처리한 후 계속 진행할 수 있습니다. 그런데 SEH가 없으면 OS는 기본 예외 처리기를 동작시키고 프로세스를 종료시킵니다.

49.3.2. 디버깅 실행의 경우 예외 처리 방법

디버깅 중에 예외가 발생하면 OS는 먼저 디버거에게 처리를 맡깁니다. 그리고 디버거 실행이 중지되고 다른 방법을 취해야 디버깅을 계속할 수 있습니다. 아래는 자주 쓰는 몇 가지 방법입니다.

1) 예외 직접 수정: 코드, 레지스터, 메모리

이 경우에는 디버거를 통해서 문제가 발생한 코드, 메모리, 레지스터 등을 직접 수정하고 정상적인 진행할 수 있습니다.

2)예외를 디버기에게 넘겨서 처리

디버기 내부에 예외를 처리할 수 있는 SEH가 있으면 예외 통지를 디버기에게 보내서 자체 해결하게 만듭니다. 이와 일반 실행의 경우 똑같습니다.

3)OS 기본 예외 처리기

디버거와 디버기는 발생한 예외를 처리할 수 없으면 OS의 기본 처리기에서 처리하고 디버깅이 중지됩니다.

48.4. 예외

그 중에 대표적인 예외 다섯 가지가 있습니다.

1) EXCEPTION_ACCESS_VIOLATION(C0000005)

존재하지 않거나 접근 권한이 없는 메모리 영역에 접근할 때 발생하는 예외입니다.

2) EXCEPTION_BREAKPOINT(80000003)

실행 코드에 break point가 설치한 후 CPU가 그 주소를 실행하려 할 때 이 예외가 발생합니다.

3) EXCEPTION_ILLEGAL_INSTRUCTION(C000001D)

CPU가 해석할 수 없는 Instruction을 만날 때 발생하는 예외입니다.

4) EXCEPTION_INT_DIVIDE_BY_ZERO

정수 나눗셈 연산에서 분모가 0이면 이 예외가 발생할 것입니다.

5) EXCEPTION_SINGLE_STEP(80000004)

Flag 레지스터의 TF 비드를 1로 세팅하면 CPU Single Step 모드로 변경할 것입니다. CPU가 이 모드에서 명령어 하나를 샐행 후 이 예외를 발생시켜서 실행을 멈춥니다.

48.5. SEH 상세 설명

48.5.1. SEH체인

SEH는 체인 형태로 구성되어 있습니다. 첫 번쩨 예외 처리기에서 예외를 처리하지 못하면 다음 예외 처리기로 예외를 넘거줍니다.

아래의 코드는 SEH로 구성된 구조체입니다.

Next 멤버는 다음 구조체 포인터입니다.

Handler 멤버가 예외 처리기 함수입니다.

48.5.2. 함수 정의

아래의 코드는 예외 처리기 함수 정의입니다.

4개의 파라미터를 받으며 EXCEPTION_DISPOSITION이라는 열거형을 리턴합니다.

1)    EXCEPTION_RECORD

아래의 코드는 처리기 함수의 첫 번째 파라미터인 EXCEPTION_RECORD 구조체 정의입니다.

ExceptionCode 멤버는 발생한 예외의 종류를 의미합니다.

ExceptionAdress 멤버는 예외가 발생한 코드 주소를 나타냅니다.

1)    CONTEXT

아래의 코드는 처리기 함수의CONTEXT 구조체 정의입니다.

CONTEXT 구조체는 CPU레지스터 값을 백업할 때 사용합니다. CPU가 다른 스레드를 실행하려면 레지스터들의 값을 현재 스레드의 CONTEXT 구조체에 백업해야 합니다. 그 후에 CPU가 다시 예전의 스레드를 실행할 때 CONTEXT구조체에 백업된 레지스터 값을 실제 CPU 레지스터에 덮어씁니다.

48.5.3. SEH설치 방버

C언어에서 __try, __except, __finally  키워드로 구현할 수 있습니다.

어셈블리 언어에서는 아래의 코드로 추가할 수 있습니다.









'리버싱핵심원리' 카테고리의 다른 글

Reverse Engineering Chap 49  (0) 2016.02.11
Reverse Engineering Chap 47  (0) 2016.02.03
Reverse Engineering Chap 46  (0) 2016.02.03
Reverse Engineering Chap 50-51  (0) 2016.02.03
Reverse Engineering Chap 21-22  (0) 2016.02.03
Posted by 알 수 없는 사용자