PE(Portable Executable) File Format (4) - PE Header
리버싱 2017. 2. 9. 13:57IMAGE_NT_HEADERS - IMAGE_OPTIONAL_HEADER32
PE header 구조체 중에서 가장 크기가 큰 IMAGE_OPTIONAL_HEADER32 입니다.
(64 bit PE 파일의 경우 IMAGE_OPTIONAL_HEADER64 구조체를 사용합니다.)
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 를 확인해 보겠습니다.
구조체 멤버별 값과 설명은 아래와 같습니다.
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
여기까지 NT Header 의 설명을 마치고 다음에 Section Header 에 대해서 살펴보도록 하겠습니다.
(continue)
출처 - http://reversecore.com/21
'리버싱' 카테고리의 다른 글
PE(Portable Executable) File Format (6) - PE Header (0) | 2017.02.09 |
---|---|
PE(Portable Executable) File Format (5) - PE Header (0) | 2017.02.09 |
PE(Portable Executable) File Format (3) - PE Header (0) | 2017.02.09 |
PE(Portable Executable) File Format (2) - PE Header (0) | 2017.02.09 |
PE(Portable Executable) File Format (1) - PE Header (0) | 2017.02.09 |