본문 바로가기

High Level Technique/Reversing

NT Header - IMAGE_OPTIONAL_HEADER













-Magic

 IMAGE_OPTIONAL_HEADER32인지 64인지를 구별하기 위한 값으로 32bit0x10B, 64bit0x20B를 가집니다.

 



MajorLinkerVersion, MinorLinkerVersion

 어떤 버전의 컴파일러로 빌드했는지 알 수 있다.

 



SizeOfCode

 코드 양의 전체크기를 나타내며, 보통 .text Section의 파일 크기를 나타냅니다 .text SectionSizeOfRawData같은 값을 갖는다

 바이러스나 악성코드는 이 영역을 읽어 코드를 복제할 위치를 잡기도하고 보안 솔루션에서는 무결성 검사를 수행할 때 이 섹션 값을 얻어와 검사크기를 잡는다.

 



AddressOfEntryPoint

실제 파일이 메모리에 실행되는 시작지점이며 EP(Entry Point)를 말한다.


이 값은 RVA로 표시되며, ImageBase+AddressOfEntryPoint 값을 EIP 레지스터에 넣어 프로그램이 시작된다.


이 때 RVA는 프로그램의 main의 위치라 생각하면 된다. 주의할 점은 모든 프로그램은 실행을 준비하기 위해 Start Up 코드를 실행하게 되므로 가장 먼저 시작되는 코드의 위치가 이 RVA가 아니라는 것이다.


추가적으로 언패킹 할 때 OEP(Original Entry Point)를 찾아야 한다고 하는데 그 때 말하는 곳이 바로 이 곳이다.




BaseOfCode

코드영역의 시작주소이며 RVA 값이다.

 



-BaseOfData

데이터 영역의 시작주소이며 읽고 쓰기가 가능한 경우가 많고 RVA 값이다.

 



ImageBase

메모리 내에 파일이 로딩되는 시작주소이다. ImageBase0x40000이고 BaseOfCode0x1000이면 코드의 시작주소0x401000이 된다. , 메모리에 올려진 후에 코드의 시작주소는 

ImageBase + BaseOfCode이다.


이처럼 RVA 값에 ImageBase를 더해주는 것이 바로 RVA를 실제가상 주소로 변환하는 방법이다.


주의할 점은 헥스 에디터로 분석 할 때 RVA로 계산하면 안 되고 BaseOfCode가 가지고 있는 값 그대로 이동해야한다.




SectionAlignment

메모리에서 섹션의 최소단위를 나타내는 값이다. , 섹션을 정렬하기 위한 저장단위이며 보통 0x1000이다.


섹션의 크기는 SectionAlignmnet의 배수로 되어야 하며 남은 바이트는 NULL로 채워진다.


SectionAlignmnet의 배수가 되어야 한다는 말은 .text Section의 크기가 0x800이라고 한다면 0x800이후에 .rdata Section이 오는 것이 아니라 0x1000단위이기 때문에 0x200NULL로 채워진 후 .rdata Section이 온다.


Section Header에는 각 헤더가 어디에 위치할지에 대한 정보가 2가지가 있다. 메모리상에 올라갈 주소와 파일 상에 올라갈 주소이다. Section Header .text를 예를 들면 RVA0x1000이고 PTRD0x400이다.

 


PE 로더는 Section Header의 정보를 참고해서 Section .text를 메모리 주소 어디엔가 올려야한다. ImageBase가 0x400000이라고 한다면 Section .textRVA값을 더한 0x401000에 올라가게 된다. 파일 상에는 0x400의 위치에 올라가게 된다. 따라서 파일 상태로 분석할 때 PTRD 값만 참조해 주소로 이동하면 된다.













FileAlignment

SectionAlignmnet와 같은 개념이지만 똑같지만 그 기준이 PTRD에 영향을 준다는 것만 다르다. 파일상의 위치간격이다.

 




SizeOfImage

EXE, DLL이 메모리에 로딩 되었을 때의 전체크기이다. 메모리에 올라갈 때 SizeOfImage 값을 보고 공간을 확보한다.

이때 파일에서와 메모리에서 올라갔을 때의 크기가 다르게 되는데 이 이유는 SectionAlignmnet에서 할당된 공간까지 포함되기 때문에 메모리상에 올라가는 크기가 더 크게 된다. 이와 같은 이유로 SizeOfImageSectionAlignment의 배수가 된다.

 




SizeOfHeaders

파일에서의 PE Header(Dos Header, Dos Stub, Section Header)의 전체크기를 나타낸다.

 




Subsystem

프로그램이 구동하는 기반 환경을 나타낸 값이다. 쉽게 생각하면 콘솔인지 GUI인지 알려주는 값이다.




NumberOfRvaAndSizes

DataDirectory 배열의 개수를 표시한다. winnt.h0x10으로 정의되어 있지만, 실제로 이 값을 참조한다.