'Optional Header'에 해당되는 글 1건

  1. 2008.12.05 [PE 구조] Optional Header

앞에서 살펴본 FILE HEADER에 이어서 이번에는 Optional Header에 대해서 알아보자.

 

Optional Header는 좀 길어서 2개로 나누어 볼까 한다.

data directory와 그 앞부분으로 말이다.

 

Optional Header의 크기는 앞에서 살펴본 File Header의 SizeOfOptionalHeader 필드에 정의 되어 있다.

 

그럼 1차 분석을 시작해보자.!

 

=========================================================================================

 

우선 WinNT.h에 정의된 구조체를 봐보자 ^__^

 

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    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;

아고 길다.. ^^;;

 

Optional Header는 3부분으로 쪼갤 수 있다.

Standard fields와 Nt additional fields, 그리고 DataDirectory이다.

 

우선 Standard fields 부분의 필드들을 살펴보자.

Standard fields는 실행에 필요한 정보들을 가지고 있다.

차근차근 하나 씩 짚어보자.

Magic : 이미지 파일의 타입을 명시한다. 기본적인 PE 파일이라면 0x10B의 값을 가진다.

            PE32+ 포맷이라면 0x20B의 값이고, 롬 이미지일 경우 0x107의 값을 가진다.

MajorLinkerVersion

MinorLinkerVersion : 링커의 버전을 알려준다.

SizeOfCode : Code 섹션의 크기를 명시한다.

SizeOfInitializedData : 초기화된 데이터 섹션의 크기를 명시한다.

SizeOfUninitializedData : 초기화되지 않은 데이터 섹션의 크기를 명시한다.

AddressOfEntryPoint : 파일이 메모리에 로드된 후 엔트리 포인트 주소를 명시한다.

                                이 주소 값은 base address부터의 RVA이다.

 

* RVA는 Relative Virture Address의 약자로 어떤 기준점으로부터의 오프셋을 기준으로 하는 주소이다. VA와는 다른다.

 

BaseOfCode : Code 섹션의 시작 오프셋을 명시한다.

BaseOfCode : Data 섹션의 시작 오프셋을 명시한다.

여기까지가 Standard fields에 해당하는 부분이다. 음. AddressOfEntryPoint 필드 값은 쓸만할 거 같기도 하지만 실제로 사용해볼 용도가 없었기 때문에 잘 모르겠다 ^^;

 

다음은 NT additional fields를 알아보자.

ImageBase : 로드되었을 때 파일의 base address를 명시한다.

                  기본적으로 0x00400000의 값을 가지고, DLL의 경우 0x10000000의 값을 가진다.

                  이 주소를 사용하지 못 할 경우 File Header의 Chararicteristic 필드 값에 따라

                  행동이 달라진다. 하지만 기본적으로 Windows는 VA이기 때문에 정상적으로

                  로드될 것이다.

SectionAlignment : 메모리에 로드되었을 때 섹션의 정렬 값이다.

                           바이트 단위로 명시된다. 기본적으로 이 값은 Page 값과 같다.

                           FileAlignment 값보다는 크거나 같아야 한다. 일반적으로는 같다.

FileAlignment : 파일이 하드 드라이버에 저장될 때 쪼개지는 기본 단위이다.

                    SectionAlignment와 마찬가지로 바이트 단위로 명시된다.

                     기본 값은 512이지만 512에서 64K 사이의 수 중 2의 배수를 가질 수 있다.

MajorOperatingSystemVersion

MinorOperatingSystemVersion : 필요한 OS의 버전 정보를 명시한다.

MajorImageVersion

MinorImageVersion : 이미지의 버전을 명시한다.

                             사용자가 /VERSION 옵션으로 임의로 지정할 수 있다.

MajorSubsystemVersion

MinorSubsystemVersion : 사용하는 서브시스템의 버전을 명시한다.

Win32VersionValue : VC++ 6.0까지는 예약된 공간이였으며 7.0에 와서 필드명이 개조되었다.

                              하지만 여전히 사용되지 않는 것 같다.

SizeOfImage : 이미지의 크기로써 로드될 때 확보해야 할 메모리 공간의 크기이기도 하다.

                    파일의 실제 크기와 같을 수도 있지만 SectionAlignment 값에 따라 커지기도

                   한다.

SizeOfHeader : MS-DOS 스텁, PE 헤더(시그니처, File Header, Optional Header),

                     섹션 헤더의 크기를 합친 값으로 FileAlignment 필드 값의 배수이다.

CheckSum : 이미지가 로드되면서 검사할 때 사용하는 값이다.

                  무결성을 검사한다.

Subsystem : 사용하는 서브시스템을 명시한다.

                   기본적으로 가장 많이 명시되는 것이 1, 2, 3이다.

                   1은 IMAGE_SUBSYSTEM_NATIVE로 드라이버처럼 따로 서브시스템을

                  사용하지 않는 경우 사용한다.

                    2는 IMAGE_SUBSYSTEM_WINDOWS_GUI로 Windows 그래픽 환경(GUI)을

                   사용한다.

                    3은 IMAGE_SUBSYSTEM_WINDOWS_CUI로 Windows의 콘솔 환경(CUI)를

                   사용한다.

                    그 외 더 자세한 내용은 WinNT.h를 참조하여라.

DLL Characteristics : 몇 개 안되서 정리는 하지만 이해가 안되는 부분이 있다.

                               조금 더 공부를 해보아야 할 거 같다.

                               파일이 DLL일 경우에 지정된다.

                               IMAGE_DLLCHARACTERISTICS_NO_BIND

                                 -> 로드되었을 때 바인딩하지 않는다. <- 무슨 의미인지 잘..

                               IMAGE_DLLCHARACTERISTICS_WDM_DRIVER

                                 -> 드라이버가 WDM 형식을 따랐음을 명시한다.

                               IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE

                                 -> 터미널 서버가 이미지를 인식할 수 있다.

                                    즉, 터미널 어플리케이션이 알 수 없는 이미지를 서버가 실행

                                    할 수 있도록 실행에 필요한 파일들을 같이 로드 한다.

LoaderFlags : 현재 사용되지 않는 필드이다.

NumberOfRvaAndSize : DataDirectory의 개수를 명시한다.

                                  16으로 고정되었다고 할 수 있다.

여기까지가 NT additional fields라고 볼 수 있다.

이 분에서 필요한 정보라고 한다면 ImageBase정도가 되겠다.

정보를 명시할 뿐 뭔가 딱히 결정적인 역활을 하지는 않는 듯하다. ^^;;

Posted by skensita