티스토리 뷰
PE(Portable Executable) #03 - PE Header | NT - OPTIONAL_HEADER
live2skull 2016. 8. 10. 16:25NT_HEADER -> IMAGE_OPTIONAL_HEADER (x86)
이 헤더의 경우 컴파일된 시스템의 아키텍쳐에 따라 구조체의 내용과 크기가 조금씩 달라지므로,
가장 범용적인 x86 (32비트) 의 헤더에 대해서만 살펴본다.
이 구조체 역시 "winnt.h" 파일에 정의되어 있다.
!! RVA / VA : 다음 포스트에 설명. - 여기서는 해당 데이터 섹션에 대한 설명만 기록한다.
typedef struct _IMAGE_OPTIONAL_HEADER { // Standard fields. - Microsoft comment WORD Magic; BYTE MajorLinkerVersion; // file version BYTE MinorLinkerVersion; // file version DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData;
// NT additional fields. - Microsoft comment DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; //ver WORD MinorOperatingSystemVersion; //ver WORD MajorImageVersion; //ver WORD MinorImageVersion; //ver WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; // not used WORD Subsystem; WORD DllCharacteristics; // ASLR / NX setup DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; // DEPRECATED! DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
2. AddressOfEntryPoint (RVA)
프로그램이 메모리에 적제되고 난 후, 가장 먼저 실행되어야 할 주소이다.
다시 말해, 프로그램이 메모리에 적제 완료되면, EIP를 ImageBase(VA) + AddressOfEntryPoint(RVA)로 잡아준 후 실행 흐름을 이어간다.
3. ImageBase
프로그램이 메모리에 적제되기 위한 시작 주소이다.
AddressOfEntryPoint나 다른 Section의 주소는 모두 RVA 로 되어 있는데, 이는 나중에 ImageBase+RVA의 형태로 메모리에 접근하게 된다.
이 ImageBase는 참고용으로, PE Loader 가 파일을 읽으면서 해당 주소에 섹션을 넣을 수 있는 공간이 남아 있다면 이 주소대로 Virtual Address 에 데이터를 할당해 준다.
만약 이 주소가 이미 사용중이라면 (예를 들어, exe가 실행되었고 dll 를 로드하는 상황에서), 해당 주소를 무시하고 PE Loader가 적당한 주소를 찾아 데이터를 할당한다.
이는 시스템이 ASLR 을 지원할 경우, ImageBase를 무시하고 랜덤한 ImageBase를 정하기도 한다.
+ EXE, DLL Files : 0x00000000 ~ 0x7FFFFFFFF (User memory region)
+ SYS Files : 0x80000000 ~ 0xFFFFFFFF (Kernel memory region)
4. SectionAlignment
[!] 내용 보완이 필요함
섹션이 메모리에 로드될때, 한 섹션이 끝나면 바로 다음 섹션이 메모리에 이어붙는 것이 아닌, 일정한 간격을 두고 붙게 한다.
즉, 어떠한 섹션이라도 무조건 섹션의 처음 메모리 주소는(VA) SectionAlignment * n 이 되게 되고, 두 섹션 간의 빈 공간은 null padding으로 채우게 된다.
이는 컴퓨터 시스템의 아키텍쳐와 관련되어, 일정 간격(4바이트?) 로 메모리 주소가 끊어져야 퍼포먼스를 좀 더 빠르게 할 수 있다고 한다.
5. FileAlignment
파일(메모리에 올라가지 않은, 디스크에 저장된 상태)에 기록되어있는 섹션 데이터들의 최소 간격(SectionAlignment와 비슷함)
6. SizeOfImage
메모리 상에 로드된 PE파일의 총 바이트 크기. (SectionAlignment * n)
일반적으로, 메모리에 PE 파일이 로딩되게 되면 디스크에 위치한 PE파일과는 그 크기가 달라지게 된다.
7. SizeOfHeaders
디스크 상에서의 헤더의 총 바이트 크기. (FileAlignment * n)
파일 시작점(0x00) 에서 SizeOfHeaders 떨어진 만큼의 구간에 첫번째 섹션이 위치하게 된다. (Absolute Pointer)
주의해야 할 점은, SizeOfHeaders 값은 Dos 헤더와 Dos Stub 코드, 그리고 나머지 모든 데이터를 포함한 값이라는 것이다.
실제로 확인해보면 첫번째 섹션의 파일 오프셋과 본 값과 위치가 같음을 확인할 수 있다.
8. Subsystem
Driver file, GUI, CUI Application 을 구분할 때 사용된다.
9. DllCharacteristics
시스템 보호 기능인 ASLR / NX 및 기타 기능의 FLAG 옵션을 bit OR 형태로 저장한다.
10. NumberOfRvaAndSizes
[!] 내용 보완이 필요함
DataDirectory 배열의 갯수. 단, DataDirectory 구조체 배열은 옵션이므로 존재할 수 도, 존재하지 않을 수 도 있으며, 없을경우 0,
있을경우 무조건 16개 (0x10)개 값을 가지게 된다.
11. DataDirectory
>> IMPORT / EXPORT 테이블 등에 대한 정보를 가지고 있으며, 옵션이므로 존재할 수 도, 존재하지 않을 수 도 있다.
[!] 이 내용은 나중에 다른 포스트에서 상세히 정리한다.
'System > Windows' 카테고리의 다른 글
PE(Portable Executable) #06 - PE Header | IAT / IMPORT_DESCRIPTOR (0) | 2016.08.10 |
---|---|
PE(Portable Executable) #05 - PE Header | NT - SECTION_HEADER (0) | 2016.08.10 |
PE(Portable Executable) #04 - Virtual Address | FILE OFFSET (0) | 2016.08.10 |
PE(Portable Executable) #02 - PE Header | NT - FILE_HEADER (0) | 2016.08.09 |
PE(Portable Executable) #01 - PE Header | DOS (0) | 2016.08.09 |