Post

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

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;

구조체 주요 멤버

  1. WORD e_magic : Dos signature -4D5A  //ASCII(“MZ”)
  2. LONG e_lfanew : NT Header의 offset (NT Header 구조체의 포인터)

DOS 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;

구조체 주요 멤버

  1. DWORD Signature (4h): 50450000 //ASCII(“PE..”)
  2. 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;
    
  3. 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;
    

NT 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;

Section Header 구조

DOS + NT + Section Header

PE Header 구조

This post is licensed under CC BY 4.0 by the author.