티스토리 뷰

NT_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;

1. Magic
시스템의 타깃 CPU 값을 가지고 있다.
x86 시스템의 경우 0x10b, x64 시스템의 경우 0x20b 값을 가진다.


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 테이블 등에 대한 정보를 가지고 있으며, 옵션이므로 존재할 수 도, 존재하지 않을 수 도 있다.

[!] 이 내용은 나중에 다른 포스트에서 상세히 정리한다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함