본문 바로가기
정상을향해/Program Analysis

PE File Format (4)

by 사이테일 2013. 11. 10.

출처 : http://www.reversecore.com/

 

 

IMAGE_NT_HEADERS : IMAGE_OPTIONAL_HEADER32

 

IMAGE_OPTIONAL_HEADER32 PE header 구조체 중에서 가장 크기가 크다.

(64bit PE 파일의 경우 IMAGE_OPTIONAL_HEADER64 구조체를 사용한다.)

 

typedef struct _IMAGE_DATA_DIRECTORY {

    DWORD   VirtualAddress;

    DWORD   Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

 

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

 

typedef struct _IMAGE_OPTIONAL_HEADER {

    WORD    Magic;

    BYTE    MajorLinkerVersion;

    BYTE    MinorLinkerVersion;

    DWORD   SizeOfCode;

    DWORD   SizeOfInitializedData;

    DWORD   SizeOfUninitializedData;

    DWORD   AddressOfEntryPoint;

    DWORD   BaseOfCode;

    DWORD   BaseOfData;

    DWORD   ImageBase;

    DWORD   SectionAlignment;

    DWORD   FileAlignment;

    WORD    MajorOperatingSystemVersion;

    WORD    MinorOperatingSystemVersion;

    WORD    MajorImageVersion;

    WORD    MinorImageVersion;

    WORD    MajorSubsystemVersion;

    WORD    MinorSubsystemVersion;

    DWORD   Win32VersionValue;

    DWORD   SizeOfImage;

    DWORD   SizeOfHeaders;

    DWORD   CheckSum;

    WORD    Subsystem;

    WORD    DllCharacteristics;

    DWORD   SizeOfStackReserve;

    DWORD   SizeOfStackCommit;

    DWORD   SizeOfHeapReserve;

    DWORD   SizeOfHeapCommit;

    DWORD   LoaderFlags;

    DWORD   NumberOfRvaAndSizes;

    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 

* 출처 : Microsoft Visual C++ 에서 제공하는 winnt.h

 

IMAGE_OPTIONAL_HEADER32 구조체에서 주목해야 할 멤버들은 다음과 같다.

이 값들 역시 파일 실행에 필수적인 값들이기 때문에 잘못 세팅되면 파일이 정상적으로 실행되지 않는다.

 

#1. Magic

IMAGE_OPTIONAL_HEADER32인 경우 10Bh, IMAGE_OPTIONAL_HEADER64인 경우 20Bh 값을 가진다.

 

 

#2. AddressOfEntryPoint

EP(Entry Point) RVA(Relative Virtual Address) 값을 가진다.

 

 

#3. ImageBase

프로세스의 가상 메모리는 0 ~ FFFFFFFFh 범위이다. (32 bit의 경우)

ImageBase 는 이렇게 광활한 메모리 내에서 PE 파일이 로딩(매핑)되는 시작 주소를 나타낸다.

 

EXE, DLL 파일은 user memory영역인 0 ~ 7FFFFFFFh에 위치하고,

SYS 파일은 kernel memory 영역인 80000000h ~ FFFFFFFFh에 위치한다.

 

일반적으로 개발 도구(VB/VC++/Delphi)들이 만들어내는 EXE 파일의 ImageBase 값은 00400000h 이고,

DLL 파일의 ImageBase 값은 01000000h이다. (다른 값도 가능)

 

PE loader PE 파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩(매핑) 시킨 후

EIP 레지스터 값을 ImageBase + AddressOfEntryPoint 값으로 세팅한다.

 

 

#4. SectionAlignment, FileAlignment

PE 파일은 섹션으로 나뉘어져 있는데파일에서 섹션의 최소단위를 나타내는 것이 FileAlignment이고,

메모리에서 섹션의 최소단위를 나타내는 것이 SectionAlignment이다.

(하나의 파일에서 FileAlignment  SectionAlignment 값은 같을 수도 있고 다를 수도 있다.)

 

따라서 파일 / 메모리의 섹션 크기는 반드시 각각 FileAlignment / SectionAlignment의 배수가 되어야 한다.

 

 

#5. SizeOfImage

PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기를 나타낸다.

일반적으로 파일의 크기와 메모리에 로딩된 크기는 다르다

(각 섹션의 로딩 위치와 메모리 점유 크기는 나중에 소개할 Section Header에 정의 되어 있다.)

 

 

#6. SizeOfHeader

PE header의 전체 크기를 나타낸다. (이 값 역시 FileAlignment의 배수여야 한다.)

 

파일 시작에서 SizeOfHeader 오프셋만큼 떨어진 위치에 첫 번째 섹션이 위치하게 된다.

 

 

#7. Subsystem

 1 : Driver file (*.sys)

 2 : GUI (Graphic User Interface) 파일 -> notepad.exe 와 같은 윈도우 기반 어플리케이션

 3 : CUI (Console User Interface) 파일 -> cmd.exe 와 같은 콘솔 기반 어플리케이션

 

 

#8. NumberOfRvaAndSizes

마지막 멤버인 DataDirectory 배열의 개수

 

구조체 정의에 분명히 배열 개수가 IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16) 이라고 명시 되어 있지만,

PE loader NumberOfRvaAndSizes의 값을 보고 배열의 크기를 인식한다.

 

 

#9. DataDirectory

IMAGE_DATA_DIRECTORY 구조체의 배열로써, 배열의 각 항목마다 정의된 값을 가지게 된다.

 

다음은 각 배열 항목을 나열한 것이다.

 

DataDirectory[0] = EXPORT Directory        

DataDirectory[1] = IMPORT Directory        

DataDirectory[2] = RESOURCE Directory      

DataDirectory[3] = EXCEPTION Directory     

DataDirectory[4] = SECURITY Directory      

DataDirectory[5] = BASERELOC Directory     

DataDirectory[6] = DEBUG Directory         

DataDirectory[7] = COPYRIGHT Directory     

DataDirectory[8] = GLOBALPTR Directory     

DataDirectory[9] = TLS Directory           

DataDirectory[A] = LOAD_CONFIG Directory   

DataDirectory[B] = BOUND_IMPORT Directory  

DataDirectory[C] = IAT Directory           

DataDirectory[D] = DELAY_IMPORT Directory  

DataDirectory[E] = COM_DESCRIPTOR Directory

DataDirectory[F] = Reserved Directory       

 

여기서 말하는 Directory란 그냥 어떤 구조체의 배열이라고 생각하면 된다.

 

빨간색으로 표시한 EXPORT, IMPORT, RESOURCE, TLS Directory를 눈여겨 보자.

특히 IMPORT EXPORT Directory 구조는 PE header 에서 매우 중요하다. (나중에 다시 살펴볼 것이다.)

 

나머지는 중요하지 않기 때문에 크게 신경쓰지 않아도 된다.

 

 

이제 실제로 notepad.exe IMAGE_OPTIONAL_HEADER32를 확인해 보자.

 

 

구조체 멤버 값과 설명은 다음과 같다.

 

[ IMAGE_OPTIONAL_HEADER ] - notepad.exe

 

 offset   value   description

---------------------------------------------------------------------------

000000F8     010B magic

000000FA       07 major linker version

000000FB       0A minor linker version

000000FC 00007800 size of code

00000100 00008C00 size of initialized data

00000104 00000000 size of uninitialized data

00000108 0000739D address of entry point

0000010C 00001000 base of code

00000110 00009000 base of data

00000114 01000000 image base

00000118 00001000 section alignment

0000011C 00000200 file alignment

00000120     0005 major OS version

00000122     0001 minor OS version

00000124     0005 major image version

00000126     0001 minor image version

00000128     0004 major subsystem version

0000012A     0000 minor subsystem version

0000012C 00000000 win32 version value

00000130 00014000 size of image

00000134 00000400 size of headers

00000138 000126CE checksum

0000013C     0002 subsystem

0000013E     8000 DLL characteristics

00000140 00040000 size of stack reserve

00000144 00011000 size of stack commit

00000148 00100000 size of heap reserve

0000014C 00001000 size of heap commit

00000150 00000000 loader flags

00000154 00000010 number of directories

00000158 00000000 RVA  of EXPORT Directory

0000015C 00000000 size of EXPORT Directory

00000160 00007604 RVA  of IMPORT Directory

00000164 000000C8 size of IMPORT Directory

00000168 0000B000 RVA  of RESOURCE Directory

0000016C 00008304 size of RESOURCE Directory

00000170 00000000 RVA  of EXCEPTION Directory

00000174 00000000 size of EXCEPTION Directory

00000178 00000000 RVA  of SECURITY Directory

0000017C 00000000 size of SECURITY Directory

00000180 00000000 RVA  of BASERELOC Directory

00000184 00000000 size of BASERELOC Directory

00000188 00001350 RVA  of DEBUG Directory

0000018C 0000001C size of DEBUG Directory

00000190 00000000 RVA  of COPYRIGHT Directory

00000194 00000000 size of COPYRIGHT Directory

00000198 00000000 RVA  of GLOBALPTR Directory

0000019C 00000000 size of GLOBALPTR Directory

000001A0 00000000 RVA  of TLS Directory

000001A4 00000000 size of TLS Directory

000001A8 000018A8 RVA  of LOAD_CONFIG Directory

000001AC 00000040 size of LOAD_CONFIG Directory

000001B0 00000250 RVA  of BOUND_IMPORT Directory

000001B4 000000D0 size of BOUND_IMPORT Directory

000001B8 00001000 RVA  of IAT Directory

000001BC 00000348 size of IAT Directory

000001C0 00000000 RVA  of DELAY_IMPORT Directory

000001C4 00000000 size of DELAY_IMPORT Directory

000001C8 00000000 RVA  of COM_DESCRIPTOR Directory

000001CC 00000000 size of COM_DESCRIPTOR Directory

000001D0 00000000 RVA  of Reserved Directory

000001D4 00000000 size of Reserved Directory

 

 

'정상을향해 > Program Analysis' 카테고리의 다른 글

Python Hacking Programming (3)  (0) 2013.11.10
Python Hacking Programming (2)  (0) 2013.11.10
Python Hacking Programming (1)  (0) 2013.11.10
PE File Format (3)  (0) 2013.11.10
PE File Format (2)  (0) 2013.11.10
PE File Format (1)  (0) 2013.11.10