0 신민용, 한경수
1 순 서 PE File 이란 ? PE 구조를 알아야 하는 이유 개략적인 PE 구조 Section 구분이 필요한 이유 상세 구조 로더 제작 및 시연
정 의 ◦ MS WINDOWS 3.1 부터 지원되는 실행 파일의 형식을 말한다. 유닉스 COFF (Common Object file format) 를 기반으로 나왔으며, PE 포맷을 사용하는 파일의 확장자는 cpl, exe, dll, ocx, vxd, sys, scr, drv 가 있다. 다양한 운영 체제에 이식이 가능한 실행 형식 (Portable Excutable) 이라는 이름 2
프로그램 실행 원리 - 폰노이만 구조 ◦ 데이터 메모리와 프로그램 메모리가 구분되어 있지 않고 하나의 버스를 가지고 있는 구조 ◦ CPU, 메모리, 프로그램 구조를 갖는 프로그램 내장 방식 컴퓨터의 아이디어 3
디스크에서 본 실행파일 (notepad.exe) 4
메모리에서 본 실행파일 (notepad.exe) 5
CPU 에서 본 실행파일 (notepad.exe) 6
4C01 이란 ? ◦ 우선 Big Endian 과 Little Endian 을 비교해 보자 7 인텔기반 4C01 014C
4C01 이란 ? 8
의미 전달을 위해서 9 Notepad.exeVisual Studio2010 어디가 시작일까 ?
의미 전달을 위해서 ◦ 의미단위 프레임이 필요 ⇒ Protocol ◦ IP (Internet Protocol), TCP (Transmission Control Protocol) 10 IP Header UDP Header TCP Header
의미 전달을 위해서 ◦ 실행 가능한 프로그램 ⇒ PE 구조 11 Memory
실행프로그램의 수행 기능을 추가 / 변경 이번 프로젝트에서의 Packing 의 경우 ◦ 프로그램 자체 기능에 영향을 미치지 않아야 한다. ◦ Reversing 을 어렵게 만들어야 한다. 12 File 자체를 분석하지는 못하도록 실행파일을 변환시킨다. 실행 시에는 제대로 수행할 수 있도록 다시 변환시켜야 한다. File 자체를 분석하지는 못하도록 실행파일을 변환시킨다. 실행 시에는 제대로 수행할 수 있도록 다시 변환시켜야 한다.
이번 프로젝트에서의 Packing 의 경우 ◦.text,.data 에 있는 값들을 변환시킨다. 13 Section(“.pack”) Section header(“.pack”)
E0 1D8
E0 1D8 DOS 실행파일 설계자 Mark Zbikowski 의 이니셜 새로운 EXE Header 의 주소 : 0x000000E0
16 DOS 에서 실행 시 수행되는 부분 E0 1D8 16 비트 assembly 어 0D : Carrige Return(CR) 0A : Line Feed(LF) 0D : Carrige Return(CR) 0A : Line Feed(LF)
E0 1D8 PE 구조의 서명은 ‘PE’ Machine : 4C01 Section 의 수 : 0x0003 TimeStamp : 0x41107CC3 SizeOfOptionalHeader : 0x00E0 Characteristics : 0x010F Characteristics : 0x010F
E0 1D8 Magic : 0x010B(32bit) 0x020B(64bit) Magic : 0x010B(32bit) 0x020B(64bit) SizeOfCode : 0x AddressOfEntryPoint : 0x D ImageBase : 0x SectionAlignment: 0x FileAlignment: 0x SizeOfImage : 0x SizeOfHeaders : 0x Subsystem : 0x0002(GUI) 0x0001(sys, driver file) 0x0003(CUI) Subsystem : 0x0002(GUI) 0x0001(sys, driver file) 0x0003(CUI) NumberOfRvaAndSizes : 0x
E0 1D8 Name : “.text” VirtualSize: 0x x VirtualAddress: 0x SizeOfRawData: 0x x x x PointerToRawData: 0x Characteristics: 0x x
E0 1D8 0x x x x x 구 분구 분주 소주 소 파일에서 시작주소 0x 파일에서 섹션크기 0x 메모리에서 시작주소 (RVA)0x 메모리에서 섹션크기 0x ImageBase0x x00007B48 0x00007BFF 0x00007C00 0x00007B48
PE format IMAGE_DOS_HEADER MS-DOS Stub Program IMAGE_NT_HEADERS IMAGE_SECTION_HEADER.text IMAGE_SECTION_HEADER.dat a IMAGE_SECTION_HEADER.rsr c Section body (.text) Section body (.data) Section body (.rsrsc) IMAGE_NT_HEADERS DWORD Signature; IMAGE_FILE_HEADER IMAGE_OPTIONAL_HEADER32
왜 PE 파일은 여러 개의 섹션을 두었는가 ? 안전성 Code : 실행, 읽기 권한 Data : 읽기, 쓰기 권한 Resource : 읽기 권한
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;
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 – 0x x400 = 0x3C00 Ex2 ) RVA = 0x9550 의 FileOffset 은 ? FileOffset = 0x9550 – 0x x7C00 = 0x8150 0x1000 <= 0x4880 < 0x x7748 0x9000 <= 0x9550 < 0x x1BA8
Import Address Table - 0 Export Address Table Import Address Table
Import Address Table - 1 IAT – 어떤 프로그램에서 어떤 라이브러리 를 사용하는지 기술한 테이블. Programs A.EXE B.EXE C.EXE D.EXE Dll files comdlg32.dll SHELL32.dll COMCTL32.dll msvcrt.dll ADVAPI32.dll
Import Address Table - 2 Call 7C8107F0 과 똑같은 효과. 하지만 왜 call [ ] 로 쓸까 ? 파일이 실행되는 순간 PE Loader 가 의 위치에 CreateFileW 의 주소를 입력
Import Address Table - 3 typedef 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 – 0 Kernel32.dll 을 KPloader 로 열어본 모습 Export Address Table
Export Address Table – 1 EAT(Export Address Table) 은 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 매커니즘. Kernel32.dll 의 RVA : 0x262C 를 offset 으로 변환해보면 0x262C – 0x x400 = 0x1A2C 가 됩니다.
Export Address Table - 2 typedef 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 = h TimeDateStamp = 49C4D12Eh MajorVersion = 0000h MinorVersion = 0000h Name = 00004B98h Base = h NumberOfFunctions = BAh NumberOfNames = BAh AddressOfFunctions = h AddressOfNames = Ch AddressOfNameOrdinals = h AddressOfNames 멤버의 값은 RVA = 353Ch 이므로 file offset = 293Ch
Export Address Table - 5 file offset = 293Ch [0x00003FBD] 를 따라가보면, … 찾았다. AddAtomW 를 찾았음 RVA = 4BBDh 은 file offset = 3FBDh Characteristics = h TimeDateStamp = 49C4D12Eh MajorVersion = 0000h MinorVersion = 0000h Name = 00004B98h Base = h NumberOfFunctions = BAh NumberOfNames = BAh AddressOfFunctions = h AddressOfNames = Ch AddressOfNameOrdinals = h AddressOfFunctions 멤버의 값은 RVA = 2654h 이므로 file offset = 1A54h AddressOfFunctions[ordinal(2)] = 326F1 kernel32.dll 의 ImageBase = 7C7D0000h 입니다. 따라서 "AddAtomW" 함수의 실제 주소 (VA) 는 7C8026F1h
로더 제작 및 시연 37
38 - END -