Security

PE(Portable Executable) header

hilily 2022. 8. 4. 17:13
반응형

1. PE와 PEview

PE(Portable Executable) : 하나의 실행파일을 다양한 Windows 운영체제에서 실행시킬 수 있다.

PE File : 1) Windows 운영체제에서 실행되는 실행파일이다.

2) Win32 운영체제라면 어디에서도 잘 돌아간다. -> DOS모드를 제외한 windows 운영체제

PE를 배워야 하는 이유 : 1) PE파일의 구조를 배우면 파일이 실행되기 위한 모든 정보를 얻을 수 있다.

2) 이는 구조체 형식으로 PE헤더에 저장되어 있다.


PE파일의 종류

실행계열
설명
드라이버계열
설명
라이브러리
계열
설명
오브젝트계열
설명
EXE
실행파일
SYS
윈도우 운영체제에서 사용되는 시스템파일
DLL
윈도우에 저장되어있는 기능을 파일로 저장(용량↓/ 실행x )
OBJ
3차원 그래픽 이미지가 저장된 파일의 형태 중 하다
SCR
화면보호기의 일반적인 파일형식
VXD
윈도우에서 쓰이는 장치드라이버 모델
OCX
윈도우에 각종 응용프로그램 사이에서 서로 데이터를 공유할 수 있는 기능
   
       
CPL
DLL과 동일하나, EXE와 같이 실행가능
   
       
DRV
윈도우 운영체제에서 하드웨어 장피를 연결하고 통신하기 위해 사용
   

PEview에 notepad.exe를 적용시킨 모습의 좌측 목록 부분이다.

여기서 IMAGE_DOS_HEADER ~ IMAGE_SECTION_HEADER 까지가 헤더 부분이며,

SECTION.text 부터 바디 부분이다.


2. IMAGE_DOS_HEADER

 

좌측 사진은 위에서 언급하였다시피 헤더는 구조체 형식으로 이루어져 있으며, 이는 visual studio에서 #include <winnt.h>의 문서를 보면 찾을 수 있다.

1) e_magic (2byte) : 1) 가장 먼저 로더가 인식한다.

2) MZ = 4D 5A

3) 현재 파일이 PE파일인지 체크한다. (MZ일 경우)

2) e_lfanew(4byte) : 1) IMAGE_NT_HEADERS의 시작 절대주소(Offset)이다.

2) 파일에 따라 값이 다르다

오른쪽 그림은 peview를 통해 찾아본 두 값이다. data영역에 해당하는 값이 저장되어 있다.

그리고 궁금했던점들 중 제시되었던 것이 왜 WORD 자료형을 사용한 것인가? 였다.

우선 word자료형은 cpu가 처리 할 수 있는 데이터의 크기의 단위이다 (cpu마다 다르다)

그러므로 word가 사용되었고, 뒤에서 나올테지만 dword : 4byte, word : 2byte이다.

또한, pfile = offset과 같다.


+) MS-DOS Stub Program

1) 그렇게 중요한 부분이 아니다. (필수 구성요소X)

2) 프로그램을 DOS 모드에서 실행 시켰을 때 “This program cannot be run in DOS mode” 라는 문자열을 실행한다.


3. IMAGE_NT_HEADERS

1) e_lfanew에 저장된 주소 값이 이부분을 가리킨다.

2) 파일 실행에 필요한 정보가 저장되어 있다.


3-1. Signature

1) PE 구조의 파일이라는 것을 알린다.

2) PE의 값(0x50450000)을 가지며, 이 값은 변경이 불가능하다.

3) 값을 변경 시 PE파일로 인식하지 못하여 실행이 불가능하다.

pFile의 시작 값이 000000F0이다. 이 값은 앞에 나왔던 e_lfanew에서 봤던 값이고, 즉 e_lfanew에 의해 offset이 지정됨을 확인할 수 있다.


3-2. IMAGE_FILE_HEADER

: 동작하는 CPU, 섹션의 수, 생성 시간 등 파일의 대략적인 정보를 저장한다.

winnt.h와 peview에서도 같이 같은 구성요소를 가진다.


1. machine : 1) PE파일이 동작할 수 있는 CPU 종류이다.

메모장에서는 4C 01이라는 값이 나온다.

처음에 공부를 할 때는 내가 사용하는 컴퓨터의 cpu에 따라서 값이 달라진다고 생각하였다. 그래서 의심하지 않고 4C 01로 표기되었다고 생각했는데, 이를 자세히 알아보니 그게 아니라 파일이 컴파일을 몇비트로 했냐에 따라 다르게 표기되었다.

32비트로 컴파일된 exe파일과 64비트로 컴파일된 exe파일을 각각 peview에 넣어 값을 비교해 보았다.

그랬더니 같은 컴퓨터로 확인했음에도 32비트에서는 4C 01, 64비트에서는 64 86이라는 값이 나왔다.

즉, 컴퓨터의 cpu가 기준이 아니라 파일이 몇비트로 컴파일 되었냐가 핵심이다.

또한 메모장은 32비트로 컴파일 되었음을 알 수 있다.


2. Number of Sections

1) PE파일을 구성하는 섹션의 수를 나타낸다.

2) 섹션이 없는 파일은 존재하지 않는다. (값이 0보다 커야 한다.)

 

해당 값이 6이므로 섹션의 개수는 6개이다. 섹션은 헤더에 있는 섹션을 의미한다.


3. TimeDateStamp

1) 파일이 만들어진 시간이 기록된다. (1970년 1월 1일~/ 유닉스의 시작점)

2) 초단위로 표기된다.

0x93B4E8FA = 156633163892초 이므로, 이를 환산하여 1970년 1월 1일에 더한다.


4. PointerSymbolTable

1) COFF(Common Object File Format)

심볼 테이블의 파일 오프셋을 가리킨다.

2) 없는 경우가 대부분이다.

5. NumberOfSymbols

1) PointerToSymbolTable필드가 가리키는 COFF심볼 테이블의 심볼 수를 나타낸다.

*COFF : 유닉스 시스템에 의해 사용되는 실행파일, 목적파일, 공유라이브러리 컴퓨터 파일을 위한 포맷으로 어셈블러를 거쳐서 만들어진 오브젝트 파일에서 공통된것만 따로 모아 관리하는 포맷이다.

해당 값은 대부분 0이다. PointerSymbolTable, NumberOfSymbols는 현재는 잘 쓰이지 않는다.


6. SizeOfOptionalHeader

1) Optional Header의 크기를 저장한다.

2) Optional Header의 크기는 운영체제에 따라 차이가 있다.


7. Characteristics

1) 현재 파일의 형식을 알려준다.

2) 이 값을 이용하여 파일의 종류(EXE, DLL, SYS등)를 알 수 있다.

3) OR연산을 이용한다.


3-3. IMAGE_OPTIONAL_HEADER

: 파일실행에 관한 중요한 정보들을 저장한다.

1.Magic

1)실행하는 PE파일의 구조체가 32bit(0x10B)인지, 64bit(0x20B)인지 알려주는 부분


2. Size Of Code

1) 코드 영역의 크기를 나타낸다.

즉, section.text(바디)의 크기를 나타낸다.


3. Address Of Entry Point

1) 프로그램이 시작되는 코드의 주소가 RVA값으로 저장되어 있다.

2) 실제 로더가 제일 먼저 실행할 코드의 시작점

** RVA (Relative Virtual Address) : 실행파일이 메모리에 로드 되었을 때의 상대주소.

ex) RVA의 값이 0x3000이고, 실행파일이 로드되었을 때 Image Base가 0x40000이면

RVA 0x3000 영역이 메모리에 로드 되었을 때 위치는 0x43000이 된다.


4. Base Of Code

1) 코드 영역이 시작되는 상대 주소(RVA)이다.

** 코드영역 -> 메모리에 있는 코드


5. Image Base

1) PE파일이 메모리에 로드되는 시작 주소

2) 보통 exe(0x400000), DDL(0x10000000)번지로 설정

Image Base + Base of code(RVA) = section.text(코드 영역의 시작 주소)


6. Section Alignment

1) 메모리에서 섹션의 최소 단위, 시작주소는 이 값의 배수이다.


7. File Alignment

1) 파일에서 섹션의 최소 단위이다.

2) 시작주소는 이 값의 배수이다.


** PE 구조

사진 출처 : https://jmoon.co.kr/130

위에 Section Alignment와 File Alignment의 내용에서 메모리에서 섹션의 단위는 1000이고, 파일에서 섹션의 단위는 200이다.

따라서 Disk 부분에서는 섹션을 200씩 나누고, Memeory 부분에서는 1000씩 나누어서 섹션을 나누는 단위가 커졌기 때문에 널값이 증가하고, 주소 또한 바뀐다.


8. Size of Image

1) PE파일이 메모리에 로딩될 때 전체 크기이다.


9. Size of hedaer

1) 모든 헤더의 크기이다.

2) Dos Header + Dos Stub + PE Header + Section Header

400 바이트임을 확인 가능하다.


10. Sub System

1) 실행 파일의 유저 인터페이스 부분에 대해 필요한 서브 시스템 값이다.

값이 2이므로 메모장은 GUI 이다.


11. Number of RvaAndSizes

- Data Directory 구조체 멤버 개수

10개임을 알 수 있다.


4. IMAGE_SECTION_HEADER : 각 Section에 대한 이름을 비롯해 시작 주소와 사이즈 등의 정보를 관리하는 구조체이다.

1.Name

1) 섹션의 이름을 나타내는 멤버이다.

2) 섹션의 이름이 같다고 해서 같은 속성을 지니지 않으므로 Characteristics 멤버를 참조해야 한다.

**

1).text : 파일을 열었을 때 실행될 코드가 저장된다.

2).data : 초기화된 전역변수, static변수를 저장한다.

3).rdata : Const변수, 문자열 상수를 저장한다.

4).bss : 초기화되지 않은 전역변수, static변수, 문자열, 기타 상수를 저장한다. 초기화가 진행될 경우 data영역으로 이동한다.

5).edata : EAT와 관련된 정보가 저장된다.

6).idata : IAT와 관련된 정보가 저장된다.

7).rsrc : 리소스 정보가 저장된다.

** EAT(Export Address Table) : 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 쓸수있게 사용해준다.

IAT(Import Address Table) : 프로그램에서 어떤 DLL을 사용했는지 알려주는 테이블이다.


2. VirtualAddress

1) 메모리에서 해당 섹션의 위치 (RVA)


3. SizeOfRawData

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


4. PointerToRawData

1) 파일에서 섹션의 시작 위치


5. Characteristics

1) 섹션의 특징


***+) 위 내용을 바탕으로 notepad의 헤더를 보고 알 수 있는 것

IMAGE_DOS_HEADER

1) 4D 5A (MZ) = pe구조를 사용하고 있다.

MS-DOS Stub Program

2) Dos mode에선 실행되지 않는다.

IMAGE_NT_HEADERS

-IMAGE_FILE_HEADER

3) 파일이 동작하는 CPU : x86 (Machine)

4) 섹션의 수 : 6 (Number of Sections)

5) 32bit , exe형식이다. (Characteristics)

-IMAGE_OPTIONAL_HEADER

6) PE파일의 구조체 : 32bit (Magic)

7) 처음 실행되는 코드의 주소 : 400000(Image Base) + 001F8D0(Address of EntryPoint) = 41F8D0

8) 코드 영역의 주소 : 400000(Image Base) + 1000(Base of Code) = 401000

9) 메모리에 로딩 되었을 때의 크기 : 02B000(Size of Image)

10) 헤더의 크기 : 400byte (Size of Header)

11) 파일의 종류 : GUI(2) (Sub System)

반응형