Security/Forensics

[File Structure] PE파일(Portable Executable)

bonggang 2019. 11. 23. 20:39

PE-COFF(Portable Executable Common Object File Format)


Windows 운영 체제에서 실행 파일(executable files)와 object 파일. 즉 윈도우즈에서 사용되는 실행 파일을 뜻한다. PE파일에는 exe, scr, com, dll, ocx, sys 등이 있다.

PE파일은 악성코드 분석이나 리버스 엔지니어링의 주요 대상이기때문에 보안을 공부하는 사람들이 반드시 공부해야 하는 것 중 하나라고 할 수 있다.

 

PE파일 구조


PE파일의 구조를 공부하기 위해 PE파일의 헤더에 대한 공부는 필수적이다. PE헤더에 파일이 실행되기 위해 필요한 모든 정보가 구조체 형식으로 적혀있기때문이다.

 

 

 

 

DOS Header

64bytes로 고정된 길이를 가지며 주요 구성요소는 e_magic(2bytes)e_lfanew(4bytes)다.

e_magic 2bytes 0x00 MZ
... ... ...  
e_lfanew 4bytes 0x3C NT header의 시작점

 

 

 

DOS Stub Code

길이가 가변적이고 Linker가 만들어서 삽입하는 부분이다. 윈도우가 아닌 DoS 환경에서 실행되었을 경우 실행되는 코드로 필수 구성요소가 아니다.

 

 

NT Header

120bytes 혹은 248bytes의 길이를 가지며 프로그램 실행에 필요한 요소를 가지고 있다.

NT header 구조체는 크게 Signature, FileHeader, OptionalHeader 3가지로 구성되어 있다.

 

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

 

Signature 4bytes 0x00 PE(0x50450000)
FILE_Header 20bytes 0x04  
Optional_Header 96bytes, 224bytes 0x18  

 

 

- File Header

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;

 

Machine 2bytes 0x00 IA32: 0x014c / IA64: 0x0200 / AMD64: 0x8664
NumberOfSections 2bytes 0x02 섹션 개수
TimeDateStamp 4bytes 0x04 파일의 빌드 시간
... ... ... ...
SizeOfOptionalHeader 2bytes 0x10 Optional Header 크기. 
Characteristics 2bytes 0x12 파일 속성

 

Characteristics의 플래그는 다음과 같다.

(https://docs.microsoft.com/ko-kr/windows/win32/api/winnt/ns-winnt-image_file_header)

IMAGE_FILE_RELOCS_STRIPPED 0x0001 Relocation information was stripped from the file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error.
IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 The file is executable (there are no unresolved external references).
IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 COFF line numbers were stripped from the file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 COFF symbol table entries were stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 Aggressively trim the working set. This value is obsolete.
IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 The application can handle addresses larger than 2 GB.
IMAGE_FILE_BYTES_REVERSED_LO 0x0080 The bytes of the word are reversed. This flag is obsolete.
IMAGE_FILE_32BIT_MACHINE 0x0100 The computer supports 32-bit words.
IMAGE_FILE_DEBUG_STRIPPED 0x0200 Debugging information was removed and stored separately in another file.
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 If the image is on removable media, copy it to and run it from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 If the image is on the network, copy it to and run it from the swap file.
IMAGE_FILE_SYSTEM 0x1000 The image is a system file.
IMAGE_FILE_DLL 0x2000 The image is a DLL file. While it is an executable file, it cannot be run directly.
IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 The file should be run only on a uniprocessor computer.
IMAGE_FILE_BYTES_REVERSED_HI 0x8000 The bytes of the word are reversed. This flag is obsolete.

 

 

- Optional Header

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;

 

Magic 2bytes 0x00 Optional Header 시작, 0x010b(HDR32), 0x020b(HDR64)
... ... ...  
AddressOfEntrypoint 4bytes 0x10 PE파일이 메모리에 로드된 후 처음 실행되어야하는 코드(EntryPoint) 주소
... ... ...  
ImageBase 4bytes 0x1C 메모리 내에서 PE 파일이 로딩(매핑)되는 시작 주소
일반적으로 exe - 0x4000000 dll-0x1000000
SectionAlignment 4bytes 0x20 메모리에서 섹션의 최소단위
FileAlignment 4bytes 0x24 파일에서 섹션의 최소단위
... ... ...  
SizeOfImage 4bytes 0x38 메모리에 로드된 PE file 크기
... ...    
DataDirectory 128bytes 0x60  

 

 

Section Header

각 section의 속성을 정의한 부분으로 각 section 별 IMAGE_SECTION_HEADER 구조체의 배열로 구성된다.

 

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;

 

Name 8bytes 0x00 section 이름, 최대 8bytes
... ....    
VirtualAddress 4bytes 0x0C section 시작주소 값(RVA)
SizeOfRawData 4bytes 0x10 파일 상태에서의 section 크기
PointerToRawData 4bytes 0x14 파일 상태에서 section 시작 위치(RVA)
... ...    
Characteristics 4bytes 0x24 section 속성 값

 

 

 

Section

프로그램의 실제 내용을 담고 있는 블록이다.

optional header 구조체의 file alignment가 0x0200이었으므로 200의 배수부터 text section이 시작되는데 200은 아직 section header가 있으므로 400부터 text section이 시작된다.

 


실행 파일 생성 과정

=> 소스코드 -(Compiler)->오브젝트파일-(Linker)->exe, elf

 

RVA

- 상대주소

- RVA = RAW - ImageBase

 

RAW

- 데이터가 쓰인 파일 내의 주소

- RAW = RVA+ImageBase

- RAW = RVA - VirtualAddress + PointerToRawData

 


참고

https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_nt_headers32