티스토리 뷰

PE Header _ IMAGE_NT_HEADERS

PE 포맷의 실행 파일의 핵심 정보를 담고 있는 구조체이며, PE파일 signiture와 다시 두 개의 구조체로 나뉘어진다.

1개의 4바이트 데이터와 2개의 구조체를 담고 있으며, 총 248 바이트로 구성되어 있다.

typedef struct _IMAGE_NT_HEADERS { DWORD Signature; // 0x50450000 ("PE"0x00 0x00) IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER OptionalHeader; } IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;

1. signature

_IMAGE_NT_HEADERS 의 시작(DOS 헤더의 e_lfanew offset)에는 PE 파일 포맷을 알려주는 "PE"+ 0x00 0x00 이 위치하고 있으며, 이 값이 없다면 Windows 에서는 이 파일이 NT 헤더를 가지고 있지 않는 것으로 본다.


2. FileHeader (IMAGE_FILE_HEADER) | COFF Header <MSDN>

COFF 헤더라고도 부르며, 파일의 개략적인 속성을 나타낸다.


3. OptionalHeader (IMAGE_OPTIONAL_HEADER) | Standard COFF Fields + Windows Specific Fields + Data Directories

PE 파일이 32비트일 경우 IMAGE_OPTIONAL_HEADER32를 (32비트가 붙어있지 않는 경우도 있다. Visual C++ 컴파일러에 따라 다른 것으로 보임.).

64비트일 경우 IMAGE_OPTIONAL_HEADER64를 사용하게 된다.

PE header 구조체 중 그 크기가 가장 크며,  이미지 실행 및 섹션, 가상 메모리 주소 등에 대한 정보를 가지고 있다.


*** 직접 헤더를 확인해보도록 하자.

필자의 경우 CFF Explorer 를 사용했다. (Freeware) | [제작사 홈페이지 링크]

파일을 불러오면 옆에서 해당 파일의 각종 헤더를 확인할 수 있다.


** 구조체 안에 다양한 옵션들이 많이 있는데, 필수적으로 중요한 값들만 살펴보도록 하겠다.

나머지 값들은 데이터가 잘못되거나 없어도 프로그램의 실행에 지장을 주지 않는다.



NT_HEADER -> IMAGE_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;

1. Machine

해당 파일을 실행할 수 있는 (프로그램의 Compiled CPU Target) CPU의 아키텍쳐를 나타낸다.

예를 들어 x86, x86, ARM, MIPS 등이 있겠다.

해당 값은 winnt.h 파일에 "IMAGE_FILE_MACHINE_*" 으로 정의되어 있다.

#define IMAGE_FILE_MACHINE_UNKNOWN	0x0000
#define IMAGE_FILE_MACHINE_AM33		0x01d3 /* Matsushita AM33 */
#define IMAGE_FILE_MACHINE_AMD64	0x8664 /* x64 */
#define IMAGE_FILE_MACHINE_ARM		0x01c0 /* ARM little endian */
#define IMAGE_FILE_MACHINE_EBC		0x0ebc /* EFI byte code */
#define IMAGE_FILE_MACHINE_I386		0x014c /* Intel 386 or later processors 
						  and compatible processors */
#define IMAGE_FILE_MACHINE_IA64		0x0200 /* Intel Itanium processor family */
#define IMAGE_FILE_MACHINE_M32R		0x9041 /* Mitsubishi M32R little endian */
#define IMAGE_FILE_MACHINE_MIPS16	0x0266 /* MIPS16 */
#define IMAGE_FILE_MACHINE_MIPSFPU	0x0366 /* MIPS with FPU */
#define IMAGE_FILE_MACHINE_MIPSFPU16	0x0466 /* MIPS16 with FPU */
#define IMAGE_FILE_MACHINE_POWERPC	0x01f0 /* Power PC little endian */
#define IMAGE_FILE_MACHINE_POWERPCFP	0x01f1 /* Power PC with floating point support */
#define IMAGE_FILE_MACHINE_R4000	0x0166 /* MIPS little endian */
#define IMAGE_FILE_MACHINE_SH3		0x01a2 /* Hitachi SH3 */
#define IMAGE_FILE_MACHINE_SH3DSP	0x01a3 /* Hitachi SH3 DSP */
#define IMAGE_FILE_MACHINE_SH4		0x01a6 /* Hitachi SH4 */
#define IMAGE_FILE_MACHINE_SH5		0x01a8 /* Hitachi SH5 */
#define IMAGE_FILE_MACHINE_THUMB	0x01c2 /* Thumb */
#define IMAGE_FILE_MACHINE_WCEMIPSV2	0x0169 /* MIPS little-endian WCE v2 */
다양한 시스템에 대한 정의가 있지만, 주로 x86 시스템에서는 I386을, x64에서는 IA64를 이용하며,
Windows CE나 Windows Embedded 버전과 같은 ARM 프로세서를 쓰는 시스템에서는 ARM 머신 코드를 사용한다.

2. NumberOfSections
PE 파일은 (ELF도 마찬가지지만) 코드, 전역 변수, 미리 정의된 상수, 리소스 등과 같은 데이터를 각각의 섹션에 나누어 저장한다.
[섹션에 관한 설명은 PE 파일이 메모리에 로드되는 과정에서 후반에 설명]
이 데이터는 그러한 섹션의 갯수를 나타내게 된다.
프로그램이 시작되기 위해서는 최소 실행할 코드가 담겨 있는 최소 1개의 섹션을 포함해야 하므로, 즉 이 구간에는 반드시 1이상의 값이 들어가야 한다.
만약 이 값보다 작은 섹션이 후에 정의되어 있다면 프로그램은 실행되지 않고 에러를 발생하게 되며,
이 값보다 더 많은 섹션이 후에 정의되어 있다면, 이 값보다 더 많이 선언되어 있는 섹션은 로드되지 않고 무시된다.

3. SizeOfOptionalHeader
IMAGE_FILE_HEADER 다음 구간에 위치할 IMAGE_OPTIONAL_HEADER 의 길이를 지정하는 데이터이다.
Optional 헤더는 컴파일시 타겟 CPU(시스템 아키텍쳐) 에 따라 크기가 달라지므로, Windows의 PE Loader는 이 데이터를 보고 로드될 Optional Header의 길이를 결정하게 된다.
다만, Optional 헤더에도 프로그램의 Target CPU에 대한 정보가 선언되어 있으므로, 이 값으로 PE의 타켓 시스템을 판단하지 않는다.

4. Characteristics <MSDN>
이미지 파일(PE 파일)의 특성을 나타내며, bit연산을 1개 이상의 특성을 가질 수 있다. [C++ bit OR 연산을 이용한 플래그 옵션 저장]
여기에서는 자주 쓰이는 값만 설명하며 각각 자세한 내용을 확인하길 원한다면 MSDN의 링크를 참조하면 된다.
#define IMAGE_FILE_RELOCS_STRIPPED	1
#define IMAGE_FILE_EXECUTABLE_IMAGE	2
#define IMAGE_FILE_LINE_NUMS_STRIPPED	4
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED	8
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 	16
#define IMAGE_FILE_LARGE_ADDRESS_AWARE	32
#define IMAGE_FILE_BYTES_REVERSED_LO	128
#define IMAGE_FILE_32BIT_MACHINE	256
#define IMAGE_FILE_DEBUG_STRIPPED	512
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	1024
#define IMAGE_FILE_NET_RUN_FROM_SWAP	2048
#define IMAGE_FILE_SYSTEM	4096
#define IMAGE_FILE_DLL	8192
#define IMAGE_FILE_UP_SYSTEM_ONLY	16384
#define IMAGE_FILE_BYTES_REVERSED_HI	32768
IMAGE_FILE_EXECUTABLE_IMAGE : 독립적으로 실행할 수 있는 파일, .exe 파일이 바로 이것이다.
IMAGE_FILE_SYSTEM : 시스템에 속해있는 파일. 드라이버나 .sys 파일이 이에 해당한다. (?)
IMAGE_FILE_DLL : DLL(Dynamic Link Library)로, 독립적으로는 실행할 수 없으며 다른 실행 파일에서 로드될 수 있는 파일이다.

+ obj 파일의 경우 PE 포맷을 가지지 않고, COFF(X386MAGIC) 이라는 별도의 포맷을 가지고 있다.

참고:


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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
글 보관함