PE(Portable Executable) File 구조

39
PE(Portable Executable) File 구구 2011 구 Keeper – 구구 구구구구 – Packing 구구구 , 구구구

description

PE(Portable Executable) File 구조. 신민용 , 한경수. 2011 년 Keeper – 보안 기술문서 – Packing. 순 서. PE File 이란 ? PE 구조를 알아야 하는 이유 개략적인 PE 구조 Section 구분이 필요한 이유 상세 구조 로더 제작 및 시연. PE File 이란 ?. 정 의 - PowerPoint PPT Presentation

Transcript of PE(Portable Executable) File 구조

Page 1: PE(Portable Executable)  File  구조

PE(Portable Executable) File 구조

2011 년 Keeper – 보안 기술문서 – Packing

신민용 , 한경수

Page 2: PE(Portable Executable)  File  구조

순 서PE File 이란 ?PE 구조를 알아야 하는 이유개략적인 PE 구조Section 구분이 필요한 이유상세 구조로더 제작 및 시연

Page 3: PE(Portable Executable)  File  구조

PE File 이란 ?

정 의

◦ MS WINDOWS 3.1 부터 지원되는 실행 파일의 형식을

말한다 . 유닉스 COFF(Common Object file format) 를

기반으로 나왔으며 , PE 포맷을 사용하는 파일의 확장자는

cpl, exe, dll, ocx, vxd, sys, scr, drv 가 있다 .

다양한 운영 체제에 이식이 가능한 실행 형식 (Portable

Excutable) 이라는 이름

3

Page 4: PE(Portable Executable)  File  구조

PE File 이란 ?

프로그램 실행 원리 - 폰노이만 구조

◦ 데이터 메모리와 프로그램 메모리가 구분되어 있지 않고

하나의 버스를 가지고 있는 구조

◦ CPU, 메모리 , 프로그램 구조를 갖는 프로그램 내장

방식

컴퓨터의 아이디어

4

Page 5: PE(Portable Executable)  File  구조

PE File 이란 ?

디스크에서 본 실행파일 (notepad.exe)

5

Page 6: PE(Portable Executable)  File  구조

PE File 이란 ?

메모리에서 본 실행파일 (notepad.exe)

6

Page 7: PE(Portable Executable)  File  구조

PE File 이란 ?

CPU 에서 본 실행파일 (notepad.exe)

7

Page 8: PE(Portable Executable)  File  구조

PE File 이란 ?

4C01 이란 ?◦ 우선 Big Endian 과 Little Endian 을 비교해 보자

8

인텔기반

4C01 014C

Page 9: PE(Portable Executable)  File  구조

PE File 이란 ?

4C01 이란 ?

9

Page 10: PE(Portable Executable)  File  구조

PE File 이란 ?

의미 전달을 위해서

10

Notepad.exeVisual Studio2010

어디가 시작일까 ?

Page 11: PE(Portable Executable)  File  구조

PE File 이란 ?

의미 전달을 위해서

◦ 의미단위 프레임이 필요 ⇒ Protocol

◦ IP(Internet Protocol), TCP(Transmission Control Protocol)

11

IP Header

UDP Header

TCP Header

Page 12: PE(Portable Executable)  File  구조

PE File 이란 ?

의미 전달을 위해서

◦ 실행 가능한 프로그램 ⇒ PE 구조

12

Memory

Page 13: PE(Portable Executable)  File  구조

PE 구조를 알아야 하는 이유 실행프로그램의 수행 기능을 추가 / 변경

이번 프로젝트에서의 Packing 의 경우

◦ 프로그램 자체 기능에 영향을 미치지 않아야 한다 .

◦ Reversing 을 어렵게 만들어야 한다 .

13

• File 자체를 분석하지는 못하도록 실행파일을 변환시킨다 .• 실행 시에는 제대로 수행할 수 있도록 다시 변환시켜야 한다 .

Page 14: PE(Portable Executable)  File  구조

PE 구조를 알아야 하는 이유 이번 프로젝트에서의 Packing 의 경우

◦ .text, .data 에 있는 값들을 변환시킨다 .

14

Section(“.pack”)

Section header(“.pack”)

Page 15: PE(Portable Executable)  File  구조

개략적인 PE 구조

15

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

Page 16: PE(Portable Executable)  File  구조

개략적인 PE 구조 – DOS header

16

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

DOS 실행파일 설계자 Mark Zbikowski 의 이니셜

새로운 EXE Header 의 주소 : 0x000000E0

Page 17: PE(Portable Executable)  File  구조

개략적인 PE 구조 – DOS stub

17

DOS 에서 실행 시 수행되는 부분DOS header

DOS stubNT headersSection head-

ersSection bodies

0000400E01D8 16 비트 assembly 어

0D : Carrige Return(CR)0A : Line Feed(LF)

Page 18: PE(Portable Executable)  File  구조

개략적인 PE 구조 – NT headers

18

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

PE 구조의 서명은 ‘ PE’

Machine : 4C01Section 의 수 : 0x0003

TimeStamp : 0x41107CC3SizeOfOptionalHeader :

0x00E0Characteristics : 0x010F 101111

Page 19: PE(Portable Executable)  File  구조

개략적인 PE 구조 – NT headers

19

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

Magic : 0x010B(32bit)

0x020B(64bit)SizeOfCode : 0x00007800

AddressOfEntryPoint : 0x0000739DImageBase : 0x01000000SectionAlignment: 0x00100000FileAlignment: 0x00200000SizeOfImage : 0x00014000SizeOfHeaders :

0x00000400Subsystem : 0x0002(GUI)0x0001(sys, driver file)0x0003(CUI)

NumberOfRvaAndSizes : 0x00000010

Page 20: PE(Portable Executable)  File  구조

개략적인 PE 구조 – Section headers

20

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

Name : “.text”VirtualSize: 0x00007748

0x00007748

VirtualAddress: 0x00001000

SizeOfRawData: 0x00007800

0x000010000x000078000x00000400

PointerToRawData: 0x00000400

Characteristics: 0x60000020

0x60000020

Page 21: PE(Portable Executable)  File  구조

개략적인 PE 구조 – Section headers

21

DOS headerDOS stub

NT headersSection head-

ersSection bodies

0000400E01D8

0x00007748

0x000010000x000078000x00000400

0x60000020

구 분 주 소파일에서 시작주소 0x00000400파일에서 섹션크기 0x00007800

메모리에서 시작주소 (RVA) 0x00001000메모리에서 섹션크기 0x00007748

ImageBase 0x01000000

0x00007B48

0x00007BFF

0x00007C000x00007B48

Page 22: PE(Portable Executable)  File  구조

PE formatIMAGE_DOS_HEADERMS-DOS Stub ProgramIMAGE_NT_HEADERS

IMAGE_SECTION_HEADER .text

IMAGE_SECTION_HEADER .data

IMAGE_SECTION_HEADER .rsrc

------------------------------------

Section body (.text)

Section body (.data)

Section body (.rsrsc)

Page 23: PE(Portable Executable)  File  구조

왜 PE 파일은 여러 개의 섹션을 두었는가 ?

안전성Code : 실행 , 읽기 권한Data : 읽기 , 쓰기 권한Resource : 읽기 권한

Page 24: PE(Portable Executable)  File  구조

IMAGE_SECTION_HEADERBYTE 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;

Page 25: PE(Portable Executable)  File  구조

RVA to FileOffset – 1• 우리가 다룰 주소의 종류는 크게 네가지로 나눌 수 있다 . – Physics Address– VA : Virtual Address– RVA : Relative Virtual Address– RawOffset ≡ FileOffset

• 지금까지 다루어지던 주소들은 모두 RVA 로써 RVA 를 FileOffset 으로 변환을 하려면 조금의 연산이 필요하다 .

Page 26: PE(Portable Executable)  File  구조

RVA to FileOffset – 2• RVA – BaseVirtualAddress + PointerToRawData = FileOffset

• Ex1 ) RVA = 0x4880 의 FileOffset 은 ?• FileOffset = 0x4880 – 0x1000 + 0x400 = 0x3C00• Ex2 ) RVA = 0x9550 의 FileOffset 은 ?• FileOffset = 0x9550 – 0x9000 + 0x7C00 =

0x8150

0x1000 <= 0x4880 < 0x1000 + 0x77480x9000 <= 0x9550 < 0x9000 + 0x1BA8

Page 27: PE(Portable Executable)  File  구조

Import Address Table - 0

Export Address TableImport Address Table

Page 28: PE(Portable Executable)  File  구조

Import Address Table - 1• IAT – 어떤 프로그램에서 어떤 라이브러리를 사용하는지 기술한 테이블 .

ProgramsA.EXEB.EXEC.EXED.EXE

Dll filescomdlg32.dllSHELL32.dll COMCTL32.dll msvcrt.dll ADVAPI32.dll

Page 29: PE(Portable Executable)  File  구조

Import Address Table - 2

Call 7C8107F0 과 똑같은 효과 . 하지만 왜 call [1001104] 로 쓸까 ?

파일이 실행되는 순간 PE Loader  가 01001104 의 위치에 CreateFileW 의 주소를 입력

Page 30: PE(Portable Executable)  File  구조

Import Address Table - 3typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics DWORD OriginalFirstThunk; //IMAGE_IMPORT_BY_NAME array } DUMMYUNIONNAME; DWORD TimeDateStamp;

DWORD ForwarderChain; DWORD Name; // dll 이름 DWORD FirstThunk; //dll 안에 있는 함수주소들이 하드코딩되어있다 . } IMAGE_IMPORT_DESCRIPTOR

Page 31: PE(Portable Executable)  File  구조

Import Address Table – 4

RVA to Offset 변환

cmddlg32.dll 의 Original First Thunk

Page 32: PE(Portable Executable)  File  구조

Export Address Table – 0Kernel32.dll 을 KPloader 로 열어본 모습

Export Address Table

Page 33: PE(Portable Executable)  File  구조

Export Address Table – 1EAT(Export Address Table)  은 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 매커니즘 .

Kernel32.dll 의 RVA : 0x262C 를 offset 으로 변환해보면0x262C – 0x1000 + 0x400 = 0x1A2C 가 됩니다 .

Page 34: PE(Portable Executable)  File  구조

Export Address Table - 2typedef struct _IMAGE_EXPORT_DIRECTORY {    DWORD   Characteristics;    DWORD   TimeDateStamp;              WORD    MajorVersion;    WORD    MinorVersion;    DWORD   Name;                   // dll 이름을 가르키는 주소 DWORD   Base;                       DWORD   NumberOfFunctions;      // 실제 함수의 개수 ( 전체 )    DWORD   NumberOfNames;          // 이름을 가지는 함수의 개수 DWORD   AddressOfFunctions; // 함수의 주소배열을 가르키는 주소 DWORD   AddressOfNames;         // address of functino name string array    DWORD   AddressOfNameOrdinals;  // address of ordinal array} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

Page 35: PE(Portable Executable)  File  구조

Export Address Table - 3

그렇다면 “ AddAtomW” 함수를 kernel32.dll 에서어느 위치에 있는지 어떻게 알아낼 수 있을까 ?

1. AddressOfNames 멤버의 값으로 이동2. AddressOfNames 의 값으로 가면 문자열 주소가 저장되어 있음 . 문자열 비교를 통하여 원하는 함수 이름을 찾음 .  이 때의 배열 인덱스를 "idx" 라고 하겠습니다 .

3. AddressOfNameOrdinals 멤버의 값을 통해 "ordinal 배열 " 로 이동4. "ordinal 배열 " 에서 "idx" 로 해당 "ordinal_idx" 값을 찾습니다 . 

5. AddressOfFunctions 로 이동하여 ordinal_idx 멤버를 이용해 함수의 시작 주소를 얻습니다 .

Page 36: PE(Portable Executable)  File  구조

Export Address Table - 4실제 kernel32.dll  파일의 EAT 에서 AddAtomW  함수 주소를 찾는 과정앞에서 kernel32.dll  의 IMPORT_EXPORT_DIRECTORY 구조체 file offset  은 1A2Ch  였음

Characteristics       = 00000000hTimeDateStamp         = 49C4D12EhMajorVersion          =     0000hMinorVersion          =     0000hName                  = 00004B98hBase                  = 00000001hNumberOfFunctions     = 000003BAhNumberOfNames         = 000003BAhAddressOfFunctions    = 00002654hAddressOfNames        = 0000353ChAddressOfNameOrdinals = 00004424h

AddressOfNames 멤버의 값은 RVA = 353Ch 이므로 file offset = 293Ch

Page 37: PE(Portable Executable)  File  구조

Export Address Table - 5file offset = 293Ch

[0x00003FBD] 를 따라가보면 , … 찾았다 . AddAtomW 를 찾았음 RVA = 4BBDh 은 file offset = 3FBDh

Characteristics       = 00000000hTimeDateStamp         = 49C4D12EhMajorVersion          =     0000hMinorVersion          =     0000hName                  = 00004B98hBase                  = 00000001hNumberOfFunctions     = 000003BAhNumberOfNames         = 000003BAhAddressOfFunctions    = 00002654hAddressOfNames        = 0000353ChAddressOfNameOrdinals = 00004424h

AddressOfFunctions 멤버의 값은 RVA = 2654h 이므로 file offset = 1A54h

AddressOfFunctions[ordinal(2)] = 326F1

kernel32.dll 의 ImageBase = 7C7D0000h 입니다 .따라서 "AddAtomW" 함수의 실제 주소 (VA) 는 7C8026F1h 

Page 38: PE(Portable Executable)  File  구조

38

로더 제작 및 시연

Page 39: PE(Portable Executable)  File  구조

39

- END -