PE파일


마이크로소프트가 만든 실행파일의 형식, 운영체제간의 이식성을 높히기 위하여 만든 파일 포멧입니다.  PE구조로 되어 있는 파일은

 종류

 확장자

 실행파일

 exe, scr

 드라이버

 sys, vxd

 라이브러리

 dll, ocx, cpl, drv

 오브젝트파일

 obj

이 있으며 exe는 직접적으로 실행가능하고 obj를 제외한 나머지파일은 간접적으로 실행이 가능합니다.

 

PE파일 구조


 

 

 

PE헤더


DOS Header부터 Section Table[Section Header]까지를 포함하여 PE헤더라고 부르며 위의 sections은 PE Body라고 합니다. 이 부분에는 코드 및 데이터 영역의 위치와 크기, 운영체제, 초기 스택 크기 등 여러 중요한 정보가 들어갑니다.

1) 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 {     
    WORD   e_magic;          // DOS signature : 4D5A ("MZ")
    WORD   e_cblp;                     
    WORD   e_cp;                       
    WORD   e_crlc;                     
    WORD   e_cparhdr;                  
    WORD   e_minalloc;                 
    WORD   e_maxalloc;                 
    WORD   e_ss;                       
    WORD   e_sp;                       
    WORD   e_csum;                     
    WORD   e_ip;                       
    WORD   e_cs;                       
    WORD   e_lfarlc;                   
    WORD   e_ovno;                     
    WORD   e_res[4];                   
    WORD   e_oemid;                    
    WORD   e_oeminfo;                  
    WORD   e_res2[10];                  
    LONG   e_lfanew;         // offset to NT header 
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
cs

모두 다 알기는 어렵기 때문에 중요한것만 고르자면 e_magic과 e_lfanew입니다. [중요한건 텍스트를 진하게 해둘께요.]

1. e_magic : DOS signature로 PE파일의 시그니처가 저장됩니다.

2. e_lfanew : NT Header의 시작주소를 저장합니다.[옵셋값]

 

2) DOS Stub

DOS Header다음에 있는 코드로 크기가 정해져 있지 않는 부분입니다.

DOS에서 돌아가는 16bit 어셈블리어로 작성되어 있습니다.

32bit이상 윈도우에선 실행되지않고 무시되기 때문에 있든없든 상관없습니다.

(대부분 32bit로 프로그래밍된 프로그래밍이 16bit도스모드로 실행됬을때 여기선 돌릴 수 없다 라는 텍스트를 출력하는 용도로 사용하더군요.)

 

3)NT Header

1
2
3
4
5
6
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                  // PE Signature : 50450000 ("PE"00)
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
 
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
cs

총 3개의 멤버로 구성되어 있습니다.

1. Signature : NT코드의 시작을 알리는데 고정적으로 50450000(아스키코드로 PE00)값이 들어 있습니다.

2. FileHeader : 구조체

1
2
3
4
5
6
7
8
9
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
cs

1. Machine : 동작가능한 cpu의 종류를 코드로 담고 있습니다.

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
#define IMAGE_FILE_MACHINE_UNKNOWN        0
#define IMAGE_FILE_MACHINE_I386            0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000            0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000            0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000            0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2        0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA            0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3            0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP            0x01a3
#define IMAGE_FILE_MACHINE_SH3E            0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4            0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5            0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM            0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB            0x01c2
#define IMAGE_FILE_MACHINE_AM33            0x01d3
#define IMAGE_FILE_MACHINE_POWERPC            0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP        0x01f1
#define IMAGE_FILE_MACHINE_IA64            0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16            0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64            0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU            0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16            0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64            IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE            0x0520 // Infineon
#define IMAGE_FILE_MACHINE_CEF            0x0CEF
#define IMAGE_FILE_MACHINE_EBC            0x0EBC // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64            0x8664 // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R            0x9041 // M32R little-endian
#define IMAGE_FILE_MACHINE_CEE            0xC0EE
cs

2. NumberOfSections : 파일이 가지고 있는 Section의 개수를 의미합니다.

3. TimeDateStamp : 파일이 빌드된 시간을 나타냅니다.

4. SizeOfOptionalHeader : NT Header의 3번째 멤버인 OptionalHeader의 크기를 나타냅니다.

5. Characteristics : 파일의 속성에 대한 정보가 담겨있습니다. [리눅스의 rwx와 비슷한것 같네요.]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define IMAGE_FILE_RELOCS_STRIPPED            0x0001 // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE        0x0002 // File is executable (i.e. no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004 // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED        0x0008 // Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM        0x0010 // Agressively trim working set
#define IMAGE_FILE_LARGE_ADDRESS_AWARE        0x0020 // App can handle >2gb addresses
#define IMAGE_FILE_BYTES_REVERSED_LO        0x0080 // Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE            0x0100 // 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED            0x0200 // Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP    0x0400 // If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP        0x0800 // If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM                0x1000 // System File.
#define IMAGE_FILE_DLL                    0x2000 // File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY            0x4000 // File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI        0x8000 // Bytes of machine word are reversed.
cs

 3. OpticalHeader : 구조체

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
35
36
37
38
39
40
41
typedef struct _IMAGE_DATA_DIRECTORY {
 
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
 
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES  
 
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;
cs

1. Magic : 구조체가 32bit용이면 10Bh, 64bit용이면 20Bh값을 가집니다.

2. AddressOfEntryPoint : EP[프로그램의 시작점]주소를 가지고 있습니다.

3. ImageBase : PE파일이 매핑되는 시작주소를 나타냅니다.

4. SectionAlignment : 메모리에서의 섹션의 최소단위를 나타냅니다.

5. FileAlignment : 파일에서 섹션의 최소단위를 나타냅니다.

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

7. SizeOfHeader : PE헤더의 전체크기를 나타냅니다.

8. SubSystem : 파일을 실행하기위한 기본 환경을 나타냅니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define IMAGE_SUBSYSTEM_UNKNOWN            0 // Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE            1 // Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI        2 // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI        3 // Image runs in the Windows character subsystem.
#define IMAGE_SUBSYSTEM_OS2_CUI            5 // image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI            7 // image runs in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS        8 // image is a native Win9x driver.
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI        9 // Image runs in the Windows CE subsystem.
#define IMAGE_SUBSYSTEM_EFI_APPLICATION        10 //
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 //
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER    12 //
#define IMAGE_SUBSYSTEM_EFI_ROM            13
#define IMAGE_SUBSYSTEM_XBOX            14
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16
cs

9. NumberOfRvaAndSizes : 10번인 DataDirectory구조체의 배열 크기를 정합니다.

10. DataDirectory : 파일이 어떤 라이브러리를 제공하고, 필요한지를 정의한 테이블의 위치와 크기가 들어있습니다.

1
2
3
4
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
cs

이런형식으로 들어있는데 배열마다의 역할이 다릅니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Data Directory[0= Export Directory
Data Directory[1= Import Directory
Data Directory[2= RESOURCE Directory
Data Directory[3= EXCEPTION Directory
Data Directory[4= SECURITY Directory
Data Directory[5= BASERELOC Directory
Data Directory[6= DEBUG Directory
Data Directory[7= COPYRIGHT Directory
Data Directory[8= GLOBALPTR Directory
Data Directory[9= TLS Directory
Data Directory[10= LOAD_CONFIG Directory
Data Directory[11= BOUND_IMPORT Directory
Data Directory[12= IAT Directory
Data Directory[13= DELAY_IMPORT Directory
Data Directory[14= COM_DESCRIPTOR Directory
Data Directory[15= Reserved Directory
cs

 

4) SectionTable[Section Header]

이곳에서는 Section을 나누고, Section들의 시작위치, 크기, 속성값등을 정합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define IMAGE_SIZEOF_SHORT_NAME              
 
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
cs

1. VirtualSize : 메모리에서의 Section의 크기가 저장되어 있습니다.

 

2. VirtualAddress : 메모리에서 Section이 시작되는 주소가 저장되어 있습니다.[RVA형식으로 저장]

3. SizeOfRawData : 파일에서 Section이 차지하는 크기를 저장하고 있습니다.

4. PointerToRawData : 파일에서 Section이 시작하는 위치를 저장하고 있습니다.

5. Characteristics : NT헤더의 Characteristics랑 같은 역할을 합니다.

1
2
3
4
5
6
define IMAGE_SCN_CNT_CODE                   0x00000020  // Section contains code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA       0x00000040  // Section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA     0x00000080  // Section contains uninitialized data.
#define IMAGE_SCN_MEM_EXECUTE                0x20000000  // Section is executable.
#define IMAGE_SCN_MEM_READ                   0x40000000  // Section is readable.
#define IMAGE_SCN_MEM_WRITE                  0x80000000  // Section is writeable.
cs

 

 

 

'『리버싱』' 카테고리의 다른 글

PE구조 분석-메모장  (0) 2017.12.26

+ Recent posts