본문 바로가기

0x00 /0x01 Reversing

- PE File Format

# PE File Format


- PE(Portable Executable) 파일의 의미를 영단어대로 해석해보면 [Portable=이식가능한, Executable=실행가능한]

  대략 이식이 가능한 실행 파일 정도로 해석이 가능합니다. 처음 PE 파일이 만들어질 때는 다른 운영체제에 이식성을

  좋게 하려했으나 의도대로 되지 않고, 실제로는 Windows 계열의 운영체제에서만 사용되고 있다고 합니다.


  다시 말해, PE File Format은 Windows 운영체제에서만 사용되는 실행 파일의 형식입니다.

  이 PE File Format은 기존 UNIX에서 사용되는 COFF(Common Object File Format)를 기반으로 Microsoft 사에서 만들었습니다.


  PE 파일은 32비트 형태의 실행 파일을 의미하며, PE32라고 불리기도 합니다. 64비트 형태의 실행 파일은 PE+ 또는 PE32+

  라고 표현하며, 이 PE+ 또는 PE32+는 32비트 형태의 실행 파일인 PE 파일의 확장 형태입니다.


  PE File에도 여러 종류가 있는데, 그 종류에 대해서 알아보도록 하겠습니다.



1. PE File 종류


- PE File의 종류에는 실행 계열, 라이브러리 계열, 드라이버 계열, 오브젝트 파일 계열로 총 4가지로 분류되어 있습니다.

- 오브젝트 파일을 제외한 모든 종류는 실행이 가능한 파일입니다. 

- PE 공식 스펙에는 컴파일 결과물인 OBJ(오브젝트) 파일도 PE 파일로 간주합니다. 하지만, OBJ 파일 자체로는 

  어떠한 형태의 실행도 불가능하므로 리버싱에서 관심을 가질 필요는 없습니다. 


 종류

주요 확장자 

실행 계열

EXE , SCR 

라이브러리 계열

DLL , OCX , CPL , DRV 

드라이버 계열 

SYS , VXD 

오브젝트 파일  

OBJ 



간단하게 PE File의 종류에 대해서 알아보았습니다. 그럼 지금부터 PE File의 기본 구조에 대해서 알아보도록 하겠습니다.





2. PE File 기본 구조




- PE File의 기본 구조는 PE 헤더와 PE 바디로 구성되어져 있습니다. PE 헤더에는 DOS header와 DOS Stub, NT header 

  그리고 각 Section header 들로 구성되어 있으며, PE 바디에는 PE 헤더 부분을 제외한 모든 Section 들을 합쳐 PE 바디라고

  부릅니다


- 위 그림이 PE File의 기본 구조를 도식화하고, PE File이 Memory에 로딩되는 모습입니다.


- 왼쪽편의 File에서는 offset으로, 오른쪽편의 File이 로딩된 Memory에서는 VA(Virtual Address)로 위치를 표현합니다.


- PE File이 Memory에 로딩되면 Section의 크기나 위치등이 달라지게 됩니다. 

  (PE 파일은 디스크 상의 모습과 메모리 상의 모습은 거의 같습니다.)


- 참고로 Section의 이름, 크기, 개수, 저장 내용 등은 개발도구와 빌드 옵션에 따라서 달라집니다.


- Section header에는 각 Section에 대한 파일/메모리에서의 크기, 위치, 속성 등의 정보가 정의되어 있고,

  Section 영역에는 실제 실행 코드와 데이터 혹은 리소스와 같은 여러가지 실제적인 정보들이 Section header에서 

  명시한 위치와 크기별로 포함되어 있습니다.


- Section의 종류



# 여기까지가 기본적인 PE File의 기본 구조였습니다. 지금부터는 PE 헤더 부분을 좀 더 자세하게 알아보도록 하겠습니다.

# 앞으로 나오는 내용들을 이해하기 위해서는 VA(Virtual Address)와 RVA(Relative Virtual Address)를 알아야 하는데요. 

  간단하게 VA와 RVA가 어떤것인지 알아보도록 하겠습니다.


# VA & RVA

- VA(Virtual Address)는 프로세스 가상 메모리의 절대 주소를 의미합니다.

- RVA(Relative Virtual Address)는 어느 기준 위치(ImageBase)에서부터의 상대주소를 의미합니다.

- VA와 RVA의 관계는 다음 식과 같습니다.

  RVA + ImageBase = VA


- PE 헤더에서는 VA(절대주소)가 아닌 RVA(상대주소)를 많이 사용합니다. 그 이유는 여러개의 PE File(DLL)이 같은 위치에 로딩될 수 있기

  때문에 정상적인 엑세스가 이루어지지 않을 수 있게 됩니다. 사실 이렇게 같은 위치에 로딩이 되게 될 경우 재배치(Relocation) 과정을 통해

  비어 있는 위치로 PE File(DLL)을 로딩시키게 됩니다. VA(절대주소)를 사용한다고 가정하면, 재배치 과정을 통해 위치가 변하게 되면 VA도

  변해야 정상적인 엑세스가 될 것 입니다. 반면에 RVA(상대주소)인 경우에는 재배치 과정을 통하더라도 기준위치에 대한 상대주소는 변함없

  기 때문에 아무 문제 없이 엑세스할 수 있습니다. 이것이 VA가 아닌 RVA를 사용하는 이유입니다.







3. PE 헤더


- PE 헤더에는 크게 DOS header, DOS stub, NT header, Section header들로 구성되어 있습니다. 그리고 많은 구성 요소들이 구조체로 이루어져 

  있습니다. 지금부터 각 구성요소들에 대해서 하나씩 살펴보도록 하겠습니다.




3.1. DOS Header


- 첫 번째로 살펴볼 부분은 DOS Header의 IMAGE_DOS_HEADER 구조체 입니다. PE File에서 제일 앞부분에 위치하고 있는 구조체로 DOS 파일에 대한  호환을 

  위한 DOS 실행 이미지입니다. (기존 DOS EXE Header를 확장시킨 IMAGE_DOS_HEADER 구조체)



[ 출처 : http://ko.wikipedia.org/wiki/MZ_%EC%8B%A4%ED%96%89_%ED%8C%8C%EC%9D%BC ]



- IMAGE_DOS_HEADER의 구조체입니다. 많은 구조체 멤버를 가지고 있지만, 모든 멤버들을 다 알아야 할 필요는 없습니다. IMAGE_DOS_HEADER 

  구조체에서 꼭 알아야할 중요한 멤버는 e_magic과 e_lfanew 멤버입니다.


e_magic : DOS signature (4D5A => ASCII 값 "MZ") - 2Byte

e_lfanew : NT Header의 옵셋을 표시 (파일에 따라 가변적인 값을 가짐) - 4Byte


- 모든 PE 파일의 e_magic에는 DOS signature ("MZ")가 존재하며, e_lfanew 값이 가리키는 위치에 NT Header 구조체가 존재합니다.

- IMAGE_DOS_HEADER 구조체의 크기는 64Byte (0x40) 입니다.

  ( DOS signature "MZ"는 DOS 실행 파일을 설계한 마크 주비코브스키라는 사람의 영문 이니셜입니다 )




- Calc.exe(계산기)를 헥사 에디터로 열어본 모습입니다. Calc.exe 파일의 DOS Header 부분이며, 구조체의 첫 2Byte는 File Signature 값으로

  DOS Signature 인 "4D5A(MZ)" 값임을 확인할 수 있습니다. Calc.exe 역시 PE 파일이기 때문입니다. 그리고 DOS Header의 가장 마지막에

  위치하는 e_lfanew 멤버 값을 확인해보면 "000000D8" 임을 확인할 수 있습니다. 000000D8 주소에 NT Header가 존재하겠네요.

  ( 참고로 Intel 계열 CPU는 데이터를 역순으로 저장하는 리틀 엔디언 방식을 이용하여 메모리에 데이터를 저장합니다. )


- 000000D8 주소에 NT Header가 정말 존재하는지 PEview를 이용하여 확인해 보도록 하겠습니다.



- PEview 라고 PE 파일의 구조를 한눈에 보기 쉽게 분석해주는 Tool 입니다. IMAGE_NT_HEADERS 영역을 선택하고 시작하는 주소를 확인해

  보니 앞에서 확인한 DOS_HEADER 구조체의 e_lfanew 멤버 값과 같음을 확인할 수 있습니다.


- DOS HEADER는 이정도로 마무리하고, PE 헤더의 2번째 구성 요소인 DOS Stub에 대해서 알아보도록 하겠습니다.




3.2. DOS Stub


- DOS Stub은 있는 경우도 있고, 없는 경우도 있습니다. DOS Stub의 존재 여부는 개발 도구의 지원 여부에 의해 결정됩니다. 한 마디로 옵션이며,

  VB, VC++, Delphi 등에서는 DOS Stub을 기본적으로 지원하고 있습니다. 그리고 DOS Stub의 크기 또한 개발 도구에 따라 다르며, DOS Stub이 없어도

  파일 실행에는 아무런 문제가 되지 않습니다. 즉, PE HEADER의 중요 요소가 아니므로 생략이 가능합니다.


- DOS Stub은 코드와 데이터의 혼합으로 이루어져 있으며, OS가 PE File 형식을 인지하지 못할 때 실행되는 부분이라고 생각하시면 되겠습니다.

- Calc.exe 파일의 DOS Stub 영역을 헥사 에디터를 이용하여 한번 보도록 하죠.






- 노란 부분 : 이 부분이 바로 DOS Stub 영역입니다. 파일 Offset (h) 40~4D 영역(DOS Stub 영역 처음부터 14Byte)은 16비트 어셈블리 명령어입니다. 

                   ( 초록 박스 ) 이 16비트 어셈블리 명령어는 32비트 Windows OS에서는 실행되지 않는 명령어입니다. DOS 환경이나 DOS용 디버거를

                   이용하여 실행했을 때, 16비트 어셈블리 명령어가 실행됩니다. 이 코드는 "This program cannot be run in DOS mode" 라는 문구를 출력

                   하고 종료하는 간단한 코드로 구성되어 있습니다. 


- 빨간 부분 : 이 부분은 바로 앞에서 이야기한 DOS Header 영역입니다. 반복해서 계속보는게 공부에 더 도움이 될 것 같아 같이 정리해 보았습니다.

                   제일 첫 부분의 2Byte는 DOS signature, DOS Header 영역의 가장 마지막 4Byte는 e_lfanew 멤버 값입니다. NT Header의 주소를 값으로

                   가지고 있다고 했었습니다. 보시는 것 처럼 NT Header의 첫 부분, IMAGE_NT_HEADERS 구조체의 첫 번째 멤버인 Signature를 가리키고

                   있습니다. 



# DOS Stub 영역에 대해서 정리해보겠습니다.

  ① DOS 환경에서 실행할 때 실행되는 코드와 데이터가 저장되어 있는 영역이다.

  ② PE Header의 중요 요소가 아니므로 생략되어도 된다. (DOS Stub이 없어도 실행엔 문제 없음)

  ③ DOS Stub 크기는 고정되어 있지 않다.

  ④ DOS Stub 영역은 옵션이다. (개발 도구에서 지원을 해주어야 함 - VB, VC++, Delphi 등은 기본으로 지원)

  



3.3. NT Header 


- 이번에는 PE Header의 세 번째 구성요소인 NT Header에 대해서 알아보도록 하겠습니다. NT Header는 IMAGE_NT_HEADERS라는 구조체를 가지고 있습니다.

  IMAGE_NT_HEADERS 구조체는 3개의 멤버로 구성되어 있습니다. 첫 번째 멤버는 Signature, 두세번째는 구조체 멤버로 FileHeader와 OptionalHeader

  있습니다. PE File의 Signature는 50450000("PE"00)의 값을 가집니다. 우선 헥사 에디터를 이용하여 Calc.exe 파일의 IMAGE_NT_HEADERS 구조체를 한번 

  보도록 하죠.



[IMAGE_NT_HEADERS 구조체의 크기는 F8(248Byte) 입니다]



- 위 그림이 Calc.exe 파일의 NT Header 부분입니다. 처음 4Byte는 첫 번째 멤버인 Signature입니다. (50450000 = "PE"00)

  그 아래에 있는 나머지가 FileHeader와 OptionalHeader인데요. 구체적으로 FileHeader의 구조체인 IMAGE_FILE_HEADER의 멤버는 어떤게 있는지, 구조체의

  크기는 얼마나 하는지, FileHeader와 OptionalHeader에 대해서 각각 알아보도록 하겠습니다.




3.3.1 NT Header - File Header 


- NT Header의 세 번째 멤버인 File Header의 IMAGE_FILE_HEADER 구조체는 파일의 개략적인 속성 정보를 가지고 있습니다.

- IMAGE_FILE_HEADER 구조체의 멤버들엔 어떤것들이 있는지 살펴보도록 합시다.



[ IMAGE_FILE_HEADER 구조체의 크기는 14(20Byte) 입니다]


[ 출처 : http://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx ]


- 위에 보이시는 것이 _IMAGE_FILE_HEADER 구조체입니다. 멤버로 Machine, NumberOfSections, ... 등 총 7개의 멤버를 가지고 있는데요. 이 중에서 중요시

  봐야할 멤버는 4가지 정도 간추려낼 수 있습니다. Machine, NumberOfSection, SizeOfOptionalHeader, Characteristics 이렇게 4가지 멤버인데요.

  이 멤버들이 정확한 값으로 세팅되어 있지 않으면 파일은 정상적으로 실행되지 않습니다. 이 4가지 멤버에 대해서 좀더 자세하게 알아보도록 합시다.


  


#1. Machine

- Machine 넘버는 CPU별로 고유한 값이며, 해당 실행 파일이 실행될 수 있는 시스템(CPU)을 나타내는 값입니다. 아래는 winnt.h 파일에 정의된 Machine 넘버의

  값들입니다.


[ 출처 : Microsoft Platform SDK - winnt.h ]



#2. NumberOfSection

- PE 파일의 PE 바디에는 여러 섹션들이 존재한다고 했습니다. 일반적인 섹션의 종류로는 코드 섹션, 데이터 섹션, 리소스 섹션 등 여러 섹션이 올 수 있는데요.

  NumberOfSection 멤버는 이러한 섹션들의 개수를 값으로 가집니다. 그런데 이 값은 0보다 커야 하며, 정의된 섹션 개수와 실제 섹션이 다르면 실행 에러가 발생

  하게 된다는 점도 알아두시면 좋을 것 같습니다.




#3. SizeOfOptionalHeader

- NT Header의 세 번째 멤버인 OptionalHeader의 IMAGE_OPTIONAL_HEADER32 구조체의 크기를 저장하고 있는 필드입니다. PE 형태의 파일인 경우 IMAGE_

  OPTIONAL_HEADER32 구조체를 사용하고 PE+ 형태의 파일일 경우에는 IMAGE_OPTIONAL_HEADER64 구조체를 사용합니다. 두 구조체는 크기가 다르기 때문

  에 SizeOfOptionalHeader 멤버에 OptionalHeader의 구조체 크기를  명시하는 것입니다.






#4. Characteristics

- Characteristics 멤버는 파일의 속성을 나타내는 값으로, 실행이 가능한 형태인지(executable or not) 혹은 DLL 파일인지 등의 정보들이 bit OR 형식으로 조합됩니다.

  다음은 winnt,h 파일에 정의된 Characteristics 값입니다. (0002h와 2000h의 값을 기억하시길 바랍니다)



[ 출처 : Microsoft Platform SDK - winnt.h ]


- 위에 보이시는 Characteristics 값들을 bit OR 하여 파일의 속성을 나타내는 값을 만드는데요. 0002h가 없는 경우는 실행이 불가능한 파일이라는 것을 의미합니다.

  예를 들면 object 파일 및 resource DLL 같은 파일이 이에 해당합니다. 





#5. TimeDateStamp (참고)

- IMAGE_FILE_HEADER의 TimeDateStamp 멤버는 링커(Linker)에 의해 프로그램이 만들어진 시간 값이 저장되어 있습니다. 이 값은 1970년 1월 1일 오전 9시 

  GMT로 부터 1초 단위의 증가 값으로 표시된 것이며, 파일의 실행에 영향을 미치지 않는 값으로 중요한 멤버는 아닙니다. 단, 개발 도구에 따라서 이 값을 세팅해

  주는 도구(VB, VC++)가 있는 반면 그렇지 않은 도구(Delphi)도 있습니다.



# 지금까지 NT Header의 두 번째 멤버인 IMAGE_FILE_HEADER 구조체의 멤버들에 대해서 알아보았습니다. 실제로 Calc.exe 파일을 헥사 에디터와

   PE view를 이용하여 보도록 하겠습니다.




- Calc.exe 파일을 헥사 에디터로 열어본 모습입니다. 위에서 해당하는 영역이 바로 IMAGE_FILE_HEADER 영역입니다. PE View를 이용하여 Calc.exe 파일을 확인

  해 보도록하겠습니다.



- IMAGE_FILE_HEADER 구조체에 대해서 알아보았는데요. 구조체 이름 처럼 파일에 관한 정보를 담고 있는 구조체였습니다. 그럼 NT_HEADER의 마지막 멤버인 

  IMAGE_OPTIONAL_HEADER 구조체에 대해서 알아보도록 하겠습니다.




3.3.2 NT Header - Optional Header 


- PE 헤더 구조체 중에서 가장 크기가 큰 IMAGE_OPTIONAL_HEADER32입니다. 지금부터 IMAGE_OPTIONAL_HEADER32 구조체에 대해서 알아보도록 하겠

  습니다.

- IMAGE_OPTIONAL_HEADER32 구조체에 대해서 알아보도록 하겠습니다. 아래의 그림에서 강조한 부분에 해당하는 멤버들이 IMAGE_OPTIONAL_HEADER32

  구조체에서 주의깊게 봐야할 멤버들입니다. 이 멤버들의 값은 파일 실행에 있어 필수적이기 때문에 잘못 세팅되면 파일이 정상적으로 실행되지 않습니다.



[ 출처 : Microsoft Platform SDK - winnt.h ]



#1. Magic

- Magic 넘버는 IMAGE_OPTIONAL_HEADER32 구조체인 경우 10B, IMAGE_OPTIONAL_HEADER64 구조체인 경우 20B, ROM 이미지일 경우

  107의 값을 가집니다.




#2. AddressOfEntryPoint

- AddressOfEntryPoint 멤버는 PE 로더가 파일을 메모리에 매핑한 후 처음 실행을 시작할 EP(Entry Point)의 RVA(Relative Virual Address)값을

  가지고 있습니다. 이 값이야말로 프로그램에서 최초로 실행되는 코드의 시작 주소로, 매우 중요한 값입니다.




#3. ImageBase

- ImageBase는 프로세스의 가상 메모리 범위인 0~FFFFFFFF(32비트 운영체제인 경우)에서 PE 파일이 로딩되는 시작 주소를 나타냅니다. EXE, 

  DLL 파일은 user memory 영역인 0~7FFFFFFF 범위에 로딩되고, SYS 파일은 kernel memory 영역인 80000000~FFFFFFFF 범위에 로딩됩니다.

  일반적인 개발 도구인 VB, VC++, Delphi를 이용하여 만든 EXE 파일의 ImageBase 값은 00400000이고, DLL 파일의 ImageBase 값은 10000000

  입니다. PE 로더는 PE 파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩한 후 EIP 레지스터 값을 ImageBase + AddressOfEntry Point 

  값으로 세팅합니다.




#4. SectionAlignment, FileAlignment

- PE File 기본 구조에 대한 그림을 참고하시면 File 영역과 Memory 영역으로 나누어져있는것을 확인할 수 있습니다. PE 파일을 실행하게 되면 File 영역에

  있던 데이터가 Memory 영역에 맵핑되게 됩니다. SectionAlignment 멤버는 메모리에서 섹션의 최소단위를 나타내는 것이고, FileAligment 멤버는 파일에서

  섹션의 최소단위를 나타냅니다. (하나의 파일에서 FileAlignment와 SectionAlignment의 값은 같을 수도 있고 다를 수도 있습니다.) 파일/메모리의 섹션 크기

  는 반드시 각각 FileAlignment/SectionAlignment의 배수가 되어야 합니다.




#5. SizeOfImage

- SizeOfImage는 PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기를 나타냅니다. 일반적으로 파일의 크기와 메모리에 로딩된

  크기는 다릅니다. SizeOfImage에 들어가는 값의 크기는 PE 헤더를 포함해 모든 세션을 다 포함한 크기이며, 이는 Windows 로더가 해당 파일을 메모리에 

  로드할 때 얼마만큼의 메모리를 할당할지를 결정하는 값이기도 합니다.




#6. SizeOfHeader

- SizeOfHeader는 PE 헤더의 전체 크기를 나타냅니다. (DOS Header, DOS Stub, NT Header, Section Headers) 이 값 역시 FileAlignment의 배수

  여야 합니다. 파일 시작에서 SizeOfHeader 옵센만큼 떨어진 위치에 첫 번째 섹션이 위치합니다.




#7. Subsystem

- Subsystem 멤버에 들어가는 값은 실행 파일의 유저 인터페이스 부분에 대한 필요한 서브 시스템 값입니다. 이 Subsystem의 값을 보고 시스템 드라이버

  파일(*.sys)인지, 일반 실행 파일(*.exe, *.dll)인지 구분할 수 있습니다. Subsystem 멤버가 가질 수 있는 값은 아래와 같습니다.



[ 출처 : Microsoft Platform SDK - winnt.h ]



- 일반적으로 자주 쓰이는 Subsystem 값은 1~3 까지 입니다. 

  * 1 - Driver File - 시스템드라이버 (예 : ntfs.sys)

  * 2 - GUI(Graphic User Interface)파일 - 창 기반 애플리케이션 (예: notepad.exe)

  * 3 - CUI(Console User Interface)파일 - 콘솔 기반 애플리케이션 (예: cmd.exe)




#8. NumberOfRvaAndSizes

- NumberOfRvaAndSizes는 IMAGE_OPTIONAL_HEADER32 구조체의 마지막 멤버인 DataDirectory 배열의 개수를 나타냅니다. 구조체 정의에 

  분명히 배열 개수가 IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16) 이라고 명시되어 있지만, PE 로더는 NumberOfRvaAndSizes의 값을 보고 배열의 

  크기를 인식합니다. 따라서, 꼭 16이 되는 것은 아닙니다.




#9. DataDirectory

- DataDirectory는 IMAGE_DATA_DIRECTORY 구조체의 배열로, 배열의 각 항목 마다 정의된 값을 가집니다.



[ 출처 : 리버싱 핵심원리 ]


- 여기서 중요한 구조체 배열 멤버는 EXPORT, IMPORT, RESOURCE, TLS Directory 정도가 있겠습니다. 특히 IMPORTEXPORT Directory 구조는 

  PE 헤더에서 매우 중요하기 때문에 기억해두시기 바랍니다.



# NT Header의 Optional Header 멤버에 대해서 알아보았습니다. 헥사 에디터, PE View를 통해 실제로 한번 살펴보고 마무리하도록 하겠습니다.





- Calc.exe 파일에서의 Optional Header 영역을 헥사 에디터로 본 모습입니다. 제일 처음 Magic 멤버로 시작하는 것을 확인할 수 있습니다. (010B)

- 다음 사진은 PE View를 이용하여 Calc.exe 파일의 Optional Header 영역을 살펴본 모습입니다.






3.4. Section Header 


- Section Header는 각 Section의 속성을 정의한 것입니다. Section은 비슷한 성격의 자료를 모아 각 각의 Section으로 나누어지는데 이렇게 하는 이유가 프로그램의

  안정성을 위해서라고 합니다. (메모리 관리를 편하게 하기 위함이라는 이유도 있습니다) 우선 Section Header 구조체인 IMAGE_SECTION_HEADER 구조체를 살펴

  보도록 하겠습니다.



[ IMAGE_SECTION_HEADER 구조체의 크기는 28(40Byte) 입니다]

[ 출처 : Microsoft Platform SDK - winnt.h ]



- Section의 속성에는 file/memory에서의 시작 위치, 크기, 엑세스 권한 등이 있습니다. Code, Data, Resourse Section은 각각의 특성, 접근 권한 

  등이 다르게 설정됩니다.



# 메모리 속성별 액세스 권한

[ 출처 : 리버싱 핵심원리 ]



- Section Header 구조체인 IMAGE_SECTION_HEADER 구조체에서 알아야 할 중요 멤버는 5가지가 있습니다. 

  ( VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData, Characteristics )



 #1. VirtualSize              

- 메모리에서 섹션이 차지하는 크기

 

 #2. VirtualAddress          

- 메모리에서 섹션의 시작 주소 (RVA)

 

 #3. SizeOfRawData        

- 파일에서 섹션이 차지하는 크기

 

 #4. PointerToRawData   

- 파일에서 섹션의 시작 위치

 

 #5. Characteristics         

- 섹션의 속성 (bit OR)


 #6. Name (참고)      

- 8Byte 크기의 세션 이름 값이 저장, PE 스펙에너느 섹션 Name에 대한 어떠한 명시적인 규칙이 없기 때문에 어떠한 값을 넣어

  도 되고 심지어 NULL로 채울 수도 있습니다. 따라서 섹션의 Name은 중요하지 않고, 참고 정도만 하시면 될 것 같습니다.



- VirtualAddress와 PointerToRawData는 아무 값이나 가질 수 없으며, 각각 (IMAGE_OPTIONAL_HEADER32에 정의된) SectionAlignment와 

  FileAlignment에 맞게 결정 됩니다. 앞에서 한번 언급했었는데, 파일에서의 섹션 크기와 메모리에 로딩되는 섹션의 크기는 다르다고 말했었습니다. 때문에, 

  VirtualSize 멤버의 값과 SizeOfRawData 멤버의 값은 일반적으로 다른 값을 가지게 됩니다.


- 마지막 멤버인 Characteristics 멤버의 값은 섹션의 속성 값을 bit OR 연산하여 나온 결과 값을 가지게 됩니다. 섹션의 속성들에는 어떤것들이 있는지 살펴보도록 

  하겠습니다.



[ 출처 : Microsoft Platform SDK - winnt.h ]



#1. IMAGE_SCN_CNT_CODE

- 실행 가능한 코드를 포함하는 세션임을 의미한다.

 

#2. IMAGE_SCN_CNT_INITIALIZED_DATA

- 이 세션은 코드가 실행되기 이전에 초기화가 되어 있던 데이터들이 포함되어 있는 데이터 세션임을 의미한다.

 

#3. IMAGE_SCN_CNT_UNINITIALIZED_DATA

- 이 세션은 초기화가 필요 없는 데이터가 포함된 세션을 의미하며, 로더는 이 메모리 내용에 대하여 0으로 초기화 한다.


#4. IMAGE_SCN_MEM_SHARED

- 이 모듈을 사용하는 모든 프로세스들이 이 플래그가 정의된 세션을 공유하도록 하는 플래그 값이다.


#5. IMAGE_SCN_MEM_EXECUTE

- 로더가 이 세션을 위한 메모리 할당 시 실행이 가능하도록 메모리를 할당하는 플래그 값이다.


#6. IMAGE_SCN_MEM_READ

- 로더가 이 세션을 위한 메모리 할당 시 읽기가 가능하도록 메모리를 할당하는 플래그 값이다.


#7. IMAGE_SCN_MEM_WRITE

- 로더가 이 세션을 위한 메모리 할당 시 쓰기가 가능하도록 메모리를 할당하는 플래그 값이다.


#8. IMAGE_SCN_MEM_DISCARDABLE

- 이 세션은 프로세스가 시작된 이후에 필요 없는 데이터임을 나타내며, 재배치 테이블이 이러할 수 있다.


#9. IMAGE_SCN_MEM_NOT_PAGED

- 이 세션이 페이지 아웃이 안 되고 항상 메모리에 있어야 함을 나타내는 플래그로 디바이스 드라이버의 세션에서 주로 확인할 수 있다.




# 지금까지 Section Header에 대해서 알아보았습니다. 마지막으로 Calc.exe 파일의 Section Header 영역을 PE View, 헥사 에디터로 한번 보도록 

  하겠습니다.




[ Calc.exe 파일의 Section Headers - HXD ]





- 헥사 에디터를 이용하여 Calc.exe 파일의 Section Header 영역을 살펴본 모습입니다. 오른쪽에 ANSI 형태로 표현된 값들을 살펴보면 총 4개의

  섹션이 존재한다는 것을 확인할 수 있습니다. ( .text  ,  .data  ,  .rsrc  ,  .reloc = 각각 40Byte씩 차지하고 있습니다)





[ Calc.exe 파일의 Section Headers - PE View ]


- 위의 사진은 PE View를 이용하여 본 모습입니다. 각 섹션별로 헤더 정보들을 자세하게 볼 수 있습니다.




# 마지막 Section Header 까지, 이렇게 PE File Format에 대하여 알아보았습니다. 저도 공부하는 입장이라 관련 도서 및 관련 자료들을 많이 참고

  하면서 포스팅하게 되었네요. 처음에는 대충 훑어보는데 엄청 어려운 내용들인줄 알았는데, 천천히 그리고 반복해서 계속 읽어보고 모르는 부분은

  여러 자료들 보면서 공부하니 조금이나마 이해가 된 것 같습니다. 제가 참고한 자료들은 아래에 정리해두겠습니다. 개인적으로 리버싱 핵심원리를

  많이 참고했습니다. 책에 좋은 팁들도 많고 초심자에게 정말 좋은 책인것 같습니다. 






# 참고 도서 및 참고 자료


- 리버싱 핵심원리

- Windows 구조와 원리

http://ko.wikipedia.org/wiki/MZ_%EC%8B%A4%ED%96%89_%ED%8C%8C%EC%9D%BC

PE File Format [koromoon].pdf

- PE Structure [Deok9].pdf