출처 : http://www.reversecore.com
NT Header
다음은 NT header 구조체 IMAGE_NT_HEADERS 이다.
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; // PE Signature : 50450000 ("PE"00) IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h |
(위 구조체는 32 bit 용이며, 64 bit 용은 세번째 멤버가 IMAGE_OPTIONAL_HEADER64로 되어있다.)
IMAGE_NT_HEADER 구조체는 3개의 멤버로 구성된다.
첫 번째 멤버는 Signature 로서 50450000h ("PE"00) 값을 가진다. (변경 불가!)
그리고 FileHeader 와 OptionalHeader 구조체 멤버가 있다.
notepad.exe 의 IMAGE_NT_HEADERS 의 내용을 hex editor로 살펴보자.
IMAGE_NT_HEADERS 구조체의 크기는 F8h로 상당히 큰 편이다.
FileHeader 와 OptionalHeader 구조체를 하나하나 살펴보자.
IMAGE_NT_HEADERS : IMAGE_FILE_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;
* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h |
IMAGE_FILE_HEADER 구조체에서는 다음 4가지 멤버들이 중요하다.
(이 값들이 정확히 세팅되어 있지 않으면 파일은 정상적으로 실행되지 않는다.)
#1. Machine
Machine 넘버는 CPU 별로 고유한 값이며 32bit Intel 호환 칩은 14Ch 의 값을 가진다.
아래는 winnt.h 파일에 정의된 Machine 넘버의 값들이다. (일반적인 14Ch 의 값을 기억하면 된다.)
#define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian #define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian #define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP #define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian #define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian #define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian #define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian #define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian #define IMAGE_FILE_MACHINE_THUMB 0x01c2 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 #define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS #define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS #define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 #define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 |
#2. NumberOfSections
PE 파일은 코드, 데이터, 리소스 등이 각각의 섹션에 나뉘어 저장되는데, NumberOfSections는 바로 그 섹션의 개수를 나타낸다.
(이 값은 반드시 0보다 커야 한다.)
정의된 섹션 개수보다 실제 섹션이 적다면 실행 에러가 발생하며,
정의된 섹션 개수보다 실제 섹션이 많다면 정의된 개수만큼만 인식된다.
#3. SizeOfOptionalHeader
IMAGE_NT_HEADERS 구조체의 마지막 멤버는 IMAGE_OPTIONAL_HEADER32 구조체이다.
SizeOfOptionalHeader 멤버는 IMAGE_OPTIONAL_HEADER32 구조체의 크기를 나타낸다.
IMAGE_OPTIONAL_HEADER32 는 C언어의 구조체이기 때문에 이미 그 크기가 결정되어 있다.
그런데 Windows 의 PE Loader 는 IMAGE_FILE_HEADER 의 SizeOfOptionalHeader 값을 보고 IMAGE_OPTIONAL_HEADER32 구조체의 크기를 인식한다.
(IMAGE_DOS_HEADER의 e_lfanew 멤버와 IMAGE_FILE_HEADER의 SizeOfOptionalHeader 멤버 때문에 일반적인(상식적인) PE 파일 형식을 벗어나는 일명 '꽈배기' PE파일(PE Patch)을 만드는 것이 가능하다.)
#4. Characteristics
파일의 속성을 나타내는 값으로써, 실행이 가능한 형태인지(executable or not) 혹은 DLL 파일인지 등의 정보들이 bit OR 형식으로 조합된다.
아래는 winnt.h 파일에 정의된 Characteristics 값들이다. (0002h 와 2000h 의 값을 기억해 두자.)
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable // (i.e. no unresolved externel 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 // Agressively 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. |
(PE 파일중에 Characteristics 값에 0002h 가 없는 경우(not executable)가 있을까?
그렇다. 예를 들어 *.obj 와 같은 object 파일이 그런 경우이고, resource DLL 같은 파일이 그런 경우 이다.)
마지막으로 IMAGE_FILE_HAEDER의 TimeDateStamp 멤버에 대해서 알아보자.
이 값은 파일의 실행에 영향을 미치지 않는 값으로써 해당 파일의 빌드 시간을 나타낸 값이다.
단, 개발 도구에 따라서 이 값을 세팅해주는 도구(VB, VC++)가 있고, 그렇지 않은 도구(Delphi)도 있다.
(또한 개발 도구의 옵션에 따라서 달라질 수 있다.)
이제 실제로 notepad.exe 의 IMAGE_FILE_HEADER를 확인해 보자.
이를 알아보기 쉽게 구조체 멤버로 표현하면 다음과 같다.
[ IMAGE_FILE_HEADER ] - notepad.exe
offset value description ------------------------------------------------------------ 000000E4 014C machine 000000E6 0003 number of sections 000000E8 48025287 time date stamp (Mon Apr 14 03:35:51 2008) 000000EC 00000000 offset to symbol table 000000F0 00000000 number of symbols 000000F4 00E0 size of optional header 000000F6 010F characteristics IMAGE_FILE_RELOCS_STRIPPED IMAGE_FILE_EXECUTABLE_IMAGE IMAGE_FILE_LINE_NUMS_STRIPPED IMAGE_FILE_LOCAL_SYMS_STRIPPED IMAGE_FILE_32BIT_MACHINE |
'정상을향해 > Program Analysis' 카테고리의 다른 글
Python Hacking Programming (2) (0) | 2013.11.10 |
---|---|
Python Hacking Programming (1) (0) | 2013.11.10 |
PE File Format (4) (0) | 2013.11.10 |
PE File Format (2) (0) | 2013.11.10 |
PE File Format (1) (0) | 2013.11.10 |
Calling Convention (0) | 2013.11.10 |