튜기's blogggg

PE구조

by St1tch


    1. PE 구조 개요

Microsoft의 운영 체제 Windows 3.1부터 지원되는 실행파일의 구조를 말한다. 다양한 운영 체제에서의 이식성을 보여준다는 뜻에서 이식이 가능한 실행 형식(Portable Executable)이라는 이름을 붙였다.

 

PE 파일의 종류는 다음과 같다.

•실행 파일 계열 : EXE, SCR(Screen Saver)

•라이브러리 계열 : DLL, OCX(Active X)

•드라이브 계열 : SYS

•오브젝트 파일 계열 : OBJ

 

사용할 툴 : HxD

분석대상 : Notepad.exe

 

전체적인 PE 파일의 구조는 다음과 같다.

 











 

 

 

 

    2. DOS_Header (PE Header > DOS_Header)

 

 

"4D 5A"로 시작하는 부분부터 64Byte까지가 Image_Dos_Header 부분이다. 이 부분은 PE 구조를 가지고 있는 파일인지 판단한다. "4D 5A" 로 시작하는 파일이라면 PE 구조를 가진다.

"4D 5A"는 MZ라는 문자열로서, PE 구조를 개발한 Mark Zbikowski의 이름을 의미한다.

 

Image_Dos_Header에 들어갈 내용은 WinNT.H 헤더파일에 구조체의 형식으로 설정되어 있다. 이 구조체의 크기를 계산 해 보면 64Byte임을 알 수 있다. 그 내용은 다음과 같다.

 

 

위의 구조체에서 확인해야 할 부분은 e_magic과 e_lfanew 부분이다.

 

e_magic : PE 구조를 가진 파일인지 확인할 때 사용된다. "4D 5A (MZ)" 부분이다. 프로그램을 실행하면 가장 먼저 이 부분의 2Byte를 읽어온 후 PE 구조(4D 5A)가 맞는지 확인한다.

 

e_lfanew : 다음에 나올 Image_NT_Header의 시작 주소를 저장한다. 파일에 따라 다른 값이 저장된다. 주소값의 저장에는 Little Endian 표기법이 사용된다.

 

Little Endian 표기법 : 0x11223344 라는 값을 저장할 때 44 33 22 11 의 순서로 저장하는 방식을 말한다.

 

 

 

 

 

 

   3. DOS Stub Code (PE Header - DOS Stub Code)

 

 

DOS Stub Code에는 DOS 모드에서 실행되었을 때 실행할 내용을 저장한다. 오른쪽 ASCII Code를 표시하는 부분을 보면 "This program cannot be run in DOS mode" 라는 메시지를 표시하는 것을 볼 수 있다.

 

 

    4. NT_Header (PE Header > NT_Header )

WinNT.H의 구조체에서 e_lfanew에 저장된 주소값이 바로 이 부분을 가리킨다. NT_Header에는 파일 실행에 필요한 정보가 저장되어 있다. "50 45 00 00"으로 시작하는 곳이 NT_Header의 시작 부분이다.

 





 

PE Header에는 Signature, File_Header, Optional_Header의 정보를 포함한다. 각각의 구조체가 포함하는 정보의 내용은 다음과 같다.

 

PE Header

Signature

"50 45 00 00"의 4Byte 공간. ASCII Code로 PE 라는 문자열을 나타내며 PE구조를 가진 파일이라는 것을 알린다.

File_Header

동작하는 CPU, 섹션의 수, 생성 시간 등 파일의 대략적인 정보를 저장한다.

Optional_Header

파일의 실행에 필요한 주요 정보들을 저장한다.

 

 

NT_Header 구조체의 멤버는 아래 그림과 같이 선언되어 있다.

 

 

NT_Header에 저장되는 정보들을 구체적으로 알아보자.

 

4-1 Signature (PE Header > NT_Header > Signature)

"50 45 00 00" 부분은 NT_Header의 시작을 나타낸다. 이를 Signature라고 하는데, ASCII Code로 PE 라는 문자열을 나타내며, NT_Header의 시작을 알리는 역할을 한다. 이 부분의 값을 수정하면 올바른 PE 파일이 아니라고 인식하여 실행되지 않는다.

 

4-2 File_Header (PE Header > NT_Header > File_Header)

File Header에는 파일에 대한 기본적인 정보가 저장되어 있다. 그 내용은 다음과 같다.

 

File_Header

Machine

파일이 동작할 수 있는 CPU 종류

Number Of Sections

PE 파일을 구성하는 섹션의 수

Time Data Stamp

PE 파일이 만들어진 시간

Size Of Optional Header

Optional Header의 크기

Characteristics

현재 파일의 형식

 

File Header 구조체는 다음과 같은 내용을 포함한다.

 

    4-2-1. Machine (PE Header > NT_Header > File_Header > Machine)

아래의 부분이 Machine 값이 실제로 표시되는 위치이다.



다음 코드는 WinNT.H에 정의된 Machine 상수이다. CPU의 타입에 따라 저장되는 값을 지정해 두고 있다.

 

 

64 86이라는 값은 Little Endian 표기법에 따라 저장된 값이므로, 0x8664를 의미한다. Machine 상수에서 그 값을 찾아보면 AMD64에 해당하는 값이다. 즉, 이 파일은 AMD64 CPU와 호환성을 가진다.

 

분석에 사용한 Notepad 파일은 Vmware로 만든 가상 PC에서 분석한 값이므로 AMD64 CPU로 표시되었다. 보통 많이 사용하는 Intel 계열의 CPU라면 0x014c, "4C 01" 라는 값이 표시 될 것이다.

 

    4-2-2. Number Of Section (PE Header > NT_Header > File_Header > Number Of Section)

이 부분에는 PE 파일을 구성하는 섹션의 숫자를 나타낸다. 이 값을 보고 이후에 등장하는 섹션의 개수를 알 수 있으며, 이 값은 0보다 커야 한다. 즉, 섹션이 없는 파일은 존재하지 않는다.

 

 

Notepad 파일의 섹션 수는 6개 임을 알 수 있다.

    4-2-3. Time Data Stamp (PE Header > NT_Header > File_Header > Time Data Stamp)

Time Data Stamp는 PE 파일이 만들어진 시간이 기록된다.

 

 

B3 C9 5B 4A 는 0x4A5BC9B3이며, 이는 10진수로 1247529395이다. 이는 1970년 1월 1일 0시를 기준으로 경과 된 시간을 초 단위로 표시한다.

 

1247529395 / 60 = 20792156분 35초

20792156 / 60 = 346535시간 56분

346535 / 24 = 14438일 23시

14438 / 365 = 39년 203일

1970년 1월 1일 0시 + 39년 203일 23시 56분 35초 즉, 2009년 7월 13일 23시 56분 35초가 된다.

 

 

    4-2-4. Pointer To Symbol Table, Number of Symbols

            (PE Header > NT_Header > File_Header > Pointer To Symbol Table, Number Of Symbols)

 

 

▶Pointer To Symbol Table

COFF(Common Object File Format) Symbol Table이 존재할 때 Symbol 테이블로 향하는 포인터 역할을 한다.

COFF는 수많은 프로그램들을 하나로 합쳐 메모리에 옮기는 과정에서 매우 복잡하고 많은 시간을 요구하는 등의 문제점을 개선하기 위해 미국 AT&T사에서 고안해 낸 규칙이다. 공통된 성질을 가지는 것들을 하나로 합치며, 합쳐진 것을 섹션이라 하고, 섹션은 사용하는 언어에 따라 따로 정해져 있다. COFF 규칙은 프로그램 개수에 상관없이 프로그램을 몇 개의 섹션으로 구분하기 때문에 프로그램 구성적인 측면에서 보면 간단해 진다.

 

Number Of Symbols

Pointer To Symbol Table에 값이 설정되어 Symbol 테이블을 참조하고 있다면, 해당 테이블 안의 Symbol의 개수의 값이 설정된다. 현재는 Symbol의 크기가 커져 따로 파일로 저장되어 사용되기에 Pointer To Symbol Table과 Number Of Symbols는 사용되지 않는다.

 

 

    4-2-5. Size Of Optional Header (PE Header > NT_Header > File_Header > Size Of Optional Header)

Size Of Optional Header는 이름에서 알 수 있듯이 Optional Header의 크기를 저장한다. Optional Header의 크기는 운영 체제에 따라 차이가 있다.

 

 

Notepad 파일의 Size Of Optional Header에는 "0x00F0"가 저장되어 있다. 32Bit PE 파일의 경우 0xE0(224Byte), 64Bit PE 파일의 경우 0xF0(240Byte), OBJ 파일의 경우0x00(0Byte) 가 저장된다. 이 파일은 64Bit PE 파일이다.

 

 

    4-2-6. Characteristics (PE Header > NT_Header > File_Header > Characteristics)

Characteristics는 현재 파일의 형식을 알려준다. 이 값을 이용해 파일의 종류(EXE, DLL, SYS등)를 알 수 있다.

 

 

Characteristics에 저장되는 값은 다음과 같이 정의되어 있으며, Bit OR연산을 진행하여 저장된다. Linux의 Permission값의 계산에 사용된 방식과 동일하다.

 

 

Notepad의 Characteristics에는 0x0022라는 값이 저장되어 있다. 이는 0x0002와 0x0020의 OR 연산 결과이다. 즉, 실행 파일이면서 App can handle >2gb addresses, 64Bit 운영 체제를 사용한다.

 

    4-3 Optional_Header (PE Header > NT_Header > Optional_Header)

Optional Header에는 파일 실행에 관한 중요한 정보들을 저장한다. Optional Header를 이해하기 위해서 RVA주소의 개념을 먼저 이해할 필요가 있다.

 

※RVA : Relative Virtual Address

실행파일이 메모리에 로드 되었을 때, 그 시작 주소(Image Base)를 0으로 생각하고 계산하는 주소이다. 즉, RVA의 값이 0x3000 이고 실행파일이 로드 되었을 때 Image Base가 0x40000 이라면, RVA 0x3000 영역이 메모리에 로드 되었을 때 위치는 0x403000이 된다.

 

Optional Header의 멤버들은 다음과 같은 값을 지닌다.

 

Optional_Header

Magic

Optional Header 32 구조체인 경우 0x10B,

Optional Header 64구조체인 경우 0x20B가 저장된다.

Size Of Code

코드 영역(.text Section)의 크기를 나타낸다.

Address Of Entry Point

프로그램이 시작되는 코드의 주소가 RVA값으로 저장되어 있다.

Olly DBG를 실행시키면 처음 실행하는 위치이다.

Base Of Code

코드 영역이 시작되는 상대 주소(RVA)이다.

Image Base

PE 파일이 메모리에 로드되는 시작 주소를 가리킨다.

EXE 파일은 0x400000, DLL파일은 0x10000000 번지로 설정되어 있으나, 설정에 따라 달라질 수 있다.

RVA의 기준이 된다.

Section Alignment

메모리에서 섹션의 최소 단위를 나타낸다. 메모리 섹션의 시작 주소는 반드시 Section Alignment의 배수가 된다.

File Alignment

파일에서 섹션의 최소 단위를 나타낸다. 파일 섹션의 시작 주소는 반드시 File Alignment의 배수가 된다.

Size Of Image

PE 파일이 메모리에 로딩되었을 때의 전체 크기를 나타낸다.

Size Of Headers

모든 헤더의 크기를 나타낸다.

(Dos Header+ DOS Stub+ PE Header+ Section Header)

Sub System

System Driver 파일, GUI, CUI 파일을 구분한다.

1인 경우에는 System Driver File,

2 인 경우에는 GUI 파일,

3 인 경우에는 CUI 파일을 의미한다.

Number Of RvaAndSizes

Data Directory의 구조체 멤버 개수(0x10으로 일정)를 나타낸다.

Data Directory

PE 파일에서 중요한 역할을 하는 개체들의 위치, 크기를 나타낸다.

 

 

Optional Header구조체는 는 다음과 같이 선언되어 있다.

 

 

Optional Header의 Data Directory 구조체는 Export 디렉터리, Import 디렉터리, Resource 디렉터리, 예외 디렉터리, 보안 디렉터리 영역 등에 접근할 수 있는 주소와 크기를 지니고 있는 배열로써 다음과 같이 정의되어 있다.

 

 

Notepad.exe의 Optional Header 값들을 살펴 보자.

 

 

이 값들을 통해 알 수 있는 Notepad.exe의 정보는 다음과 같다.

 

번호

이름

설명

1

0x20b

Magic

Optional Header 64를 사용한다.

2

0x8a00

Size of Code

코드 영역(.Text Section)의 크기는 0x8a00

3

0x3570

Address Of Entry Point

파일을 실행하면 Image Base + 0x3570 즉,

0x3571 코드부터 실행된다.

4

0x1000

Base of Code

코드 영역이Image Base+0x1000부터 즉,

0x1001부터 시작된다.

5

0x1

Image Base

RVA의 기준은 0x1이 된다.

6

0x1000

Section Alignment

섹션의 크기는 1000의 배수가 되고,

빈 공간은 0으로 채워진다.

7

0x200

File Alignment

 

8

0x35000

Size of Image

파일이 로딩되었을 때의 전체 크기는 0x35000이다. 파일이 로딩 되었을 때의 크기이므로, File Alignment의 배수가 된다.

9

0x600

Size Of Headers

헤더의 크기는 0x600이다.

10

0x2

Subsystem

이 파일은 GUI 파일이다.

11

0x10

Number Of RvaAndSizes

Data Directory의 구조체는 0x10개 이다.

 

 

 

 

 

 

 

5. Section_Header (PE Header > Section_Header )

Section Header에는 섹션에 대한 정보가 저장된다. Section Header의 구조체는 다음과 같다.

 

 

Section Header는 종류가 다양하다. Section의 종류는 Name 구조체에 최대 8Byte 크기로 저장된다. 기본적인 섹션의 종류와 용도는 다음과 같다.

 

종류

용도

.text

파일을 열었을 때 실행될 코드가 저장된다.

.data

초기화된 전역 변수, static 변수를 저장한다.

.rdata

const 변수, 문자열 상수를 저장한다.

.bss

초기화 되지 않은 전역 변수, static변수, 문자열, 기타 상수가 저장된다. 초기화가 진행되면 data영역으로 이동한다.

.edata

EAT와 관련된 정보가 저장된다.

.idata

IAT와 관련된 정보가 저장된다.

.rsrc

리소스가 저장된다.

 

다음 표는 각각의 구조체 멤버가 저장하는 값과 그 내용이다.

 

멤버

내용

Virtual Size

메모리에서 섹션의 크기이다.

Virtual Address

메모리에서 섹션의 시작 주소를 RVA로 나타낸다.

Size Of Raw Data

파일에서의 섹션의 크기이다(File Alignment의 배수).

Pointer To Raw Data

파일에서 섹션의 시작 위치이다.

Characteristics

섹션의 정보를 표시한다.

 

▶Characteristics

File_Header > Characteristics와 유사한 기능을 가진다. 섹션이 읽기, 쓰기, 실행이 가능한지, 초기화된 섹션인지 등을 표시한다. 그 내용은 다음과 같이 정의되어 있다.

 

 

 

다음 그림은 Notepad 파일의 .text Section의 내용이다.

 

 

번호

이름

설명

1

0x747865742E

Name

Section의 이름은 .text 즉, 코드를 저장하는 섹션이다.

2

0xA770

Virtual Size

메모리에서 섹션의 크기는 0xA770이다.

3

0x1000

Virtual Address

메모리에서 섹션은 0x1000부터 시작한다.

Image Base가 0x1이므로, 실제 주소는 0x1001이 된다. Optional Header의 Base of Code 값과 동일하다.

4

0xA800

Size of Raw Data

파일에서의 섹션의 크기는 0x800이다.

File Alignment(0x200)의 배수이다.

5

0x600

Pointer To Raw data

파일에서 섹션이 시작되는 위치이다.

File Alignment(0x200)의 배수이다.

6

0x60000020

Characteristics

OR연산을 진행하여 표시된다. Characteristics 구조체에서 20000000은 실행, 40000000은 읽기, 20은 코드로 채워진 섹션이라는 의미이다. 따라서 이 영역은 읽기와 실행이 가능한 코드 섹션이다.

 

 

 

 

 

 

 

6. Notepad.exe 파일의 PE 구조를 분석해 얻을 수 있는 정보

 

파일의 PE 구조를 분석해 얻을 수 있는 정보는 다음과 같다.

이름

용도

Notepad.exe의 값

DOS Header

PE 구조 사용 여부

4D 5A (MZ)

DOS Stub

Dos에서 실행되었을 때 표시 할 내용

This program cannot...

NT Header

Machine

파일이 동작하는 CPU

AMD64

Number of Section

섹션의 수

6개

Time Data Stamp

만들어진 시간

2009.7.13 23:56:35

Size of Optional Header

Optional Header의 크기

64Bit 240Byte

Characteristics

파일의 형식

64Bit 실행파일

Optional Header

Magic

Optionnal Header의 종류

64Bit

Size of Code

코드섹션의 크기

0x8a00

Address Of Entry Point

처음 실행되는 코드의 주소

Image Base + 0x3570

Base of Code

코드 영역의 주소

Image Base + 0x1000

Image Base

RVA의 기준점

0x1

Section Alignment

섹션의 단위

0x1000

File Alignment

파일의 단위

0x200

Size of Image

메모리에 로딩 되었을 때의 크기

0x35000

Size of Header

헤더의 크기

0x600

Sub System

파일의 종류

GUI

.text Section

Name

섹션의 종류

코드를 저장하는 text섹션

Virtual Size

메모리에서 섹션의 크기

0xA770

Virtual Address

메모리에서 섹션의 주소

Image Base + 0x1000

Size of Raw Data

파일에서의 섹션의 크기

0x800

Pointer To Raw Data

파일에서 섹션이 시작되는 주소

0x200



블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기