본문 바로가기
악성코드 분석/리버싱 팁

PE 구조

by ITPro 2010. 12. 9.
PE(Portable Excutable) 구조

-PE포맷은 프로그램 실행 파일의 제일 첫 부분에 존재한다.
DOS Header
DOS Stub
PE File Header
Optional Header
Section Table
Sections

IMAGE_DOS_HEADER
IMAGE_NT_HEADER PE\0\0
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER
IMAGE_SECTION_HEADER

DOS Header

-도스 헤더 부분은 IMAGE_DOS_HEADER라는 구조체로 구성되어 있다.
typedef struct _IMAGE_DOS_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 헤더를 구별하는 식별자로 이 값을 체크하여 올바른 MZ 파일인지 확인한다. 모든 실행 파일은 파 일 가장 첫 부분에 MZ라는 2바이트의 아스키 코드값을 가지고 있는데 PE로더는 이 값을 체크하여 실행 파일을 메모리에 로드한다.

※e_magic 상수
명칭 설명
IMAGE_DOS_SIGNATURE 0x5A4D MZ
IMAGE_OS2_SIGNATURE 0x454E NE
IMAGE_OS2_SIGNATURE_LE 0x454C LE(도스)
IMAGE_VXD_SIGNATURE 0x454C LE(장치)
IMAGE_NT_SIGNATURE 0x00004550 PE00(NT계열)

elanew
-PE 헤더가 있는 곳의 오프셋 값(RVA 값)이다.
※RVA(Relative Virtual Address) : 가상 메모리의 오프셋

IMAGE_NT_HEADER

typedef struct _IMAGE_NT_HEADERS{
	DWORD Signature;
	IMAGE_FILE_HEADER FileHeader;
	IMAGE_OPTIONAL_HEADER OptionalHeader;
}IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

Signature
-이 파일이 올바른 PE 포맷으로 구성되어 있는지 확인하기 위한 일종의 플래그 값이다.
올바른 파일이라면 PE\0\0 값을 갖는다.
FileHeader
-IMAGE_FILE_HEADER의 구조체 멤버. 현재 파일이 exe인지 dll인지, 어느 플랫폼에서 실행되는지, 섹션 의 개수가 몇 개인지의 정보를 담고 있다.
OptionalHeader
-IMAGE_OPTIONAL_HEADER의 구조체 멤버.


IMAGE_FILE_HEADER

typedef struct _IMAGE_FILE_HEADER{
	WORD Machine;		//호환되는 머신
	WORD NumberOfSections;	//섹션의 개수
	DWORD TimeDateStamp;	//오브젝트 생성일자
	DWORD PointerToSymbolTable;	//COFF 심볼 테이블 주소
	DWORD NumberOfSymbols;	//심볼 개수
	WORD SizeOfOptionalHeader;	//IMAGE_OPTIONAL_HEADER 크기
	WORD Characteristics;	//파일의 정보를 OR 연산하여 표현
}IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

Machine
-현재 파일이 어느 플랫폼(CPU)에서 실행되는지에 대한 정보를 가진다.
※Machine 상수
명칭 설명
IMAGE_FILE_MACHINE_UNKNOWN 0 알 수 없음
IMAGE_FILE_MACHINE_I386 0x014C x86 계열
IMAGE_FILE_MACHINE_R3000 0x0160 MIPS Big Endian
0x0162 MIPS Little Endian
IMAGE_FILE_MACHINE_R4000 0x0166 MIPS Little Endian
IMAGE_FILE_MACHINE_R10000 0x0168 MIPS Little Endian
IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 MIPS Little Endian WCE v2
IMAGE_FILE_MACHINE_ALPHA 0x0184 Alpha_AXP
IMAGE_FILE_MACHINE_POWERPC 0x01F0 IBM PowerPC
Little Endian
IMAGE_FILE_MACHINE_SH3 0x01A2 SH3 Little Endian
IMAGE_FILE_MACHINE_SH3E 0x01A4 SH3E Little Endian
IMAGE_FILE_MACHINE_SH4 0x01A6 SH4 Little Endian
IMAGE_FILE_MACHINE_ARM 0x01C0 ARM Little Endian
IMAGE_FILE_MACHINE_THUMB 0x01C2  
IMAGE_FILE_MACHINE_IA64 0x0200 x64 계열
IMAGE_FILE_MACHINE_MIPS16 0x0266 MIPS
IMAGE_FILE_MACHINE_MIPSFPU 0x0366 MIPS
IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 MIPS
IMAGE_FILE_MACHINE_ALPHA64 0x0284 ALPHA64

NumberOfSections
-섹션을 분석하기 위해 사용되는 값이다.
TimeDateStamp
-파일이 생성된 날짜이다.
SizeOfOptionalHeader
-IMAGE_FILE_HEADER 바로 다음에 위치한 IMAGE_OPTIONAL_HEADER 구조체 크기이다.
Characteristics
-현재 파일이 exe인지 dll 파일인지의 플래그를 가진다.

※Characteristics 상수
명칭 설명
IMAGE_FILE_RELOCS_STRIPPED 0x0001 Relocation info stripped from file
IMAGE_FILE_EXCUTABLE_IMAGE 0x0002 File is executable
IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 Line numbers stripped from file
IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 Local symbols stripped from file
IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 Agressively trim working set
IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 App can handle >2gb addresses
IMAGE_FILE_BYTES_REVERSED_L0 0x0080 Bytes of machine word are reversed
IMAGE_FILE_32BIT_MACHINE 0x0100 32bit word machine
IMAGE_FILE_DEBUG_STRIPPED 0x0200 Debugging info stripped from file in .DBG file
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 If Image is on removable media, copy and run from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 If Image is on Net, copy and run from the swap file
IMAGE_FILE_SYSTEM 0x1000 System File
IMAGE_FILE_DLL 0x2000 File is a DLL
IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 File should only be run on a UP machine
IMAGE_FILE_BYTES_REVERSED_HI 0x8000 Bytes of machine word are reversed



IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER{	//표준 구조체 필드
	WORD Magic;
	BYTE MajorLinkerVersion;	//컴파일러 버전 정보
	BYTE MinorLinkerVersion;
	DWORD SizeOfCode;		//코드 전체 크기
	DWORD SizeOfInitializedData;	//초기화되는 데이터 크기
	DWORD SizeOfUninitializedData;	//초기화되지 않는 데이터 크기
	DWORD AddressOfEntryPoint;	//실행 코드의 시작 위치
	DWORD BaseOfCode;		//코드의 시작 위치

DWORD BaseOfdata; //.data 섹션의 시작 주소(RVA 값) //NT 추가 필드

	DWORD ImageBase;		//PE 파일이 매핑될 메모리 실제 시작 주소
	DWORD SectionAlignment;	//메모리상에 올려진 후의 섹션 배치간격
	DWORD FileAlignment;	

WORD MajorOperatingSystemVersion;

	WORD MinorOperatingSystemVersion;
	WORD MajorImageVersion;
	WORD MinorImageVersion;
	WORD MajorSubsystemVersion;
	WORD MinorSubsystemVersion;
	WORD Win32VersionValue;

WORD SizeOfImage; //파일의 전체 크기

	WORD SizeOfHeaders;	
	WORD 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;

SizeOfCode
-.text 섹션에 CPU가 실행하는 기계어 코드가 들어있는데 이 코드의 전체 크기이다.
SizeOfInitializedData
-프로그램 내에서 쓰이는 변수들이 저장되어 있는 섹션 영역들 중에서 데이터가 초기화 되어 있는 섹션영 역들의 집합이다.
SizeOfUninitializedData
-SizeOfInitializedData의 반대이다.
AddressOfEntryPoint
-메인 함수 시작 주소가 RVA로 저장되어 있다.
BaseOfCode
-코드영역의 시작주소가 RVA로 저장되어 있다.
BaseOfdata
-데이터영역의 시작주소가 RVA로 저장되어 있다.
ImageBase
-PE파일이 메모리에 매핑될 시작 주소로써, RVA의 기준에 되는 주소이다.
보통 exe 파일은 0x00400000의 값을 갖고 dll 파일은 0x10000000의 값을 갖는다.
SectionAlignment
-메모리상에 올려진 후의 섹션의 배치 간격이다.
※섹션 헤더에는 2가지 주소 정보가 있는데 VirualAddress 멤버는 PE 로더가 참조할 가상 주소 값이고 PointerToRawData 멤버는 메모리에 올려지지 않은 파일상의 주소이다.
FileAlignment
-파일상의 섹션 배치 간격이다.
SizeOfImage
-파일의 전체 크기이다.
SizeOfHeaders
-도스 헤더, 도스 스텁, PE 헤더, 섹션 헤더 모두를 더한 값이다.
SizeOfStackReserve
-프로그램에서 사용될 스택을 얼마만큼 예약할지의 바이트 기준 값이다.
SizeOfStackCommit
-프로그램에서 사용될 스택을 얼마만큼 commit할지의 바이트 기준 값이다.
SizeOfHeapReserve
-프로그램에서 사용될 힙을 얼마만큼 예약할지의 바이트 기준 값이다.
SizeOfHeapCommit
-프로그램에서 사용될 힙을 얼마만큼 commit할지의 바이트 기준 값이다.
DataDirectory
-Export table, Import table, Resource 영역, Exception 영역, 보안 영역, 디버그 영역등을 접근할 수 있는 주소를 가지고 있는 IMAGE_DATA_DIRECTORY 구조체 배열이다.
-이 배열에는 각 해당 영역으로 갈 수 있는 RVA 주소와 그 영역의 크기 정보를 담고 있다.


※IMAGE_DATA_DIRECTORY 구조체 배열 구성
명칭
IMAGE_DIRECTORY_ENTRY_EXPORT 0
IMAGE_DIRECTORY_ENTRY_IMPORT 1
IMAGE_DIRECTORY_ENTRY_RESOURSE 2
IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
IMAGE_DIRECTORY_ENTRY_SECURITY 4
IMAGE_DIRECTORY_ENTRY_BASERELOC 5
IMAGE_DIRECTORY_ENTRY_DEBUG 6
// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
IMAGE_DIRECTORY_ENTRY_TLS 9
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
IMAGE_DIRECTORY_ENTRY_IAT 12
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14



IMAGE_DATA_DIRECTORY

typedef struct _IMAGE_DATA_HEADER{
	DWORD VirtualAddress;
	DWORD VirtualSize;
}IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

IMAGE_SECTION_HEADER

-섹션 테이블이라고도 하며 PE 포맷의 옵셔널 헤더 바로 뒤에 구조체 배열 형식으로 위치해 있다.
-섹션의 개수만큼 섹션 헤더 배열이 있고 마지막에 null로 채워진 섹션 헤더 구조체가 위치한다.
typedef struct _IMAGE_SECTION_HEADER{
	BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
	union{
		DWORD PhysicalAddress;
		DWORD VirtualSize;
	}Misc;
	DWORD VirtualAddress;
	DWORD SizeOfRawData;
	DWORD PointerToRawData;
	DWORD PointerToRelocations;
	DWORD PointerToLinenumbers;
	WORD NumberOfRelocations;
	WORD NumberOfLinenumbers;
	DWORD Characteristics;
}IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Name
-섹션의 이름을 나타낸다. IMAGE_SIZEOF_SHORT_NAME은 8바이트 크기를 나타내는 상수이다.
-섹션의 이름으로 섹션의 성격을 파악해서는 안 되며, 섹션의 이름이 같다고 하여 항상 같은 속성을 지니 지 않기 때문에 속성을 파악하기 위해서는 Characteristics 멤버를 참조하여야 한다.

※일반적인 섹션 이름별 용도
이름 용도
.text 실행되는 코드들
.data 초기화된 전역 변수를 담고 있는 RW가능한 섹션
.rdata 읽기 전용 데이터 섹션, 문자열 표현이나 c++/com 가장 함수 테이블
.bss 초기화되지 않은 전역 변수들을 위한 섹션
.idata 다른 DLL로부터 가져다 쓰는 함수들의 정보. IMAGE_IMPORT_DESCRIPTOR의 배열로 이루어져 있으며 하나당 DLL 한 개의 정보를 담고 있다.
.edata 다른 모듈이 이 파일을 사용할 때 사용하도록 해놓은 함수 리스트

PhysicalAddress/VirtualSize
-PE로더에 의해 이미지가 메모리에 올려진 후에 해당 섹션이 얼마만큼의 크기를 가지고 있게 되는지의 정보이다.
VirtualAddress
-PE로더에 의해 이미지가 메모리에 올려진 후에 해당 섹션이 어느 주소에 위치하는지의 RVA 주소 값이 다. 이 멤버는 항상 IMAGE_OPTIONAL_HEADER의 멤버인 SectionAlignment의 배수 값을 가진다.
SizeOfRawData
-Raw data 상에서 해당 세션에 대한 실제 사용된 크기 정보를 담고 있다.
PointerToRawData
-Raw data가 파일 상의 어느 주소에 위치해 있는지 나타내는 변수이다.
Characteristics
-섹션에 대한 속성 정보를 플래그로 가지고 있다. 해당 섹션의 속성 값을 알아내기 위해서 AND 연산을 이 용한다.
ex) if(SectionHeader.Characteristics & IMAGE_SCN_MEM_READ)

※Characteristics 상수
명칭 설명

IMAGE_SCN_CNT_CODE

0x00000020 코드로 채워진 섹션

IMAGE_SCN_CNT_INITIALIZED_DATA

0x00000040 데이터가 초기화된 섹션

IMAGE_SCN_CNT_UNINITIALIZED_DATA

0x00000080
데이터가 비초기화된 섹션
IMAGE_SCN_MEM_EXECUTE 0x20000000 코드로서 실행될 수 있는 섹션
IMAGE_SCN_MEM_READ 0x40000000 읽기 가능 영역 섹션
IMAGE_SCN_MEM_WRITE 0x80000000 쓰기 가능 영역 섹션
반응형

'악성코드 분석 > 리버싱 팁' 카테고리의 다른 글

mov EDI,EDI (Hot Patching)  (0) 2010.12.21
어셈블리 코드 해석  (0) 2010.12.01