Download presentation
Presentation is loading. Please wait.
1
PE Format Guo Yu
2
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
3
PE Overview PE files are derived from the Common Object File Format (COFF) found on VAX/VMS Why “Portable” ? versatility in numerous environments of operating system software architecture. x86, MIPS®, Alpha NT Team (from Digital)
4
PE Overview EXE, DLL, SYS, CPL Windows Kernel .NET framework support
ntoskrnl.exe .NET framework support
5
Why Learn PE Format PE structures everywhere
EXE, DLL files in hard-disks Modules in process memory space Loaded from PE files PE structures support dynamic loading and dynamic linking User process memory space Kernel memory space Kernel image and various device drivers
6
Utilities Hex file viewer (tools) Static PE files viewer
Ultra-editor (not free) WinHex (not free) HT Editor, BIEW, Hiew, Static PE files viewer PE Explorer (not free) LordPE (free) Stud_PE (free) , Dynamic PE images viewer Ollydbg (free), SoftICE (not free)
7
Example hello.exe
8
PE Structure: Overview
9
PE Structure DOS Header Base Address PE Header Opt Header Header
Data DIR Sections Table Padding Section #1 Section #2
10
PE Loading PE files in disk DOS Header DOS Header PE Header PE Header
Opt Header Sections Table Data DIR DOS Header PE Header Opt Header Data DIR Sections Table Section #1 Section #1 Loading Section #2 Section #2 PE Images in Mem
11
PE Loading Not direct mapping Simple loading Almost same, but
Memory Alignment (bigger) File Alignment (smaller) Drop useless sections Relocation Simple loading Main advantage
12
Relocation Quiz Why need relocation?
13
Relocation Direct Memory Address
call dword ptr [0x ] mov eax, dword ptr [ ] If the base address of a PE image is not 0x Then we need relocation actions Why the base address can be changed ?
14
Relocation In one process space There are many PE images
EXE Image and many DLL Images Conflict
15
Relocation Need the addresses in PE header be relocated ? No Need
16
RVA RVA – (Relative Virtual Address)
For PE Structures Used by PE Loader Note : RVA points to the address in memory images Not the offset in disk files PE Image Address = Base Address + RVA
17
RVA PE file in disk Base Addr DOS Header DOS Header PE Header
Opt Header Sections Table Data DIR DOS Header PE Header Opt Header Data DIR RVA Sections Table Section #1 + Section #1 Section #2 Section #2 PE Image in Mem Loading
18
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
19
Dos Header “MZ” DOS struct { DOS Header WORD e_magic; PE Header ...
DWORD e_lfanew; } PE Header DOS Header Dos Stub Opt Header Data DIR Sections Table CD Th F is progr D E 6E 6F am canno E t be run E F in DOS D 6F mode Section #1 Section #2
20
DOS Stub Modify DOS Stub code Link /stub:dosfile.exe hello.obj
21
_IMAGE_DOS_HEADER Defined in WinNT.h
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE 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; Defined in WinNT.h
22
PE Header size: 4bytes “PE00” Signature PE Header File Header
Optional Header PE Header size: 20bytes Opt Header Data DIR typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
23
Optional Header Signature File Header Optional Header Data DIR
24
Optional Header (1) typedef struct _IMAGE_OPTIONAL_HEADER { //
// Standard fields. WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; ... } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
25
Optional Header (2) 16 typedef struct _IMAGE_OPTIONAL_HEADER {
// NT additional fields. DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; ... DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD 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; 16
26
Optional Header (3) AddressOfEntryPoint ImageBase Alignment (Padding)
Execution Entry (Note : RVA) ImageBase Alignment (Padding) SectionAlignment (Bigger) FileAlignment (Smaller) Subsystem “D:\> link /subsystem:windows hello.obj” Console, windows, posix, native, …
27
Optional Header (4) DataDirectory Array with size 16*8
Note : RVA IMAGE_DATA_DIRECTORY DataDirectory[16]; typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY;
28
Optional Header (4) DataDiretory 0 : Export 1 : Import 2 : Resource
3 : Exception 4 : Security 5 : Base Relocation 6 : Debug 7 : Architecture 8 : Global PTR (unknown) 9 : TLS (Thread Local Storage) 10 : LOAD_CONFIG 11 : BOUND_IMPORT 12 : IAT 13 : DELAY_IMPORT 14 : COM_DESCRIPTOR 15 : 0x , 0x
29
Programming Handle hFile= CreateFile(szFilename, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile==INVALID_HANDLE_VALUE) return -1; HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); DWORD lpFileBase = (DWORD)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
30
Programming PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpFileBase; PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)( lpFileBase + pDosHeader->e_lfanew); PIMAGE_OPTIONAL_HEADER32 pOptHeader = &(pNtHeaders->OptionalHeader); PIMAGE_FILE_HEADER pFileHeader = &(pNtHeaders->FileHeader);
31
Sections Table DOS Header NumberOfSections PE Header Opt Header
Section Header Data DIR Section Header NumberOfSections Sections Table ... Section Header Section #1 Section #2
32
Per Section Header Name[8] VirtualAddress (RVA) SizeOfRawData
“.text” “.data” “.idata” “.reloc” “.rsrc” “.rdata” VirtualAddress (RVA) Addr of section SizeOfRawData Size of section in PE file PointerToRawData Offset of section in PE file Characteristics Cached? Paged? Shared? Executable? Readable? Writable? Discardable? typedef struct _IMAGE_SECTION_HEADER { BYTE Name[8]; 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;
33
Programming PIMAGE_SECTION_HEADER pSecHeader0 = (PIMAGE_SECTION_HEADER) (lpFileBase + (pDosHeader->e_lfanew) + sizeof(IMAGE_NT_HEADERS)); WORD wSecNum = pFileHeader->NumberOfSections; PIMAGE_SECTION_HEADER pSecHeader[64]; for(i=0;i<wSecNum;i++) { pSecHeader[i] = (PIMAGE_SECTION_HEADER) ((DWORD)pSecHeader0 + i * sizeof(IMAGE_SECTION_HEADER)); }
34
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
35
Dynamic Linking Review (1)
0x : call 0x // MessageBoxA 0x : jmp dword ptr [0x ] //stub code 0x : 0x77D // Import Address Table 0x77D66534 : mov edi, edi // MessageBoxA(User32.dll) push ebp ...
36
Dynamic Linking Review (2)
Memory Import table kernel32.dll hello.exe Export table aaa.dll Memory
37
Import Symbols Symbols (functions/data) can be imported from external DLLs The loader will automatically load external DLLs All the dependencies are loaded as well All DLLs will be loaded only once External addresses are written to the Import Address Table (IAT) IAT is most often located in the “.idata” section
38
DLL Dependency Tree
39
Tool Dependency Walker (free)
A free utility that scans any 32-bit or 64-bit Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical tree diagram of all dependent modules.
40
Dynamic Linking Write target function addresses into IAT in PE structure Where to find IAT ? Import Address Table MessageBoxA … … …
41
Import Table DOS Header PE Header Opt Header Export
Export Virtual Address(RVA) Data DIR 1 Import Size Sections Table ... 15 Section #1 ... Section #n “.idata”
42
Import Table Quiz Where to find import table in PE file?
Note : RVA is memory address, not PE file offset
43
Import Table Quiz Answer Where to find import table in PE file?
Note : RVA is memory address, not PE file offset Answer 1, get RVA of some section, RVAsec 2, get Offsetsec of this section 3, RVAoffset=RVAIAT- RVAsec 4, OffsetIAT=Offsetsec+RVAoffset
44
Import Table DOS Header typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union { DWORD Characteristics; DWORD OriginalFirstThunk; }; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; DWORD FirstThunk; // RVA to IAT } IMAGE_IMPORT_DESCRIPTOR; PE Header Opt Header Data DIR Sections Table Section #1 ... import desc 0 import desc 1 Section #n “.idata” ...
45
Import Descriptor (In File)
OriginalFirstThunk IMAGE_THUNK_DATA IMAGE_THUNK_DATA TimeDataStamp IMAGE_THUNK_DATA IMAGE_THUNK_DATA ForwarderChain IMAGE_THUNK_DATA IMAGE_THUNK_DATA Name FirstThunk “Kernel32.dll” 02F6 ExitProcess 0111 ReadFile
46
Import By ? Import By Name typedef struct _IMAGE_IMPORT_BY_NAME {
IMAGE_THUNK_DATA typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; 0111 ReadFile Import By Ordinal 0111
47
Import Descriptor (In Mem)
OriginalFirstThunk IMAGE_THUNK_DATA 02F6 ExitProcess TimeDataStamp IMAGE_THUNK_DATA 0111 ReadFile ForwarderChain B Name FirstThunk “Kernel32.dll” Addr of ExitProcess IAT? Addr of ReaFile Addr of WriteFile
48
Import Address Table (IAT)
Addr of ExitProcess Addr of ReaFile Addr of WriteFile OriginalFirstThunk TimeDataStamp ForwarderChain Name FirstThunk “Kernel32.dll” OriginalFirstThunk TimeDataStamp ForwarderChain Name FirstThunk Addr of GetActiveWindow Addr of SendMessageA Addr of MessageBoxA “User32.dll” OriginalFirstThunk TimeDataStamp ForwarderChain Name FirstThunk Addr of _read Addr of _exit Addr of _open “MSVCR90.dll”
49
Import Address Table (IAT)
DOS Header PE Header Opt Header Sections Table Data DIR Virtual Address (RVA) Size Export 1 Import ... IAT 12 Virtual Address (RVA) Size ... 15 Section #1 ... Section #n “.idata” ... import desc 0 import desc 1 address 1 address 1 address 1
50
Programming DWORD dwRVAImpTbl = pOptHeader->DataDirectory[1].VirtualAddress; DWORD dwSizeOfImpTbl = pOptHeader->DataDirectory[1].Size; DWORD pImpTbl = lpFileBase + RVA2Offset(dwRVAImpTbl); PIMAGE_IMPORT_DESCRIPTOR p = (PIMAGE_IMPORT_DESCRIPTOR)pImpTbl; for (i=0; (p – pImpTbl) < dwSizeOfImpTbl; i++,p++) { pImpDesc[i] = p; if (pImpDesc[i]->Name == NULL) break; } DWORD dwNumOfImpDesc = i;
51
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
52
Export Symbols Exporting can be done with ordinals, name or both
Ordinals are simple index numbers of symbols Name is a full ASCII name of the exported symbol Exports can be forwarded to another DLL Example : NTDLL.RtlAllocHeap
53
Export Table Usually, EXE files have no export table
Most DLLs files have export table Except DLLs only for resources container
54
Export Table DOS Header PE Header Opt Header Export
Export Virtual Address(RVA) Data DIR 1 Import Size Sections Table ... 15 Section #1 ... Section #n “.edata”
55
Export Table DOS Header PE Header Opt Header Data DIR Sections Table
typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; // RVA DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA DWORD AddressOfNames; // RVA DWORD AddressOfNameOrdinals; // RVA } IMAGE_EXPORT_DIRECTORY; PE Header Opt Header Data DIR Sections Table Section #1 ... Export Directory Section #n “.edata” ...
56
Export Table Name typedef struct _IMAGE_EXPORT_DIRECTORY {
“kernel32.dll” Even filename is “kernel3.dll” Base Ordinal = Base + Index NumberOfFunctions NumberOfNames <= NumberOfFunctions Some functions have no name AddressOfFunctions RVA, point to an array of RVAs AddressOfNames AddressOfNameOrdinals typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; // RVA DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA DWORD AddressOfNames; // RVA DWORD AddressOfNameOrdinals;// RVA } IMAGE_EXPORT_DIRECTORY;
57
Export Table Export Directory “Kernel32.dll” . . . OpenFile Addr
Base+0 Name ReadFile Addr 1 Base+1 Base WriteFile Addr 2 Base+2 NumOfFunctions CloseFile Addr 3 Base+3 NumOfNames . . . AddrOfFunctions AddrOfNames RVA “OpenFile” AddrOfNameOrds RVA “ReadFile” 1 RVA “CloseFile” 3 ... ...... ... word
58
Export Table Lookup function by ordinal Get Base
Index = Ordinal – Base If Index >= NumberOfFunctions then error Addr = [AddrOfFunctions + Index * 4]
59
Export Table Lookup function by name Get NumberOfNames
For each i in {0 .. NumberOfNames-1} Search Name Get AddressOfNameOrdinals Ordinal = [AddressOfNameOrdinals + i * 4] Lookup function by ordinal
60
Programming mov edi, 0xXXXXYYYY
mov eax, [edi + 0x3c] // edi = BaseAddr, eax = pNTHeader mov edx, [edi + eax + 0x78] add edx, edi // edx = Export Table (RVA) mov pex, edx mov ecx, [edx + 0x18] // ecx = NumberOfNames mov ebx, [edx + 0x20] // add ebx, edi // ebx = AddressOfNames _search: dec ecx mov esi, [ebx + ecx*4] add esi, edi mov eax, 0x // "PteG" cmp [esi], eax jne _search mov eax, 0x41636f72 //"Acor" cmp [esi+4], eax jne search // to be continued …
61
Programming (cont.) // mov ebx, [edx + 0x24] //
add ebx, edi // ebx = AddressOfNameOrdinals mov ecx, [ebx + ecx*2] // ecx = GetProcAddress-orinal mov ebx, [edx + 0x1c] // add ebx, edi // ebx = AddressOfFunction mov eax, [ebx + ecx*4] add eax, edi // eax = GetProcAddress
62
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
63
Base Relocation Preferred Base Address Offset Actual Base Address
DOS Header PE Header Opt Header Sections Table Section #1 Section #n Data DIR ... Actual Base Address DOS Header PE Header Opt Header Sections Table Section #1 Section #n Data DIR ...
64
Base Relocation Sometimes a DLL can not be loaded to its preferred address (ImageBase) When rebasing, the loader has to adjust all hardcoded address Relocations are done in 4KB blocks Page size on x86 Each relocation entry gives a type and points to a location The offsets are adjusted according to the difference
65
Base Relocation Who need be relocated ? How to know who ?
Code with hardcoded address Data with hardcoded address How to know who ? Compiler “.reloc” section Generated by compilers
66
0x0050111A: mov eax, dword ptr [0x00400FFC]
Base Relocation Base Address – 0x A1 FC 0F 40 00 0x A: mov eax, dword ptr [0x00400FFC] [0x00500FFC]
67
0x0050111A: mov eax, dword ptr [0x00400FFC]
Base Relocation Relocation Information Preferred Base Address (PBA) (In PE Header) Actual Base Address (ABA) (Given by Loader) Relocated Address (RA) (In Relocation Table) [RA] = [RA] + ABA - PBA A1 FC 0F 40 00 0x A: mov eax, dword ptr [0x00400FFC] [0x00500FFC]
68
Base Relocation Table DOS Header PE Header Opt Header Export
Export Virtual Address(RVA) Data DIR 5 Size Sections Table Base Relocation 15 Section #1 ... Section #n “.reloc”
69
Base Relocation Table DOS Header PE Header Opt Header Data DIR
typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; } IMAGE_BASE_RELOCATION; PE Header Opt Header Data DIR Base Relocation Block low 12-bit Sections Table Low Addr Low Addr Low Addr Low Addr 0 ABSOLUTE 1 HIGH 2 LOW 3 HIGHLOW 4 HIGHADJ 5 MIPS_JMPADDR 6 SECTION 7 REL32 Base Relocation Block Section #1 Low Addr Low Addr ...... ...... ... ... Low Addr Low Addr Section #n “.reloc”
70
Base Relocation Table Relocation Block Relocation Item
VirtualAddress RVA of current page, 32-bit SizeOfBlock Numbers of relocation items Relocation Item Low 12-bit Relocated Address = VirtualAddress + Low 12-bit Why so boring ? Save Space
71
That’s why Program entry address is always like 0x , not 0x The second page after Base-Address Reason: RelocationBlock.VirtualAddress cannot be 0 And, RelocationBlock.VirtualAddress is page aligned
72
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques
73
Resources Resources in PE are similar to an archive
Resources files can be organized into directory tree The data structure is quite complex but there are tools to handle it Most common resources: Icons Version Information GUI resources
74
Resources Tools eXeScope (free) Resource Hacker (free)
Resource Hacker (free) ResScope (not free) PE Explorer (not free)
75
Outline PE Overview PE Structure Header Import Table Export Table
Base Relocation Table Resource Table Virus Techniques Introduction
76
PE Compressor ASPack ASProtect, protect software from Reduce file size
<20% Decrease loading time Download time Basic protection From kid-crackers ASProtect, protect software from Reverse-engineering Debugging Proc-dumping Memory-patching DOS Header PE Header Opt Header Sec. Table Data DIR Compressed Code Compressed data Compressed Res Decompressor
77
IAT Hook Hook ReadFile function Code OpenFile Addr WriteFile Addr
address 1 address 2 ReadFile Addr CloseFile Addr address 4 . . . Virus Code
78
Get API Entry What should virus code do if it want to use system DLLs?
Analyze the import table of the host file If import table has no some DLL ? Use GetModuleHandle to get this DLL BaseAddress, and use GetProcAddress function, if the DLL have been loaded already If the DLL is not in memory ? Use LoadLibrary to load this DLL dynamically The point is, LoadLibrary is also an API function
79
Get API Entry (cont.) The problem is We can get GetProcAddress firstly
How to get LoadLibrary function We can get GetProcAddress firstly Find the Base-Address of “Kernel32.dll” Analyze PE structures of Kernel32.dll Peek into its export table Find GetProcAddress function Wait, It’s not easy to find Base-Address of “Kernel32.dll” ?
80
Get API Entry (cont.) How to find Base-Address of “Kernel32.dll” ?
81
Code Injection Virus can inject itself into a PE files, known as “infection” Put virus in padding space of some sections Or add Additional sections Modify AddressOfEntryPoint (point to virus code)
82
DLL Detour Modify DLL code at run-time
Detours: Binary Interception of Win32 Functions Galen C. Hunt (Microsoft Research Operating Systems Group)
83
Supply Readings Matt Pietrek: An In-Depth Look into PE
Microsoft Portable Executable and Common Object File Format Specification
84
Exercise Write a PE file parser Deadline
Read and analyze the header of EXE PE files (e.g. hello.exe, any valid EXE file will be ok) Dos Header (Requisite) PE File Header, Optinal Header (Requisite) Sections Table (Requisite) Import Table (Optional) Export Table (Optional) Output the results In friendly format To console, or window, or msgbox, even debugger Deadline (20:00)
85
Any Question ?
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.