안녕하세요
테라트입니다
오늘은 PE에 대한 정의 및 구조에 대해 공부한 것을 정리하고자 합니다
# PE(Portable Executable File Format)
: 이 부분이 손상될 경우 파일이 실행되지 않음
: 여러 개의 구조체로 구성
: Windows 에서의 실행 가능한 파일을 의미
: OS별로 실행 파일의 구조가 다르기 때문에 OS가 달라져도 실행된다는 것을 의미하진 않음
# PE 빌드 과정(실행 파일 컴파일 과정)
Source -- Complie -> Obj -- Link --> Exe
- Source : 사용자가 알아 볼 수 있는 언어 형태의 소스
- Compile : 사용자의 소스를 컴퓨터가 인식할 수 있는 형태로 바꾸는 작업
- Obj : 컴퓨터가 이해하는 형태의 파일, 실행은 불가능한 파일
- Link : 윈도우의 약속된 규약에 맞춰 파일을 생성하는 과정
- Exe : PE를 포함한 실행 가능한 최종 파일
# PE 파일 구조
위에서 설명했듯이 PE는 여러 개의 구조체로 이루어졌습니다
한개의 구조체씩 정리하도록 하겠습니다
1. IMAGE_DOS_HEADER : DOS에서도 실행 가능하도록 호환성을 제공하는 헤더
※ 여러개의 변수들이 있지만, 리버싱 공부 시작단계이므로 중요한 정보의 필드만 확인해보도록 하겠습니다
- e_magic : 현재 파일이 PE 파일 인지 체크
- e_lfanew : IMAGE_NT_HEADER 구조체의 위치를 저장
2. IMAGE_NT_HEADER : 한 개의 DWORD 변수와 두 개의 구조체로 구성
※ 두 개의 구조체는 여러 개의 변수를 포함하기 때문에 따로 설명하겠습니다
- Signature : PE 파일임을 표시
- IMAGE_FILE_HEADER : 파일을 실행하기 위한 데이터를 담고 있는 구조체
- IMAGE_OPTIONAL_HEADER : 주소값, 시작 주소 등이 저장되어 있는 구조체
3. IMAGE_FILE_HEADER : 파일을 실행하기 위한 데이터를 담고 있는 구조체
- Machine : 현재 CPU가 이 프로그램을 실행하기 적합한지 확인
- NumberOfSections : 섹션의 개수를 알려준다.
※ 섹션 : .text , .data 와 같은 코드 섹션이나 데이터 섹션을 의미
- TimeDateStamp : Obj 파일에서 링커를 통해 Exe 파일로 생성한 시간
- SizeOfOptionalHeader : IMAGE_OPTIONAL_HEADER32의 구조체 크기 정보
- Characteristics : 파일 형식의 정보 저장, DLL인지 EXE 파일인지를 구분
4. IMAGE_OPTIONAL_HEADER : PE구조체의 핵심 정보라 할 수 있는 주소값, 시작 주소 등이 저장되어 있는 구조체
- Magic : 32비트인지, 64비트인지를 저장 32비트는 0x10B, 64비트는 0x20B로 표시
- SizeOfCode : 코드 전체의 크기를 저장
- MajorLinkerVersion, MinorLinkerVersion : 어떤 버전의 컴파일로 빌드했는지 저장
- ImageBase : PE파일이 가상 메모리에 매핑 될 때, 가상 메모리의 시작주소 저장
- AddressOfEntryPoint : 실제 파일이 메모리에서 실행되는 시작 지점
- BaseOfCode : 실제코드가 실행되는 번지
※ AddressOfEntryPoint 와 BaseOfCode : 두 변수 모두 시작 지점을 저장하는 것 같아 보일 수 있지만, AddressOfEntryPoint는 PE 파일 전체의 시작 위치를 저장하고, BaseOfCode는 실제 코드가 시작되는 지점을 저장한다. AddressOfEntryPoint 범주 안에 BaseOfCode가 속해있다고 볼 수 있다.
- SectionAlignment, FileAlignment : 각 섹션을 정렬하기 위한 저장 단위
- SectionAlignment : 메모리 상에서의 간격을 의미
- FileAlignment : 파일 상에서의 간격을 의미
- SizeOfImage : EXE/DLL이 메모리에 로딩되었을 때의 전체크기, SectionAlignment 값에 패딩한 값까지 포함
※ 패딩 : 섹션의 빈공간을 0으로 채워지는 행위
- SizeOfHeaders : PE 헤더의 크기 정보를 저장
- Subsystem : 프로그램이 GUI인지, 콘솔인지의 정보를 저장
- 0x1 : *.sys 같은 드라이버 모듈
- 0x2 : Windows GUI
- 0x3 : 콘솔 프로그램
- DataDirectory : 구조체 타입으로, Export Directory, Import Directory, IAT 등의 정보를 저장
5. IMAGE_SECTION_HEADER : 각 섹션에 대한 정보를 관리하는 구조체
- Name : 섹션의 이름을 나타내는 멤버, 섹션의 속성 파악은 Characteristics 멤버 참조
- VirtualSize : 메모리에서 섹션의 시작 주소
- VirtualAddress : 메모리에서 섹션이 차지하는 크기
- SizeOfRawData : 파일에서 섹션이 차지하는 크기
- PointerToRawData : 파일에서 섹션의 시작위치
- Characteristics : 섹션에 대한 정보 정의
※ VirtualSize와 SizeOfRawData는 보통 다른 값을 가지는데, 파일에서의 PE와 메모리에서의 PE가 다른 형태를 가지기 때문이다
※ 메모리에 로딩된 상태를 IMAGE라고 표현한다