PE File Format – PE Header
PE 포맷(Portable Executable)은 윈도우 운영 체제에서 사용되는 실행 파일(EXE), DLL, object 코드, FON 폰트 파일 등을 위한 파일 형식이다.
PE 파일은 크게 PE Header와 PE Body로 나누어 진다.
Dos header부터 Section header까지를 PE Header라 하고, 그 아래 각 Section들과 NullPadding들을 합쳐서 PE Body라고 한다.
우선 PE Header의 내용부터 정리해 보려고 한다.
PE Header
DOS Header (40h/64)
- IMAGE_DOS_HEADER 구조체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // DOS signature – 4D5A (“MZ”)
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
구조체 주요 멤버
- WORD e_magic : Dos signature -4D5A //ASCII(“MZ”)
- LONG e_lfanew : NT Header의 offset (NT Header 구조체의 포인터)
NT Header (F8h/248)
IMAGE_NT_HEADERS 구조체
1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
구조체 주요 멤버
- DWORD Signature (4h): 50450000 //ASCII(“PE..”)
struct IMAGE_FILE_HEADER (20h): 추가정보 참조
1 2 3 4 5 6 7 8 9
typedef struct _IMAGE_FILE_HEADER { WORD Machine; //CPU별 고유 값(intel x86 : 0x014c) WORD NumberOfSections; //the number of sections DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; //IMAGE_OPTIONAL_HEADER32의 크키 WORD Characteristics; //파일의 속성 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
struct IMAGE_OPTIONAL_HEADER(E0h) : 추가정보 참조
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; //x86: 10B / x64 : 20B BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; //RVA값, 프로그램 최초 실행코드의 시작주소 DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; //PE파일에 로딩되는 시작주소 DWORD SectionAlignment; //메모리에서의 섹션 최소단위 DWORD FileAlignment; //파일에서의 섹션 최소단위 WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; //메모리에서 PE Image가 차지하는 크키 DWORD SizeOfHeaders; //PE Header의 전체 크키 DWORD CheckSum; WORD Subsystem; //파일 구분 – Driver(1), GUI(2), CUI(3) WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; //DataDirectory 구조체 배열의 개수 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //EXPORT, IMPORT, RESOURCE, TLS Directory 등 16개의 구조체 } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
Section Header(28h/40)
IMAGE_SECTION_HEADER 구조체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //섹션의 이름. NULL이어도 실행에 무관
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //메모리에서 섹션이 차지하는 크기
} Misc;
DWORD VirtualAddress; //메모리에서 섹션의 시작 주소(RVA)
DWORD SizeOfRawData; //파일에서 섹션이 차지하는 크기
DWORD PointerToRawData; //파일에서 섹션의 시작 위치
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; // 섹션의 속성
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
DOS + NT + Section Header
This post is licensed under CC BY 4.0 by the author.