Upload
aram
View
301
Download
1
Tags:
Embed Size (px)
DESCRIPTION
PE(Portable Executable) File 구조. 신민용 , 한경수. 2011 년 Keeper – 보안 기술문서 – Packing. 순 서. PE File 이란 ? PE 구조를 알아야 하는 이유 개략적인 PE 구조 Section 구분이 필요한 이유 상세 구조 로더 제작 및 시연. PE File 이란 ?. 정 의 - PowerPoint PPT Presentation
Citation preview
PE(Portable Executable) File 구조
2011 년 Keeper – 보안 기술문서 – Packing
신민용 , 한경수
순 서PE File 이란 ?PE 구조를 알아야 하는 이유개략적인 PE 구조Section 구분이 필요한 이유상세 구조로더 제작 및 시연
PE File 이란 ?
정 의
◦ MS WINDOWS 3.1 부터 지원되는 실행 파일의 형식을
말한다 . 유닉스 COFF(Common Object file format) 를
기반으로 나왔으며 , PE 포맷을 사용하는 파일의 확장자는
cpl, exe, dll, ocx, vxd, sys, scr, drv 가 있다 .
다양한 운영 체제에 이식이 가능한 실행 형식 (Portable
Excutable) 이라는 이름
3
PE File 이란 ?
프로그램 실행 원리 - 폰노이만 구조
◦ 데이터 메모리와 프로그램 메모리가 구분되어 있지 않고
하나의 버스를 가지고 있는 구조
◦ CPU, 메모리 , 프로그램 구조를 갖는 프로그램 내장
방식
컴퓨터의 아이디어
4
PE File 이란 ?
디스크에서 본 실행파일 (notepad.exe)
5
PE File 이란 ?
메모리에서 본 실행파일 (notepad.exe)
6
PE File 이란 ?
CPU 에서 본 실행파일 (notepad.exe)
7
PE File 이란 ?
4C01 이란 ?◦ 우선 Big Endian 과 Little Endian 을 비교해 보자
8
인텔기반
4C01 014C
PE File 이란 ?
4C01 이란 ?
9
PE File 이란 ?
의미 전달을 위해서
10
Notepad.exeVisual Studio2010
어디가 시작일까 ?
PE File 이란 ?
의미 전달을 위해서
◦ 의미단위 프레임이 필요 ⇒ Protocol
◦ IP(Internet Protocol), TCP(Transmission Control Protocol)
11
IP Header
UDP Header
TCP Header
PE File 이란 ?
의미 전달을 위해서
◦ 실행 가능한 프로그램 ⇒ PE 구조
12
Memory
PE 구조를 알아야 하는 이유 실행프로그램의 수행 기능을 추가 / 변경
이번 프로젝트에서의 Packing 의 경우
◦ 프로그램 자체 기능에 영향을 미치지 않아야 한다 .
◦ Reversing 을 어렵게 만들어야 한다 .
13
• File 자체를 분석하지는 못하도록 실행파일을 변환시킨다 .• 실행 시에는 제대로 수행할 수 있도록 다시 변환시켜야 한다 .
PE 구조를 알아야 하는 이유 이번 프로젝트에서의 Packing 의 경우
◦ .text, .data 에 있는 값들을 변환시킨다 .
14
Section(“.pack”)
Section header(“.pack”)
개략적인 PE 구조
15
DOS headerDOS stub
NT headersSection head-
ersSection bodies
0000400E01D8
개략적인 PE 구조 – DOS header
16
DOS headerDOS stub
NT headersSection head-
ersSection bodies
0000400E01D8
DOS 실행파일 설계자 Mark Zbikowski 의 이니셜
새로운 EXE Header 의 주소 : 0x000000E0
개략적인 PE 구조 – DOS stub
17
DOS 에서 실행 시 수행되는 부분DOS header
DOS stubNT headersSection head-
ersSection bodies
0000400E01D8 16 비트 assembly 어
0D : Carrige Return(CR)0A : Line Feed(LF)
개략적인 PE 구조 – NT headers
18
DOS headerDOS stub
NT headersSection head-
ersSection bodies
0000400E01D8
PE 구조의 서명은 ‘ PE’
Machine : 4C01Section 의 수 : 0x0003
TimeStamp : 0x41107CC3SizeOfOptionalHeader :
0x00E0Characteristics : 0x010F 101111
개략적인 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
개략적인 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
개략적인 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
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)
왜 PE 파일은 여러 개의 섹션을 두었는가 ?
안전성Code : 실행 , 읽기 권한Data : 읽기 , 쓰기 권한Resource : 읽기 권한
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;
RVA to FileOffset – 1• 우리가 다룰 주소의 종류는 크게 네가지로 나눌 수 있다 . – Physics Address– VA : Virtual Address– RVA : Relative Virtual Address– RawOffset ≡ FileOffset
• 지금까지 다루어지던 주소들은 모두 RVA 로써 RVA 를 FileOffset 으로 변환을 하려면 조금의 연산이 필요하다 .
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
Import Address Table - 0
Export Address TableImport Address Table
Import Address Table - 1• IAT – 어떤 프로그램에서 어떤 라이브러리를 사용하는지 기술한 테이블 .
ProgramsA.EXEB.EXEC.EXED.EXE
Dll filescomdlg32.dllSHELL32.dll COMCTL32.dll msvcrt.dll ADVAPI32.dll
Import Address Table - 2
Call 7C8107F0 과 똑같은 효과 . 하지만 왜 call [1001104] 로 쓸까 ?
파일이 실행되는 순간 PE Loader 가 01001104 의 위치에 CreateFileW 의 주소를 입력
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
Import Address Table – 4
RVA to Offset 변환
cmddlg32.dll 의 Original First Thunk
Export Address Table – 0Kernel32.dll 을 KPloader 로 열어본 모습
Export Address Table
Export Address Table – 1EAT(Export Address Table) 은 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 매커니즘 .
Kernel32.dll 의 RVA : 0x262C 를 offset 으로 변환해보면0x262C – 0x1000 + 0x400 = 0x1A2C 가 됩니다 .
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;
Export Address Table - 3
그렇다면 “ AddAtomW” 함수를 kernel32.dll 에서어느 위치에 있는지 어떻게 알아낼 수 있을까 ?
1. AddressOfNames 멤버의 값으로 이동2. AddressOfNames 의 값으로 가면 문자열 주소가 저장되어 있음 . 문자열 비교를 통하여 원하는 함수 이름을 찾음 . 이 때의 배열 인덱스를 "idx" 라고 하겠습니다 .
3. AddressOfNameOrdinals 멤버의 값을 통해 "ordinal 배열 " 로 이동4. "ordinal 배열 " 에서 "idx" 로 해당 "ordinal_idx" 값을 찾습니다 .
5. AddressOfFunctions 로 이동하여 ordinal_idx 멤버를 이용해 함수의 시작 주소를 얻습니다 .
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
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
38
로더 제작 및 시연
39
- END -