본문 바로가기

리버싱/리버싱기초

PE파일 구조

PE파일 분석 도구 : 


PEview0.9.8.zip



 실행파일(Executable File)이란 명령(Operation Codes)에 따라 지시된 작업을 수행하도록 하는 파일을 말한다. 이 파일은 실행 코드, 전역 데이터, Import/Export 함수정보, 리소스 데이터 등으로 구성된다. 포맷 종류는 PE(Windows), ELF(Linux, Unix), Mach-O(OS X,iOS), DEX(Android), MZ(Dos)등이 있다. 


 이때 PE(Portable Executable)파일은 Windows 3.1부터 지원되는 실행파일 형식이다. 이는 유닉스의 COFF(Common Object File Format)를 기반으로 하고 파일 종류는 실행파일(EXE, SCR), 라이브러리(DLL, OCX), 드라이버(SYS), 오브젝트파일(OBJ) 등이 있다.


 프로그램이 프로세스가 되면 관련 데이터가 메모리에 올라가게 된다. 운영체제는 가상 메모리를 사용하기 때문에 우리는 실제 주소로 데이터 및 코드를 참조하지 않는다. 페이징 기법으로 인해 물리 메모리는 프레임으로 나누어져 있고 논리 메모리는 페이지로 구분된다. 세그멘테이션 기법은 프로그램을 코드, 데이터, 리소스등을 분리해서 저장하는 방식이다. 


 메모리 상의 주소 표현방식은 다음과 같다.

    - VA(Virtual Address): 가상 메모리상의 절대주소

    - RVA(Relative Virtual Address): 기준(ImageBase) 위치에서의 상대주소

    - PE 파일 내부데이터는 RVA 형식으로 메모리위치가 지정됨

    - VA = ImageBase+ RVA

    - RAW: PE 파일내에서의오프셋(offset)


 PE파일이 메모리에 올라가면 헤더는 동일하나 바디부분은 참조 위치가 조금 변하게 된다. 아래 그림은 PE 파일 구조와 메모리에 올라갔을 때의 구조를 표현한 그림이다.





- Dos Header, Dos Stub : DOS 시절 사용 (현재 사용 안 함)


- NTHeader : 

    - 메모리에 올리기 위해 필요한 정보

    - 파일 속성 정보


- Section Header : 세션에 관한 읽기, 쓰기 정책

    - 세션에 관한 읽기, 쓰기 정책

    - 세션 크기 및 기타 정보


- Section : 세션에 대한 내용

    - 섹션의 종류는 아래 표와 같다.


 종류

 이름 

 설명 

 Code

 .text

 프로그램 실행을 위한 코드

 Data

 .data

 초기화된 전역변수 (읽기,쓰기 가능)

 .rdata

 읽기 전용 변수 (문자열, C++가상함수)

 .bss

 초기화 되지 않은 전역변수(.data에병합)

 Import API

 .idata

 Import할 DLL과 그 API에 대한 정보 (IAT) (.rdata에 병합)

 .didat

 Delay-loading importDLL 정보

 (프로그램 실행 후 DLL 사용시에만 연결)

 (릴리즈 모드 시 다른 섹션에 병합)

 Export API

 .edata

 Export할 API 정보 (주로 DLL에서 사용)

 (.text또는 .rdata에 합병)

 Resource

 .rsrc

 리소스 관련 데이터

 재배치정보

 .reloc

 기본 재배치 정보(주로 DLL에서 사용)

 TLS

 .tls

 (__declspec(thread) 지시어와 함께 선언되는 스레드 지역 저장소

 Debugging

 .debug$p

 미리 컴파일된 헤더 사용시에만 존재



1. IMAGE_DOS_HEADER (64바이트)



- e_magic : DOS signature -> MZ

    - MZ : Mark Zbikowski 

    - DOS실행파일을 설계한 사람 이니셜


-e_lfanew : NT header RVA형태의 주소값

    - 꼭 40이상의 크기를 가질 필요 없음

    - 변종 PE를 가능하게함





2. MS-DOS Stub Program (가변적)


- DOS용 실행코드와 데이터로 구성

- 16비트 형태 

- 고정되지 않은 크기

- 없어도 됨




3. IMAGE_NT_HEADER (248바이트)



1) PE Signature(4바이트) : 0x504500 (PE  )



2) IMAGE_FILE_HEADERS(20바이트)


- Machine : CPU별로 고유한 값
    - IA-32 호환 CPU : 14Ch의 값
    - IA-64 호환 CPU : 200h의 값

- NumberOfSections : PE 파일에 포함된 섹션의 수(반드시 0보다 큼)
    - Section들의 개수 (최소 1개 이상)

- TimeDateStamp : PE파일이 만들어진 시간(Unixtime 포맷, UTC)

- SizeOfOptionalHeader 
    - IMAGE_OPTIONAL_HEADER32의 구조체의 크기
    - 변종 PE를 가능하게 함

- Characteristics
    - 파일의 속성(아래 표 참고)


 정의

 값 

 정보 

 IMAGE_FILE_RELOCS_STRIPPED

0x0001

 재배치 정보가 없음

 IMAGE_FILE_EXECUTABLE_IMAGE

0x0002

 실행 file image

 IMAGE_FILE_LINE_NUMS_STRIPPED

0x0004

 Line 정보가 없음

 IMAGE_FILE_LOCAL_SYMS_STRIPPED

0x0008

 Local 심볼이 없음

 IMAGE_FILE_AGGRESIVE_WS_TRIM

0x0010

 OS가 적극적으로 working set처리

 IMAGE_FILE_LARGE_ADDRESS_AWARE

0x0020

 어플리케이션이 2g이상의 주소를 제어

 IMAGE_FILE_BYTES_REVERSED_LO

0x0080

 Bytes of machine word are reversed.

 IMAGE_FILE_32BIT_MACHINE

0x0100

 32비트 워드 머신 필요

 IMAGE_FILE_DEBUG_STRIPPED

0x0200

 디버깅 정보가 .dbg파일에 존재

 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP

0x0400

 이동장치에 존재시swap파일로 고정 디스크에 복사후 실행

 IMAGE_FILE_NET_RUN_FROM_SWAP

0x0800

 네트워크에 존재시swap파일로 고정 디스크에 복사후 실행

 IMAGE_FILE_SYSTEM

0x1000

 System File. 

 IMAGE_FILE_DLL

0x2000

 File is a DLL.  

 IMAGE_FILE_UP_SYSTEM_ONLY

0x4000

 하나의 processor 장착 기기에만 실행

 IMAGE_FILE_BYTES_REVERSED_HI

0x8000

 Bytes of machine word are reversed. 




3) IMAGE_OPTIONAL_HEADER(224바이트)



- Magic : 32bit -> 10Bh or 64bit -> 20Bh


- SizeOfCode : 실행 코드가 포함된 섹션의 크기 (보통 .text)


- AddressOfEntryPoint : EP(Entry Point)의 RVA 주소값

    - 실제 EP 주소 값  : AddressOfEntryPoint+ImageBase

    - 이 값을 통해 패킹 여부를 알 수 있음


- ImageBase : PE파일이 맵핑 되는 시작 주소

    - 메모리(가상주소공간) 내에 PE 파일이 로딩되는 시작주소

    - EXE 기본 ImageBase: 0x00400000

    - DLL 기본 ImageBase: 0x01000000

    - 링크시 옵션 /BASE를 사용하여 변경 가능


- SectionAlignment : 메모리에서 섹션의 최소 저장 단위

    - Memory Mapped File의성질에 의해 메모리페이지의 배수가 사용됨

    - 섹션 크기는 최소 저장 단위의 배수가 되어야하며, 나머지는 NULL 값으로 채워짐


- FileAlignment : 파일에서 섹션의 최소 저장 단위

    - 일반적으로 섹터크기(512바이트)

    - 섹션 크기는 최소 저장 단위의 배수가 되어야하며, 나머지는 NULL 값으로 채워짐


- NULL padding : 4,5번의 최소단위를 맞추기 위해 section들이 끝나면 NULL값을 집어넣음


- SizeOfImage : PE구조의 크기(메모리)

    - 반드시 SectionAlignment의 배수가 되어야함


- SizeOfHeader : PE header의 크기

    - DOS Header, NT Header, Section Table을 모두 합한 크기

    - 반드시 SectionAlignment의 배수가 되어야함


- Subsystem : 

    - 드라이브 파일 SYS,VXD

    - GUI 파일

    - CLI 파일


- NumberOfRvaAndSizes : 

    - 바로 밑의 구조체 배열 IMAGE_DATA_DIRECTORY 구조체 배열의 원소 개수

    - 항상 16의 값을 가짐(0x00000010)

    - 여기까지 96바이트


- IMAGE_DATA_DIRECTORY  DataDirectory[16]

    - 가상 주소(4바이트)와 크기(4바이트)로 구성
    - 8바이트 * 16개 = 128바이트
    - 아래 표 참고



 순서

 이름

 설명 

 0 

 EXPORT

 IMAGE_DIRECTORY_ENTRY_EXPORT 구조체를 가리킴

1

 IMPORT

 IMAGE_IMPORT_DESCRIPTOR 구조체를 가리킴 

2

 RESOURCE

 IMAGE_RESOURCE_DIRECTORY 구조체를 가리킴 

3

 EXECPTION

 IMAGE_RUNTIME_FUNCTION_ENTRY 구조체를 가리킴(예외 핸들러 테이블) 

4

 SECURITY

 WIN_CERTIFICATE 구조체를 가리킴, PE 파일 상에서 offset을 가리킴 

5

 BASERELOC

 ImageBase 필드에 지정된 가상 주소 공간에 위치시키지 못했을 때, 코드 상의 포인터 연산과 관련된 주소를 다시 갱신 

6

 DEBUG

 IMAGE_DEBUG_DIRECTORY 구조체 배열을 기리키며, 디버그 관련 정보가 있음 

7

 ARCHITECTURE

 IMAGE_ARCHITECTURE_HEADER 구조체를 가리킴
 x86, IA-64 계열에서 사용되지 않음 
 (DEC/CompaqAlpha 계열에서 사용된 것으로 알려짐)

8

 GLOBALPTR

 IMAGE_DATA_DIRECTORY 엔트리의 VirtualAddress 필드는 글로벌 포인터로 사용되는 RVA., IA-64 계열에서 사용됨, SIZE는 사용되지 않음 

9

 TLS

 스레드 지역 저장소 초기화 세션에 대한 포인터,

 _declspec(thread)라는 지시어를 통해 변수를 선언하면 TLS에 들어가게되며, 링커는 별도의 TLS 섹션을 만듬 

10

 LOAD_CONFIG

 IMAGE_LOAD_CONFIG_DIRECTORY 구조체에 대한 포인터 

11

 BOUND_IMPORT

 IMAGE_BOUND_IMPORT_DESCRIPTOR 구조체의 배열을 가리키는 포인터

 DLL 바인딩과 관련된 정보를 담고 있음 

12

 IAT

 IAT의 시작번지를 가리킴 

13

 DELAY_IMPORT

 DELAYIMP.h 헤더에 정의되어 있는 ImgDelayDescr 구조체의 배열을 가리키는 지연 로딩 정보에 대한 포인터 

14

 COM_DESCRIPTOR

 .NET 프로그램이나 DLL용 PE를 위한 것

15

 RESERVED

 예약된 영역 






4. IMAGE_SECTION_HEADER (1개 섹션 크기당 40바이트)


섹션의 수는 Image File Header의 NumberOfSections필드에 명시됨



- Name : 섹션이름(단순참고정보,최대8 바이트)


- VirtualSize : 메모리에서 섹션 데이터의 실제바이트수


- VirtualAddress : 메모리에서 해당 섹션이 시작하는 주소(RVA)


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


- PointerToRawData :  파일에서 섹션의 시작 위치(RVA)


- Characteristics : Section의 속성 

    - 아래 표 참고(이것보다 더 정의됨 winnt.h 참고)


 정의 

 값  

 정보 

 IMAGE_SCN_CNT_CODE

 0x00000020

 Section contains code.

 IMAGE_SCN_CNT_INITIALIZED_DATA

 0x00000040

 Section contains initialized data.

 IMAGE_SCN_CNT_UNINITIALIZED_DATA

 0x00000080

 Section contains uninitialized data.

 IMAGE_SCN_MEM_EXECUTE

 0x20000000

 Section is executable.

 IMAGE_SCN_MEM_READ

 0x40000000

 Section is readable.

 IMAGE_SCN_MEM_WRITE 0x80000000 Section is writeable.