본문 바로가기

리버싱/리버싱핵심원리

PE File Format(Dos Header ~ Optional Header)

PE File Format 이란?

PE(Portable Executable) 파일은 Windows 운영체제에서 사용되는 실행파일 형식

 

PE 파일 종류

- 실행 계열 : EXE, SCR

- 드라이버 계열 : SYS, VXD

- 라이브러리 계열 : DLL, OCX, CPL, DRV

- 오브젝트 파일 계열 : OBJ

 

* 참고

OBJ 파일 자체로는 어떠한 형태의 실행도 불가능하므로 리버싱

에서는 크게 관심X

 

PE 파일 기본 구조

PE Header : DOS Header ~ Section Header

PE Body : PE Header 이후의 Section들

 

파일에서는 offset으로, 메모리에서는 VA(Virtual Address, 절대주소)로 위치를 표현

파일의 내용은 보통 코드(.txt), 데이터(.data), 리소스(.rsrc) 섹션으로 나뉘어 저장된다

파일/메모리에서 섹션의 시작 위치는 각 파일/메모리의 최소 기본 단위의 배수에 해당하는 위치여야 하고, 빈 공간은 NULL로 채움

 

VA(Virtual Address) & RVA(Relative Virtual Address)

VA는 프로세스 가상 메모리의 절대주소를 말하며, RVA는 어느 기준 위치에서부터의 상대주소를 말한다

 

RVA + ImageBase(기준 위치) = VA

 

 

 

PE 헤더

DOS Header

PE 헤더 가장 앞부분에는 IMAGE_DOS_HEADER 구조체가 존재하는데 크기는 40이고, 이 구조체에서 e_magic과 e_lfanew를 알아야한다

e_magic : DOS signature (4D5A -> ASCII값 "MZ")

e_lfanew : NT Header의 옵셋을 표시(파일에 따라 가변적인 값을 가짐)

 

모든 PE 파일의 시작부분(e_magic)에는 DOS signature ("MZ")가 존재하고, e_lfanew 값이 가리키는 위치에 NT Header 구조체가 존재한다

파일 시작 2바이트는 4D5A이며, e_lfanew 값은 000000E0이다

 

DOS Stub

DOS Stub의 존재 여부는 옵션이며 크기도 일정하지 않다

코드와 데이터의 혼합으로 이루어졌다

 

NT Header

 

IMAGE_NT_HEADERS 구조체는 3개의 멤버로 되어 있는데, 우선 Signature로 50450000h("PE"00)값을 가짐

그리고 File Header와 Optional Header 구조체 멤버가 있다

IMAGE_NT_HEADERS 구조체의 크기는 F8이다

 

 

 

 

NT Header -File Header

 

IMAGE_FILE_HEADER 구조체

 

typedef struct _IMAGE_FILE_HEADER {

    WORD Machine;

    WORD NumberOfSections;

    DWORD TimeDateStamp;

    DWORD PointerToSymbolTable;

    DWORD NumberOfSymbols;

    WORD SizeOptionalHeaders;

    WORD Characteristics;

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

 

#1. Machine

 Machine 넘버는 CPU별로 고유한 값(파일의 CPU 아키텍처를 나타냄)이며 32비트 Intel x86 호환 칩은 014C의 값을 가진다

 winnt.h 파일에 Machine 넘버의 값들이 정의되어 있다

 

#2. NumberOfSections

PE 파일은 코드, 데이터, 리소스 등이 각각의 섹션에 나뉘어서 저장되는데 NumberOfSections는 그 섹션이 개수를 나타냄

 

#3. SizeOfOptionalHeader

IMAGE_OPTIONAL_HEADER 구조체의 크기를 나타낸다

 

#4. Characteristics

실행이 가능한 형태인지 또는 DLL 파일인지 등의 정보들이 bit OR 형식으로 조합된다

winnt.h 파일에 정의된 Characteristcs 값들 중에 0002h, 2000h 값은 중요

 

#define IMAGE_FILE_EXCUTABLE_IMAGE  0x0002  // File is executable

                                                                 // (i.e. on unresolved externel references).

#define IMAGE_FILE_DLL                      0x2000  // File is a DLL.

 

Characteristics 값에 0002h가 없는 경우(not executable)는 *.obj와 같은 object 파일 및 resourceDLL 같은 파일이 있다

 

 

 

NT Header - Optional Header

 

IMAGE_OPTIONAL_HEADER32 구조체

 

typedef struct _IMAGE_DATA_DIRECTORY {

    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;  // PE 파일이 로딩되는 시작주소
    DWORD SectionAlignment;  // 메모리의 섹션 최소단위
    DWORD FileAlignment;       // 파일의 섹션 최소단위
    WORD MajorOperatingSystemVersion;
    WORD MinorOperatingSystemVersion;
    WORD MajorImageVersion;
    WORD MinorImageVersion;
    WORD MajorSubsystemVersion;
    WORD MinorSubsystemVersion;                            <-- NT 추가 필드 : 윈도우 링커(로더)가 요구하는 정보
    DWORD Win32VersionValue;
    DWORD SizeOfImage;     // 메모리 로딩 시 차지하는 PE 파일 크기
    DWORD SizeOfHeaders;  // PE 헤더의 전체 크기
    DWORD CheckSum;
    WORD Subsystem;         // 파일종류(드라이버 / 실행파일)
    WORD DllCharacteristics; // ASLR, DEP, SEH, Signing(메모리 보호) 관련 속성
    DWORD SizeOfStackReserve;
    DWORD SizeOfStackCommit;
    DWORD SizeOfHeapReserve;
    DWORD SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;    // DataDirectory 배열의 갯수

=====================================
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];    <-- DataDirectory 배열
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 

#1. Magic

Magic 넘버는 IMAGE_OPTIONAL_HEADER32 구조체인 경우 10B

IMAGE_OPTIONAL_HEADER64 구조체인 경우 20B의 값을 가짐

 

#2. AddressOfEntryPoint

EP의 RVA값을 가지고 있다. 프로그램에서 최초로 실행되는 코드의 시작주소

 

#3. ImageBase

PE 파일이 로딩되는 시작 주소를 나타낸다

 

EXE, DLL 파일은 user memory 영역인 0 ~ 7FFFFFFF 범위에 로딩되고,

SYS 파일은 kernel memory 영역인 80000000 ~ FFFFFFFF 범위에 로딩된다

 

PE 로더는 PE 파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩한 후 EIP 레지스터 값을 ImageBase + AddressOfEntryPoint 값으로 셋팅

 

#4. SectionAlignment ,FileAlignment

PE 파일의 Body 부분은 섹션으로 나뉘어져 있는데 파일에서 섹션의 최소단위를 나타내는 것은 FileAlignment이고,

메모리에서 섹션의 최소단위를 나타내는 것은 SectionAlignment이다

 

#5. SizeOfImage

SizeOfImage는 PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기를 나타낸다

 

#6. SizeOfHeader

PE 헤더의 전체 크기를 나타내는데 FileAlignment의 배수여야 한다

 

#7. Subsystem

Subsystem의 값을 보고 시스템 드라이버 파일(*.sys)인지, 일반 실행 파일(*.exe, *.dll)인지 구분할 수 있다

 

#8. NumberOfRvaAndSizes

DataDirectory 배열의 갯수를 나타낸다 위에 IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16)이라고 명시되어 있으나

PE 로더는 NumberOfRvaAndSizes의 값을 보고 배열의 크기를 인식하므로 값이 일치하지 않을 수 있다

 

#9. DataDirectory

 

DataDirectory 구조체 배열

 

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

'리버싱 > 리버싱핵심원리' 카테고리의 다른 글

PE File Format(EAT)  (0) 2019.12.01
PE File Format(IAT)  (0) 2019.11.29
Process Explorer, 함수 호출 규약  (0) 2019.08.25
3, 4장 요약(바이트 오더링, IA-32 Register)  (0) 2019.08.24
1, 2장 요약  (0) 2019.08.24