0%

PE 구조 이해하기 - IMAGE_FILE_HEADER 구조

windows 시스템 실행파일의 구조와 원리 책 내용을 요약 및 정리 하는 포스팅이에요.

PE파일의 PE 시그니처 다음에 이어지는 IMAGE_FILE_HEADER에 대한 내용을 알아볼 거에요.


IMAGE_FILE_HEADER 구조체

IMAGE_FILE_HEADER 구조체는 20바이트로 구성이 되어 있어요.
이것도 당연히 “WinNT.h” 헤더 파일에 정의되어 있어요.

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;

구조체 멤버에 대해 하나씩 설명을 해드릴게요.


첫 번째 멤버, WORD Machine

Machine 필드는 PE 파일의 CPU ID를 나타내요. 즉, 사용자가 어떤 CPU를 통해서 PE 파일을 생성했는지 알 수 있어요.

C언어와 C++로 짜여진 코드 같은 경우에는 CPU 의존적이라서 이런 정보가 들어가 있나봐요.

이것도 CPU ID에 해당하는 매크로 상수가 정의되어 있는데, 자주 사용되는 매크로 상수는 아래와 같아요

1
2
#define IMAGE_FILE_MACHINE_IA64              0x0200  // Intel 64
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)

두 번째 멤버, WORD NumberOfSections

PE 파일에서의 섹션의 수를 나타내요. IMAGE_SECTION_HEADER 구조체 배열의 원소의 개수. 즉, 해당 PE 파일의 섹션의 개수를 의미해요.


세 번째 멤버, DWORD TimeDateStamp

OBj 파일이라면 컴파일러가, EXE 또는 DLL과 같은 PE 파일이라면 링커가 해당 파일을 만들어낸 시간을 의미해요.

이 값은 1970년 1월 1일 09시(GMT 시간 기준)로부터 해당 파일을 만들어낸 시점까지의 초 단위로 표현해요.


네 번째 멤버, DWOARD PointerToSymbolTable

PointerToSymbolTable 필드는 말 그대로 심볼 테이블의 데이터를 가리키는 주소 값이 들어가는 영역이에요. 즉, COFF 심벌의 파일 오프셋 값을 가지고 있는 거에요.

이 필드 같은 경우에는 컴파일러에 의해 생성되는 OBJ 파일 또는 디버그 모드로 만들어져서 COFF 디버그 정보를 가진 PE 파일에서만 사용이 되요.

PE 파일은 복수의 디버그 포맷을 지원하기 떄문에 IMAGE_DIRECTORY_ENTRY_DEBUG 엔트리를 참조해야 되고요.

요즘에는 COFF 심벌 테이블은 새로운 디버그 포맷에 의해 대체되어서 PE 파일 내에서는 거의 사용하지 않아요.
물론 링커 스위치를 /DEBUGTYPE:COFF로 지정할 경우 생성할 수 있어요.


다섯 번째 멤버, DOWRD NumberOfSymbols

PointerToSymbolTable 필드가 가리키는 COFF 심벌 테이블 내에서의 심벌의 수를 나타냄.

이것도 마찬가지로 새로운 디버그 포맷에 의해 대체되어서 사용되지 않음.


여섯 번째 멤버, WORD SizeOfOptionalHeader

IMAGE_FILE_HEADER 구조체 바로 다음에 이어서 나오는 IMAGE_OPTIONAL_HEADER 구조체의 바이트 수를 나타내요.

이 필드는 OBJ 파일의 경우 0이고, 실행 파일의 경우는 “sizeof(IMAGE_OPTIONAL_HEADER)”의 값을 가져요.

32비트 PE 파일의 경우 0xE0(224)바이트이고, 64비트 PE 파일의 경우 0xF0(240)바이트에요.


일곱 번째 멤버, WORD Characteristics

PE 파일에 대한 특정 정보를 나타내는 플래그에요. 이 필드도 “WinNT.h” 헤더 파일에 정의되어 있어요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define IMAGE_FILE_RELOCS_STRIPPED           0x0001  // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external 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 // Aggressively 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.

이 중에서도 중요한 것은 요것들이에요.

매크로명 의미
IMAGE_FILE_RELOCS_STRIPPED 0x0001 현재 파일에 재배치 정보가 없음
IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 본 파일은 실행 파일 이미지이다.
IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 본 파일에 라인 정보가 없다.
IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 본 파일에 로컬 심벌이 없다.
IMAGE_FILE_AGGRESIVE 0x0010 OS로 하여금 적극적으로 워킹셋을 정리할 수 있도록 한다
IMAGE_FILE_LARGE_ADD_RESS_AWARE 0x0020 애플리케이션이 2G 이상의 가상 주소 번지를 제어할 수 있도록한다.
IMAGE_FILE_32BIT_MACHINE 0x0100 본 PE는 32비트 워드 머신을 필요로 한다.
IMAGE_FILE_DEBUG_STRIPPED 0x0200 디버그 정보가 본 파일에는 없고 .DBG 파일에 존재한다.
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 PE 이미지가 이동 가능한 장치 위에 존재할 때 고정 디스크 상의 스왑 파일로 카피해서 실행한다.
IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 PE 이미지가 네트워크 상에 존재할 때 고정 디스크 상의 스왑 파일로 카피해서 실행한다.
IMAGE_FILE_DLL 0x2000 본 파일은 동적 링크 라이브러리 파일이다.
IMAGE_FILE_UP_SYSTEM_ONLYT 0x4000 본 파일은 하나의 프로세서만을 장착한 머신에서 실행된다.

마지막으로…

IMAGE_FILE_HEADER에 대해서 살펴봤는데요.
여기서 중요한 멤버들은 섹션의 수를 조절할 수 있는 NumberOfSections 하고, PE 파일에 대한 특정 정보는 나타내는 플래그인 Characteristics 이에요.

NumberOfSections을 조절하면, 우리가 원하는대로 임의의 섹션을 추가할 수 있어요. 이러한 방법을 이용해서 악성코드를 삽입도 가능하다고 해요!

PE 파일에 특정 정보를 나타내는 플래그인 Characteristics 값의 조합을 알고 있으면, PE 파일을 분석할 필요 없이 이 값만을 가지고 PE 파일이 어떤 특징을 가지고 있는지 알 수 있을 거에요.






참고자료


IMAGE_FILE_HEADER