NT header
NT header 구조체 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 구조체 입니다.
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 별로 고유한 값이며 32 bit 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) 이 만들 수 있습니다.
(나중에 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_HEADER 의 구조를 이해하는데 부족함이 없을 것입니다.
마지막으로 IMAGE_FILE_HAEDER 의 TimeDateStamp 멤버에 대해서 설명드리겠습니다.
이 값은 파일의 실행에 영향을 미치지 않는 값으로써 해당 파일의 빌드 시간을 나타낸 값입니다.
단, 개발 도구에 따라서 이 값을 세팅해주는 도구(VB, VC++)가 있고, 그렇지 않은 도구(Delphi)가 있습니다.
(또한 개발 도구의 옵션에 따라서 달라질 수 있습니다.)
이제 실제로 notepad.exe 의 IMAGE_FILE_HEADER 를 확인해 보겠습니다.
위 그림은 hex editor 로 봤을때의 그림이고, 이를 알아보기 쉽게 구조체 멤버로 표현하면 아래와 같습니다.
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
다음에는 NT header 의 세번째 멤버인 IMAGE_OPTIONAL_HEADER32 에 대해서 알아보겠습니다.
(continue)
'study' 카테고리의 다른 글
DLL Injection - 다른 프로세스에 침투하기 (3) (10) | 2009.07.17 |
---|---|
DLL Injection - 다른 프로세스에 침투하기 (2) (117) | 2009.07.17 |
DLL Injection - 다른 프로세스에 침투하기 (1) (17) | 2009.07.06 |
PE(Portable Executable) File Format (8) - PE Header (16) | 2009.04.22 |
PE(Portable Executable) File Format (7) - PE Header (42) | 2009.04.18 |
PE(Portable Executable) File Format (6) - PE Header (62) | 2009.04.06 |
PE(Portable Executable) File Format (5) - PE Header (31) | 2009.04.03 |
PE(Portable Executable) File Format (4) - PE Header (25) | 2009.03.31 |
PE(Portable Executable) File Format (3) - PE Header (18) | 2009.03.29 |
PE(Portable Executable) File Format (2) - PE Header (31) | 2009.03.28 |
PE(Portable Executable) File Format (1) - PE Header (56) | 2009.03.23 |
-
-
Ezbeat 2009.12.22 15:42
시간날 때마다 조금씩 잘 읽어보고 있습니다 ^^
음.. 잘못 표기한 부분이 있으신거 같네요;;
IMAGE_FILE_HEADER부분을 설명 하신 후
실제로 notepad.exe의 IMAGE_FILE_HEADER를 확인해 주신다고 하셨을 때
IMAGE_FILE_HEADER부분이 아닌 IMAGE_NT_HEADERS멤버인 Signature변수가
그림에 포함이 되어 있네요 ^^;;(4Byte) -
-
Acaicat 2010.08.12 00:03
Charateristics에 관해 궁금한게 있는데요.
그 0x0002와 0x2000을 기억해 두라고 하셨는데,
아래 hex를 보면 0x010F인데 이것은 어떻게 봐야하나요?
제 컴에서 켰을 때는 0x0102가 나와서
winnt.h를 열어서 봤는데 이런 것 정의 에 없더라구요.
혹시나 해서 win32 콘솔로 컴파일된 실행 파일을 넣어 봤는데 0x0102가 나오더라구요.
이건 또 어떻게 봐야하는지 궁금합니다. -
db_click 2011.01.17 16:49
안녕하세요!
눈팅만 하다가,
궁금한게 생겼는데,
검색 능력이 턱없이 부족한지라..
질문 해도 되나요..ㅎㅎ
* TimeDateStamp 값 해석
노트패드를 PEView로 확인해 보니
TimeDateStamp에 저장되는 값이
0x47918EA2 가 나오던데요,
이 값이 2008/01/19, 05:46:10 UTC 로
풀어져있더라구요.
어떻게 하면, 이렇게 해석이 될까요..-
reversecore 2011.01.19 23:55 신고
안녕하세요.
C 언어 라이브러리 함수 ctime() 을 사용하면 그런 문자열을 만들어 낼 수 있습니다.
감사합니다.
-
-
TeamKhan 2011.04.01 17:59
IMAGE_NT_HEADERS 구조체의 크기는 F8h 이란걸 어떻게 파악하신건가요 ?
그리고 어떻게 실제로
hex editor 부분에서
이부분까지가 IMAGE_FILE_HEADER 인걸
파악하셧나요 ?-
reversecore 2011.04.06 01:07 신고
안녕하세요.
C 언어의 구조체는 크기가 정해져 있으니 자연히 그 크기를 알 수 있구요. sizeof(IMAGE_NT_HEADERS) 연산자를 써도 알 수 있지요.
그리고 구조체의 내부 구조를 훤히 알고 있으니 IMAGE_NT_HEADERS 구조체 시작부터 4 byte 이후가 IMAGE_FILE_HEADER 인걸 아는 거지요. ^^
감사합니다.
-
-
강한이 2011.05.26 23:39
위에 마지막 케릭터리스틱스에 010F로 되어있는데 원래 핵스는 뒤에서 읽어와서 그런건지 알겠고
그밑에 부가적인 값들은 어떻게 계산하는건가요? 보니까 뒤에 읽어보니 OR명령어도 되있다고하는데 추가설명이 없네요.
그리고 타임스템프는 어떻게 변환해야하는거죠?
48025287-> Mon Apr 14 03:35:51 2008
답변 부탁드려요-
reversecore 2011.06.03 22:18 신고
안녕하세요.
Zero 님께서 답변을 잘 해주셨네요~ 감사합니다. ^^
참고로 VC++, SDK 를 설치하신 후 winnt.h 파일에 보시면 저 값의 정의가 나와 있습니다.
#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_32BIT_MACHINE 0x0100 // 32 bit word machine.
감사합니다.
-
bp 2012.11.30 16:42
안녕하세요.
characteristics에서 add 연산을 사용할 수는 없을까요?
or 연산을 사용하는 특별한 이유가 있나요?-
reversecore 2012.12.02 19:00 신고
안녕하세요.
좋은 질문이네요~
Characteristics 는 각 bit 별로 의미를 가지는 형태입니다. 이러한 형태는 C언어의 강력한 bit 단위 처리 능력을 활용할 수 있기 때문에 관례적으로 OR 명령으로 처리되고 있습니다.
말씀하신대로 ADD 로도 됩니다만, 의미를 부여하기 위해 (그 bit 를 ON 시킨다.) OR 를 쓰게되면 프로그래머들끼리 의사 전달이 명확하게 되지요. "아~ bit 처리를 이용한 FLAG 사용법이군~" 하고 말이죠. ^^
감사합니다.
-