1. PE Header
- PE view를 활용해 메모장.exe(PE 파일) 구조 확인
- Visual Studio에서 #include <winnt.h>를 입력->winnt.h에 마우스 우클릭->문서로이동을 통해 구조체를 확인할 수 있다.
1.1) DOS Header
- DOS 파일에 대한 호환성을 고려하여 만들어 졌으며, 총 64Byte 크기를 가짐.
- 구조체 : IMAGE_DOS_HEADER
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
① e_magic : DOS signature(매직넘버)로 PE파일을 나타내는 첫 2바이트, MZ(5A4D로 고정 값)
각 파일은 고유의 signature(매직넘버)를 가짐.
② e_lfanew : IMAGE_NT_HEADER의 시작 Offset 값을 가짐.
- e_flanew에 설정된 주소를 확인하면 PE로 시작하는 것을 확인할 수 있으며, 한번 더 시작점을 알려준다.
1.2) DOS Stub
- 구조체 형태가 아니며, DOS 환경에서 돌아갈 명령어가 16Bit 형태로, 가변 크기를 가짐.
- 일종의 옵션으로 없어도 파일 실행에 문제 없음.
- 32Bit 윈도우 플랫폼에서 실행되도록 만들어진 PE파일이 16Bit DOS 환경에서 실행되려 하는것을 방지하기위해 만들어짐.
1.3) NT Header
- 파일 실행에 필요한 정보가 저장됨.
- DOS Header의 e_flanew 값이 NT Header를 가리킴
- 구조체에는 총 3개의 멤버로 구성
- 구조체 : IMAGE_NT_HEADERS
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
1.3.1) Signature
- NT header구조체의 시작을 판별하실 수 있으며, ASCII 값으로 PE(0x00004550)를 나타낸다.
1.3.2) FileHeader
- 파일의 개략적인 속성을 나타낸다.
- 구조체 : IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
① Machine : 이 파일이 어떤 CPU에서 동작할 수 있는지, 즉 실행될 수 있는 CPU의 타입을 나타냄
IA-32 호환 4C01, IA-64 호환 0020, AMD64 호환 시 6486
② NumberOfSections : 파일에 존재하는 색션의 개수(파일에 따라 다름)를 나타내며, 0보다 커야함
정의된 색션 개수 > 실제 색션 개수 : 에러 / 정의된 색션 개수 < 실제 색션 개수 : 정상 실행
③ TimeDateStamp : 해당 파일이 만들어진 시각, 즉 이 파일이 빌드된 날짜가 기록됨. 변조가능(신뢰할 수 있는 값 아님)
④ PointerToSymbolTable : COFF 파일의 심볼 테이블의 오프셋을 나타냄. 없는 경우가 대부분임
⑤ NumberOfSymbols : COFF 심벌 테이블 내에서의 심벌의 수를 나타냄. 없는 경우가 대부분임
⑥ SizeOfOptionalHeader : IMAGE_NT_HEADER 구조체 내 IMAGE_OPTIONAL_HEADER 구조체의 크기에 대한 정보
⑦ Characteristics : 파일의 속성을 나타내는 값으로, 실행 파일인지 DLL 파일인지 등의 정보들이 OR 연산을 통해 설정
아래 사진을 보아 메모장은 executable 형식이며, 32bit 라는 것을 알 수 있다.
1.3.3) OptionalHeader
- 파일 실행에 필요한 주요 정보들을 저장한다.
- 구조체 : IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
① Magic : 실행하는 PE파일의 구조체가 32bit(0B01)인지, 64bit(0B02)인지 알려주는 부분
② SizeOfCode : 코드영역(.text)의 크기
③ AddressOfEntryPoint : 프로그램의 실제 시작주소로, ImageBase 값에 이 값을 더해 시작 지점을 설정
④ ImageBase : PE 파일이 메모리에 로드되는 시작 주소. EXE의 경우 00400000, DLL의 경우 00000001
⑤ SectionAlignment : 메모리에서 섹션의 최소 단위, 각 섹션은 반드시 이값의 배수
⑥ FileAlignment : 파일에서 섹션의 최소 단위, 각 섹션은 반드시 이값의 배수
⑦ SizeOfImage : 메모리에 로딩될 때 가상 메모리에서 PE Image가 차지하는 크기, 즉 PE 파일의 전체 크기
⑧ SizeOfHeaders : 모든 PE Header의 크기
⑨ Subsystem : 동작환경을 정의. sys 파일 1, GUI 파일 2, CLI 파일 3의 값을 가짐
⑩ NumberOfRvaAndSizes : Data Directory의 구조체 멤버 개수
⑪ DataDirectory : IMAGE_DATA_DIRECTORY구조체의 배열로써 디렉토리별로 각각의 정보를 담음
- Export Directory : DLL등의 파일에서 외부에 함수를 공개하기 위한 정보들을 가짐
- Import Directory : 프로그램 실행을 위해 Import하는 DLL 이름과 사용할 함수 정보가 담긴 INT주소와 IAT주소 같은 정보가 담김
- TLS Directory : 스레드 지역 저장소 초기화 섹션에 대한 포인터
- IAT Directory : IAT의 시작번지를 가리킴
1.4) Section Header
- 각 Section의 속성을 정의한 헤더
- Section 유형
Code | .text | 프로그램 실행 코드를 담고 있는 섹션 |
Data | .data | 일고 쓰기가 가능한 테이터 섹션으로 초기화된 전역변수와 정적 변수 등이 위치 |
.rdata | 읽기 전용 데이터 섹션으로 상수형 변수, 문자열 상수 등이 위치 | |
.bss | 초기화되지 않은 전역변수로, 초기화 시 .data 영역으로 이동 | |
Import API | .idata | Import 할 DLL과 API에 대한 정보를 담고 있는 섹션으로 IAT 정보가 저장 |
.diata | Delay-Loading Import DLL 정보 (프로그램 실행 후 DLL 사용시에만 연결하며, 릴리즈 모드 시 다른 섹션에 병합) | |
Expoit API | .edata | Export할 API 정보를 담고 있는 섹션 (주로 DLL에서 사용되며 .text 또는 .rdata에 병합)으로 EAT 정보가 저장 |
Resource | .rsrc | 리소스 관련 데이터를 담고 있는 섹션 (아이콘, 커서 등) |
재배치 정보 | .reloc | 기본 재배치 정보를 담고 있는 섹션 (주로 DLL에서 사용) |
TLS | .tls | 스레드 지역 저장소 |
Debugging | .debug$p | 미리 컴파일된 헤더 사용시에만 존재 |
참고 :
'악성코드 > 기본' 카테고리의 다른 글
PE 파일 #1 개요 및 구조 (0) | 2022.08.02 |
---|---|
Malware #1 (0) | 2022.07.11 |