티스토리 뷰
[Reversing] IMAGE_NT_HEADER
- IMAGE_NT_HEADER
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
위 그림은 IMAGE_NT_HEADER 구조체입니다. 해당 구조체는 4byte 크기의 Signature 그리고 IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER32이 있습니다.
1.1 Signature
가장 먼저 Signature입니다.
IMAGE_NT_HEADER 구조체의 시작부분인 Signature는 실행파일이 시작하는 부분입니다.
헥사코드로는 '0x50450000'라는 값이 들어있습니다. 'PE\0\0'입니다.
1.2 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.2.1. Machine
먼저 가장 처음에 자리잡은 Machine 필드입니다.
https://docs.microsoft.com/ko-kr/windows/desktop/api/winnt/ns-winnt-_image_file_header
위 링크에서 보듯 Machine 필드의 값에 따른 의미를 설명하고 있습니다.
0x014c |
인텔 아키텍쳐 32비트 환경에서 동작한다는 의미입니다. |
0x0200 |
인텔 아키텍쳐 64비트 환경에서 동작하다는 의미입니다. |
0x8664 |
|
해당 필드는 리틀인디언 방식으로 데이터가 쓰이며, 64비트 환경에서 동작하는 실행파일이라는 것을 알 수 있습니다.
1.2.2. NumberOfSections
NumberOfSections 해당 필드는 해당 파일이 가지고 있는 섹션의 수를 나타냅니다.
해당 필드 역시 리틀 인디언 방식으로 저장되는 값입니다.
1.2.3. SizeOptionalHeader
IMAGE_OPTIONAL_HEADER 구조체의 크기에 대한 정보를 가지고 있습니다.
IMAGE_OPTIONAL_HEADER 구조체의 크기는 '0x00E0' = 224byte 크기를 갖는 걸 확인 할 수 있습니다.
1.2.4. Characteristics
각 특성별로 부여된 헥사코드가 있습니다
0x0001 |
파일에 대한 재배치 정보가 없으므로, 기본 주소에 로드 되어야한다는 의미입니다. |
0x0002 |
확인되지 않은 외부참조가 없고, 파일이 실행가능하다는 의미입니다. |
0x0004 |
COFF 라인 번호가 파일에서 삭제되었다는 의미입니다. |
0x0008 |
COFF 라인 번호가 파일에서 삭제되었다는 의미입니다. |
0x0010 |
적극적으로 워킹 셋을 정리해야한다는 의미입니다 |
0x0020 |
응용 프로그램이 2GB보다 큰 주소를 처리할 수 있다는 의미입니다. |
0x0080 |
단어의 바이트가 반대로 되어있다는 의미입니다. |
0x0100 |
32비트 단어를 지원한다는 의미입니다. |
0x0200 |
디버깅 정보가 해당 파일에 없고 다른 파일에 저장되어있다는 의미입니다. |
0x0400 |
파일이 이동식 미디어에 있는경우, 그것을 복사하여 스왑파일에서 실행한다는 의미입니다. |
0x0800 |
파일이 네트워크상에 있는 경우, 그것을 복사하여 스왑파일에서 실행한다는 의미입니다. |
0x1000 |
파일이 시스템 파일임을 의미합니다. |
0x2000 |
파일이 DLL 파일이며, 이것이 실행파일이지만 직접 실행할 수는 없다는 의미입니다. |
0x4000 |
파일이 단일 프로세서 컴퓨터에서만 실행되어야 한다는 의미입니다. |
0x8000 |
단어의 바이트가 반대로 되어있다는 의미입니다. |
파일의 특성에 따라 해당하는 헥사코드들을 더한 값을 Characteristics 필드에 저장합니다.
1.3 IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER {WORD Magic;BYTE MajorLinkerVersion;BYTE 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_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
바로 이어서 중요한 필드들에 대해서 알아보겠습니다.
1.3.1 Magic
이전의 IMAGE_DOS_HEADER 구조체에서 e_magic이라는 필드와 같이 IMAGE_OPTIONAL_HEADER의 Magic 필드 역시 해당 구조체의 시작을 알려주는 특정 값으로 고정이 되어있습니다.
32비트 |
0x10B |
64비트 |
0x20B |
헥사에디터에서는 리틀인디언 방식으로 확인 할 수 있습니다.
1.3.2 AddressOfEntrypoint
해당 필드는 EP 즉, EntryPoint라고 하는 주소값을 가지고 있습니다.
EntryPoint의 RVA 값이 저장되어 있습니다.
EntryPoint란 로더에 의해 PE파일이 로딩되고나서 가장 먼저 시작되는 소스코드의 시작점입니다.(제일 먼저 시작되는 소스코드의 시작점)
PEiD와 같은 툴을 통해 확인 해보겠습니다.
위 그림은 PEiD를 이용하여 notepad.exe를 확인하였습니다.
확인 시 AddressOfEntrypoint 필드에 저장되어 있던 값과 동일한 값이 표시되어 있을 것 입니다.
1.3.3 ImageBase
이 ImageBase 필드에 저장되어 있는 값은 PE파일이 로드되는 위치 입니다.
해당 값이 링커에 의해서 설정이 되며, 일반적으로 0x00400000 입니다.
하지만, DLL 파일의 경우에는 일반적으로 해당 값이 0x10000000 입니다.
이 값들은 절대적인 값들이 아니라고 합니다. 일반적인 값이지..
파일을 실행하게 되면 프로세스의 어디엔 존재하는 가상 메모리 주소 공간에 올라갑니다.(mapping)
이 과정을 통해 가상 메모리 주소 공간에 자리를 잡는데 그게 ImageBase를 가르킵니다.
즉, 시작주소를 알려주는 부분입니다
다음으로 VA(실제 메모리에 로딩되는 주소)를 구하고자 한다면 Image Base주소와 RVA주소를 더하면 됩니다.
1.3.4 SectionAlignment
섹션이라는 것은 실제 프로그램을 구성하는 코드 내에서 선언하는 전역변수나 static변수 등을 담고 있는 것 입니다.
그러면 Alignment란?
얼라이먼트라는 작업은 '일정하게 정렬한다'는 것을 의미합니다.
그러면 SectionAlignment는 뭘까요?
SectionAlignment는 메모리 상에서 섹션을 정렬하는 단위라고 합니다.
PEView를 통해 SectionAlignment 필드의 값을 보면 0x00001000 입니다. (4096byte)
즉, 이값을 기준으로 섹션들이 정렬된다는 것입니다.
예를 들어 .text 섹션(512byte)과 .data 섹션(5632byte)이 연속되어 나열된 섹션이라고 할때,
.text 섹션의 데이터의 크기가 작아 빈공간이 생기더라도 섹션의 절대 단위인 4096byte를 할당합니다. .text 섹션시 끝나고 3584byte 빈공간이 지나고 나서야 .data 섹션이 시작합니다.
그럼 .data는 총 8192byte를 할당 받겠죠?
이런 섹션의 단위를 설정하는 필드가 SectionAlignment 필드 입니다.
1.3.5 FileAlignment
FileAlignment 필드 역시 절대 단위를 설정하는 값을 저장하는 필드입니다.
하지만 SectionAlignment 필드는 메모리상에서의 섹션 단위를 설정하였고, FileAlignment 필드는 디스크 상에서 섹션 절대 단위를 설정합니다.
Peview를 통해 확인해보세요
SectionAlignment 필드 값과 같다면 디스크 상에서와 메모리 상에서의 PE 파일의 모습이 같다고 생각하시면 됩니다.
1.3.6 SizeOfImage
SizeOfImage 필드는 메모리 상에 로그된 PE 파일의 전체 크기입니다.(SectionAlignment 필드 섹션의 절대 단위의 배수)
1.3.7 SizeOfHeader
SizeOfHeader 필드는 PE 헤더의 크기값을 저장합니다.
400h 부터 첫번째 섹션이 시작한다는 걸 확인 할 수 있습니다.
다음을 확인 해보면 400h 앞까지는 빈공간입니다. 이것은 위에서 설명한 Alignment에서의 절대 단위와 같은 개념이라 생각하시면 됩니다.
1.3.8 Subsystem
해당 필드는 GUI 기반인지 드라이버 파일인지 등의 설정값을 가지고 있습니다.
0x01 |
.sys 확장자를 갖는 드라이버 파일 |
0x02 |
GUI 기반 |
0x03 |
CLI 기반 |
'Reversing > ETC' 카테고리의 다른 글
[Reversing] IMAGE_SECTION_HEADER (0) | 2019.02.12 |
---|---|
[Reversing] PE 포맷(Portable Executable) (0) | 2019.02.12 |
[Reversing] IMAGE_DOS_HEADER (0) | 2019.02.08 |
[Reversing] PE 파일 구조 찾기 (0) | 2019.01.31 |
[Reversing] PE 파일 구조 (0) | 2019.01.30 |
- Total
- Today