Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
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
Tags
more
Archives
Today
Total
관리 메뉴

Study

리버싱 핵심원리_13_PE File(1) 본문

Reversing/리버싱 핵심원리

리버싱 핵심원리_13_PE File(1)

마늘부추 2019. 1. 30. 21:26

13. PE File

 

13.1 PE File이란?

 

- Windows 운영체제에서 사용되는 실행 파일 형식.
- 기본적으로 32비트 형태의 실행 파일을 의미하며 PE32라는 용어를 사용하기도 한다.
- 64비트 형태의 실행 파일은 PE+ 또는 PE32+라고 부르며 PE 파일의 확장 형태이다.

 

 실행 계열

 .scr

 - Screen Saver의 약자. 윈도우 화면 보호기 파일. 이 파일은 혼자서도 실행된다.
 - 윈도우 디렉터리나 System 디렉터리에 설치되며, 디스플레이 등록정보에서 설정하여 사용한다.

 .exe

 - Executable의 약자로 가장 기본적인 실행파일.
 - 그 외 실행 파일로는 .bat, .com등이 있다.

드라이버

계열

 .sys

 - System의 약자로 시스템 운영에 꼭 필요한 파일이며, config,sys, msdows.sys처럼 부팅과 관련이 있거나 운영체제의 시스템에 관련된 내용이 들어 있다.

 .vxd

 - Virtual Device Driver(가상 디바이스 드라이버 파일)의 확장자로 하드웨어 또는 소프트웨어의 동작을 관리한다.

 라이브러리

계열

 .dll

 - 동적 링크 라이브러리(dynamic link lirary)의 약자로 독립된 개체들을 하나로 종합한 라이브러리 파일이다.

 .ocx

 - 프로그램에서 실행에 필요한 기능을 한데 모아 놓은 파일로 dll 파일과 비슷하다.

 .drv

 - driver의 약자. PC에 설치된 수많은 하드웨어의 인식과 구동을 제어하는 디바이스 드라이버 파일로 데이터가 들어있는 파일이다.

오브젝트 계열

 .obj

 - 컴파일되었지만 링크되지 않은 개체 파일

 

출처 - https://kin.naver.com/qna/detail.nhn?d1id=1&dirId=10603&docId=69718293

 

obj 파일을 제외한 드라이버, 라이브러리 계열 파일은 직접 실행은 아니더라도

다른 형태의 방법(디버거, 서비스, 기타)을 이용하여 실행이 가능한 파일이다.

 

 

 

13.2 PE File의 구조

 

- PE File의 구조

왼쪽 : 파일일 때의 모습

오른쪽 : 메모리상에서의 모습

파일은 그 모습 그대로 메모리에 올라가는 것이 아니라 각 섹션 헤더에 정의된 규칙에 따라 메모리에 올라가기 때문에 파일상에서의 모습과 다르다.

 

- PE File의 주소

파일에서는 Offset으로, 메모리에선 VA(Virtual Address) 또는 RVA(Relative Virtual Address)로 주소를 표현한다.

 

※ VA / RVA

RVA는 어느 기준 위치(ImageBase. 위 그림에선 1000000)에서부터의 상대주소를 말한다.
VA와 RVA의 관계는 다음과 같다.

RVA + ImageBase = VA

 

- PE File의 영역

 Header 영역

 - DOS header, NT header, 각 section header
 - 헤더 영역에는 파일이 실행되기 위해 필요한 모든 정보가 구조체 형태로 존재한다.
 - 어떻게 메모리에 적재되고, 어디서부터 실행되어야 하며, 실행에 필요한 dll은 어떤 것이 있고 필요한 메모리의 크기는 어떻게 할지 등등의 정보가 PE header 영역의 구조체 정보에 담겨 있다.

 Body 영역

 - 나머지 section 영역들
 - 실행 진입점, 명령어, 변수, 문자열 등등이 비슷한 용도끼리 섹션으로 구분되어 저장된 영역이다.
 - 개발도구의 종류와 빌드 옵션에 따라서 섹션의 이름, 크기, 개수, 저장 내용 등은 달라진다.

 

 

 

13.2.1 DOS Header

 

Microsoft는 DOS 파일에 대한 하위 호환성을 고려하여 PE 헤더의 제일 앞부분에 DOS EXE Header를 확장시킨

IMAGE_DOS_HEADER 구조체를 만들었다.

 

 

 

IMAGE_DOS_HEADER 구조체의 크기는 40(64byte)이다.

그 중 첫 번째 멤버인 e_magic과 마지막 멤버인 e_lfanew가 중요하다.

 

 e_magic

 - DOS Header의 시작을 뜻하는 문자열 "MZ"(4D5A)를 저장한다.
 - 모든 PE 파일의 맨 앞에는 DOS header가 존재하며, 이 DOS header 부분은 MZ 문자열로 시작한다.
 - 이 값은 PE 스펙에 따른 고정 값이므로 수정하게 되면 정상 실행이 되지 않는다.

 e_lfanew

 - IMAGE_NT_HEADER의 시작 주소를 저장한다.
 - DOS header의 다음에는 DOS stub이라는 것이 존재하는데 이는 옵션이므로 있어도 없어도 상관없는 부분이다. 어디서부터가 NT header 인지 구분이 가지 않는다면
이 멤버에 저장된 데이터를 참조하여 DOS stub를 뛰어넘어 NT header 시작 주소로 바로 갈 수 있다.

 

 

 

13.2.2 DOS Stub

 

DOS Stub의 존재 여부는 옵션이며 정해진 크기가 없다.

 

 

파일 Offset 40~4D 영역은 16비트 어셈블리 명령어이다. Notepad.exe 파일을 DOS 환경에서 실행하거나
DOS용 디버거를 이용하여 실행하면 위 코드를 실행시킬 수 있다.
이 특성을 이용하여 하나의 실행 파일에 DOS와 Windows에서 모두 실행 가능한 파일을 만들 수 있다.
(DOS 환경에서는 16비트 코드가, Windows 환경에서는 32비트 코드가 각각 실행된다)

 

 

 

13.2.3 NT Header

 

 

 

 Signature

 NT header 구조체의 처음 멤버이고 헤더의 시작을 알리는 문자열("PE"00)을 저장한다.

 FileHeader,

 OptionalHeader

 파일의 개략적인 속성을 나타낸다.

 

 

 

 Machine

 - CPU 별로 고유한 값이다. Machine 넘버의 값들은 winnt.h파일에 정의되어 있다.

 NumberOfSections

 - 섹션의 개수를 나타내고 이 값은 반드시 0보다 커야 한다.
 - 정의된 섹션의 개수와 실제 섹션의 개수가 다르면 실행 에러가 발생한다.

 SizeOfOptinalHeader

 - IMAGE_OPTIONAL_HEADER32 구조체의 크기를 정의한다.
 - PE32 파일과 PE32+ 파일의 크기가 다르기 때문에 이 멤버에 크기를 명시한다.

 Characteristics

 - 파일이 실행이 가능한 형태인지 혹은 DLL 파일인지 등의 정보들이 bit OR 형식으로 조합된다.

 TimeDateStamp

 - 파일의 실행에 영향을 미치지 않는 값으로, 해당 파일의 빌드 시간을 나타낸다.

 

 Machine 넘버

#define IMAGE_FILE_MACHINE_UNKNOWN                      0
#define IMAGE_FILE_MACHINE_I386                                0x014c  // Intel 386 .
#define IMAGE_FILE_MACHINE_R3000                              0x0162  // MIPS little-endian, 0x160

                                                                                            big-endian
#define IMAGE_FILE_MACHINE_R4000                             0x0166  // M1PS little-endian
#define IMAGE_FILE_MACHINE_R10000                            0x0168  // M1PS little-endi an
#define IMAGE_FILE_MACHINE_WCEMIPSV2                     0x0169  // M1PS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA                            0x0184  // Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC                        0x01F0  // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_SH3                                0x01a2  // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3E                              0x01a4  // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4                                0x01a6  // SH4 little-endian
#define IMAGE_FILE_MACHINE_ARM                               0x01c0  // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUM8                           0x01c2
#define IMAGE_FILE_MACHINE_IA64                               0x0200  // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16                           0x0266  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU                         0x0366  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16                      0x0466  // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64                         0x0284  // ALPHA64
#define IMAGE_FILE_MACHINE_AXP64                            IMAGE_FILE_MACHINE_ALPHA64

 

 

 

 Magic

 - IMAGE_OPTIONAL_HEADER32 구조체인 경우 10B

 - IMAGE_OPTIONAL_HEADER64 20B 값을 가진다.

 AddressOfEntryPoint

 - EP의 RVA값을 가지고 있다.

 ImageBase

 - 프로세스의 가상 메모리 주소는 0~FFFFFFFF 공간이다. 그중 PE 파일이 로딩되는 시작 주소를 나타낸다.
 * user memory - 0~7FFFFFFF
 * kernel memory - 80000000~FFFFFFFF
 - 일반적인 EXE, DLL 파일은 user memory 영역에 로딩되고, SYS 파일은 kernel memory 영역에 로딩된다.
 - PE 로더는 PE 파일을 실행하기 위해 프로세스를 생성 후 ImageBase + AddressOfEntryPoint 값을 EIP 레지스터에 담아 시작한다.

 SectionAlignment

 FileAlignment

 - 메모리에서 섹션의 최소 단위 / 파일에서 섹션의 최소 단위

 SizeOfImage

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

 SizeOfHeader

 - PE 헤더의 전체 크기를 나타낸다. FileAlignment의 배수여야 한다.

 SubSystem

 - 이 값을 보고 시스템 드라이버 파일(*.sys)인지 일반 실행파일(*.exe, *.dll)인지 구분할 수 있다.
 1 : Driver file 시스템 드라이버
 2 : GUI file 창 기반 애플리케이션
 3 : CUI file 콘솔 기반 애플리케이션

 NumberOfRvaAdnSize

 - IMAGE_OPTIONAL_HEADER32구조체의 마지막 멤버인 DataDirectory 배열의 개수를 나타낸다.

 - 구조체 정의에 이미 IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16이라고 명시되어 있지만, PE 로더는 이 값을 보고 배열의 크기를 인식한다.

 DataDirectory

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

 

 

 

13.2.4 Section Header

 

각 섹션의 속성(file/memory에서의 시작 위치, 크기, 액세스 권한 등)을 정의하는 헤더이다.

비슷한 성격을 가진 자료들을 섹션에 모아 구분, 각 섹션의 속성을 기술할 헤더가 필요해 만들어진 것이다.

 

 code

 실행, 읽기 권한

 data

 비실행, 읽기, 쓰기 권한

 resource

 비실행, 읽기 권한

 

 

 

 VirtualSize

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

 VirtualAddress

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

 SizeOfRawData

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

 PointerToRawData

 파일에서 섹션의 시작 위치

 Characteristic

 섹션의 속성(bit OR)

 Name

 .text, .data 등의 이름이 지정되는 멤버

 ※ PE 스펙에서는 섹션 Name에 대한 어떠한 명시적인 규칙이 없기 때문에 어떠한 값을 넣어도 되고 심지어 NULL로 채워도 상관이 없다.