본문 바로가기
reversing

IMAGE_FILE_HEADER - OPTINAL_HEADER

by 코끼리_땃쥐 2022. 11. 29.
반응형

NT Header - Optional Header

PE 헤더 구조체 중에서 가장 크기가 큰 IMAGE_OPTIONAL_HEADER32 입니다.

typedef struct _IMAGE_DATA_DIRECTORY {
	DWORD	VirtualAddress;
    DWORD	Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUBEROF_DIRECTORY_ENTRIES	16

typedef struct _IMAGE_OPTIONAL_HEADER {
	WORD	Magic;
    BYTE	MajorLinkerVersion;
    BTYE	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_DIRECTORYT_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

IMAGE_OPTIONAL_HEADER32 구조체에서 주목해야 할 멤버들은 아래와 같습니다.

이 값들은 파일 실행에 필수적이라서 잘못 세팅되면 파일이 정상실행되지 않습니다.

 

1. Magic
Magic 넘버는 IMAGE_OPTIONAL_HEADER32구조체인 경우 10B
IMAGE_OPTIONAL_HEADER64 구조체인 경우 20B 값을 가집니다.
2. AddressOfEntryPoint
AddressOfEntryPoint 는 EP(EntryPoint)의 RVA(Relative Virtual Address) 값을 가지고 있습니다.
이 값이야 말로 프로그램에서 최초로 실행되는 코드의 시작 주소로 매우 중요한 값입니다.
3. ImageBase
프로세서의 가상 메모리는 0 ~ FFFFFFFF 범위입니다.(32비트 경우) ImageBase는 이렇게 광활한 메모리에서 PE파일이 로딩되는 시작 주소를 나타냅니다.
EXE, DLL 파일은 user memory 영역인 0 ~ 7FFFFFFF범위에 로딩되고, SYS 파일은 kernel memory 영역인 80000000 ~ FFFFFFFF 범위에 로딩됩니다. PE 로더는 PE 파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩한 후 EIP레지스터 값을 ImageBase + AddressOfEntryPoint 값으로 세팅합니다.
4. SectionAlignment, FileAlignment
PE 파일의 Body 부분은 섹션(Section) 으로 나뉘어져 있습니다. 파일에서 섹션의 최소단위를 나타내는 것이 FileAlignment이고 메모리에서 섹션의 최소단위를 나타내는 것이 SectionAlignment 입니다.(하나의 파일에서 FileAlignment와 SectionAlignment의 값을 같을 수도 있고 다를 수도 있습니다.) 파일/ 메모리의 섹션 크기는 반드 각각 FileAlignment/SectionAlignment의 배수가 되어야 합니다.
5. SizeOfImage
SizeOfImage는 PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기를 나타냅니다. 일반적으로 파일의 크기와 메모리에 로딩된 크기는 다릅니다.
6.SizeOfHeader
SizeOfHeader는 PE 헤더의 전체 크기를 나타냅니다. 이 값 역시 FileAlignment의 배수여야 합니다. 파일 시작에서 SizeOfHeader 옵셋만큼 떨어진 위치에 첫 번재 섹션이 위치합니다.
7. Subsystem
이 Subsystem의 값을 보고 시스템 드라이버 파일(*.sys)인지, 일반 실행 파일(*.exe, *.dll) 인지 구분할 수 있습니다.
8. NumberOfRvaAndSizes
NumberOfRvaAndSizes는 IMAGE_OPTIONAL_HEADER32 구조체의 마지막 멤버인 DataDirectory 배열의 개수를 나타냅니다. 구조체 정의에 분명이 배열 개수가 IMAGE_NUMBEROF_DIRECTORYENTRIES (16) 이라고 명시되어 있지만, PE 로더는 NumberOfRvaAndSizes의 값을 보고 배열의 크기를 인식합니다. 즉 16이 아닐수도 있다는 뜻입니다.
9. DataDirectory
DataDirectory는 IMAGE_DATA_DIRECTORY 구조체의 배열로, 배열의 각 항목 마다 정의된 값을 가집니다.
DataDirectory[0] = EXPORT Directory
DataDirectory[1] = IMPORT Directory
DataDirectory[2] = RESOURCE Directory
DataDirectory[3] = EXCEPTION Directory
DataDirectory[4] = SECUITY 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 Directory
DataDirectory[E] = COM_DECRIPTOR Directory
DataDirectory[F] = Reserved Directory​

여기서 말하는  Directory란 그냥 어떤 구조체의 배열이라고 생각하면 됩니다.
EXPORT, IMPORT, RESOURCE, TLS Directory를 눈여겨 보기 바랍니다. 특히 IMPORT와 EXPORT Directory 구조는 PE해더에서 매우 중요합니다.

반응형

'reversing' 카테고리의 다른 글

IAT & EAT  (0) 2022.12.12
PE File Format 중요 멤버 간단정리  (0) 2022.12.05
PE File Format 구조  (0) 2022.11.25
바이트 오더링  (0) 2022.11.03
고급 안티 디버깅  (0) 2022.10.20

댓글