PE(Portable Executable) File Format(Chinese) - PE(可移植的可執行文件) 文件格式說明(中文)

PE文件結構(PE文件簡介)
[2008/3/27 15:56:00| By:perfecter]

1 PE文件簡介

PEPortable Executable,可移植的可執行文件)文件是指在Microsoft Windows95及其之後的Microsoft操作系統上運行的可執行文件,包括.EXE文件和.DLL文件。

可移植性(Portable)是指在任何機器(Intel 386 MIPS Alpha Power PC 等)上的Microsoft Windows操作系統都可以使用相同的可執行文件格式,使得程序加載器以及程序開發工具不需要針對每一個新的操作系統重寫。

2 相關概念

     RVARelative Virtual Address

當被裝載到內存中,可執行文件的某一個項目相對於基地址的偏移。比如一個可執行文件被裝載到虛擬地址空間的0x40000處,其中有一個項目位於0x401464處,那麼它的RVA就是0x1464。虛擬地址(0x401464- 基地址(0x400000= RVA0x1464

     Section()

PE文件中最基本的代碼或者數據單元。例如,PE文件中的所有代碼可以被放在同一個節中,或者每一個函數都可以被放到不同的節中去。節有點類似於Intel 8086的段。PE文件可以有多個節,像.text(代碼節)以及.data(數據節)節等。

3 PE文件結構

下面就是一個典型的PE文件的結構示意圖:

MS-DOS

 

Offset to
PE Header

MS DOS 2.0 Stub Program

 

Magic Number

PE Header

 

 

Optional header 

 

 

Section headers

 

 

Sections

 

 

PE文件結構(PE文件頭一)
[2008/3/27 15:58:00| By:perfecter]

3 PE文件結構

     MS-DOS

MS-DOS頭在winnt.h中定義成爲IMAGE_DOS_HEADER,這個結構中,最需要關心的是成員e_lfanew,它給出了PE Header在文件中的偏移量。比如,e_lfanew的值是0xE0,則PE Header在文件距離開頭0xE0處。

     MS DOS 2.0 Stub Program

這是一段DOS程序,如果把win32的可執行文件放到dos上執行,這段代碼將在屏幕上顯示類似於“This program can not run in dos”的信息。

     Magic NumberPE Header

這纔是真正的win32可執行文件的開始。Magic Number是一個DWORD類型的數,值是0x4550,對應的ASCII值就是“PE”PE Headerwinnt.h裏被定義成爲:

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;

其中:

Machine:聲明PE文件是在那種CPU架構下運行,它可以是下表中所列出的值:(通常PE文件運行在x86系列的CPU架構下,這個值就應該是0x14C。)

標誌

說明

IMAGE_FILE_MACHINE_UNKNOWN

0x0

假定在所有機器上運行

IMAGE_FILE_MACHINE_AM33

0x1d3

Matsushita AM33

IMAGE_FILE_MACHINE_AMD64

0x8664

x64

IMAGE_FILE_MACHINE_ARM

0x1c0

ARM little endian

IMAGE_FILE_MACHINE_EBC

0xebc

EFI byte code

IMAGE_FILE_MACHINE_I386

0x14c

Intel 386家族及其兼容CPU

IMAGE_FILE_MACHINE_IA64

0x200

Intel Itanium處理器家族

IMAGE_FILE_MACHINE_M32R

0x9041

Mitsubishi M32R little endian

IMAGE_FILE_MACHINE_MIPS16

0x266

MIPS16

IMAGE_FILE_MACHINE_MIPSFPU

0x366

MIPS with FPU

IMAGE_FILE_MACHINE_MIPSFPU16

0x466

MIPS16 with FPU

IMAGE_FILE_MACHINE_POWERPC

0x1f0

Power PC little endian

IMAGE_FILE_MACHINE_POWERPCFP

0x1f1

有浮點支持的Power PC

IMAGE_FILE_MACHINE_R4000

0x166

MIPS little endian

IMAGE_FILE_MACHINE_SH3

0x1a2

Hitachi SH3

IMAGE_FILE_MACHINE_SH3DSP

0x1a3

Hitachi SH3 DSP

IMAGE_FILE_MACHINE_SH4

0x1a6

Hitachi SH4

IMAGE_FILE_MACHINE_SH5

0x1a8

Hitachi SH5

IMAGE_FILE_MACHINE_THUMB

0x1c2

Thumb

IMAGE_FILE_MACHINE_WCEMIPSV2

0x169

MIPS little-endian WCE v2

NumberOfSections表示PE文件中節的數量。

TimeDateStamp:鏈接器產生這個文件的時間,是自從1969 12 31 4:00 P.M. 之後的總秒數。

PointerToSymbolTableNumberOfSymbols一般只對COFFCommon Object File Format)格式文件有用。

SizeOfOptionalHeader它是Optional header的大小,也就是sizeof(IMAGE_OPTIONAL_HEADER)Optional header被定義成爲IMAGE_OPTIONAL_HEADER結構)。

Characteristics聲明這個PE文件的性質,它可以是下表列出的值,並且可以按位或:(對於一個DLL文件,這個值應該通常是0x2102;對於一個EXE文件,這個值通常是0x0103

標誌

描述

IMAGE_FILE_RELOCS_STRIPPED

0x0001

用於Windows CEWindows NT以及後續操作系統。聲明此PE文件沒有基礎重定位,並且必須裝載到預先定義的基地址。如果基地址不可用,裝載器將報錯。

IMAGE_FILE_EXECUTABLE_IMAGE

0x0002

這是一個可執行文件。

IMAGE_FILE_LINE_NUMS_STRIPPED

0x0004

這一位應該置零。

IMAGE_FILE_LOCAL_SYMS_STRIPPED

0x0008

這一位應該置零。

IMAGE_FILE_AGGRESSIVE_WS_TRIM

0x0010

建議不要再Windows 2000機器後續系統中使用,應該置零。

IMAGE_FILE_LARGE_ADDRESS_ AWARE

0x0020

程序可以處理大於2G的地址。

 

0x0040

此位爲將來使用而保留。

IMAGE_FILE_BYTES_REVERSED_LO

0x0080

這一位應該置零。

IMAGE_FILE_32BIT_MACHINE

0x0100

機器以32位架構爲基礎。

IMAGE_FILE_DEBUG_STRIPPED

0x0200

調試信息已經被移除。

IMAGE_FILE_REMOVABLE_RUN_ FROM_SWAP

0x0400

如果文件位於可移動的媒體上,那麼將整個文件讀入交換文件。

IMAGE_FILE_NET_RUN_FROM_SWAP

0x0800

如果文件位於網絡上,那麼將整個文件讀入交換文件。

IMAGE_FILE_SYSTEM

0x1000

文件是一個系統文件,不是用戶文件

IMAGE_FILE_DLL

0x2000

文件是一個動態鏈接庫,雖然它們不能直接運行,也被認爲是一個可執行文件。

IMAGE_FILE_UP_SYSTEM_ONLY

0x4000

只能在單芯片機器上運行

IMAGE_FILE_BYTES_REVERSED_HI

0x8000

這一位應該置零。

 

 

PE文件結構(PE文件頭二)
[2008/4/1 9:05:00| By:perfecter]

     Optional header

從字面上看,這個文件頭是可選的,但實際上它是PE文件中必不可少的。它在winnt.h中被定義稱爲:

typedef struct _IMAGE_OPTIONAL_HEADER {

    WORD    Magic;

    BYTE    MajorLinkerVersion;

    BYTE    MinorLinkerVersion;

    DWORD   SizeOfCode;

    DWORD   SizeOfInitializedData;

    DWORD   SizeOfUninitializedData;

    DWORD   AddressOfEntryPoint;

    DWORD   BaseOfCode;

    DWORD   BaseOfData;

    DWORD   ImageBase;

    DWORD   SectionAlignment;

    DWORD   FileAlignment;

    WORD    MajorOperatingSystemVersion;

    WORD    MinorOperatingSystemVersion;

    WORD    MajorImageVersion;

    WORD    MinorImageVersion;

    WORD    MajorSubsystemVersion;

    WORD    MinorSubsystemVersion;

    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;

其中:

Magic聲明PE文件的狀態,如果是普通的PE文件,值爲0x10B;如果是隻讀的,值爲0x107

MajorLinkerVersionMinorLinkerVersion鏈接器的版本號,但實際上這兩個值並不可靠,某些鏈接器不會設置這兩個值。

SizeOfCode所有代碼節的大小。

SizeOfInitializedDataSizeOfUninitializedData所有已初始化數據節、未初始化數據節的大小。

AddressOfEntryPoint這是一個RVA。當PE文件被裝載到內存中以後,第一條可執行指令的地址。對於設備驅動,這是初始化函數的地址;對於DLL,這個入口點是可選的,如果DLL沒有入口點,則這個值必須爲零。

BaseOfCodeBaseOfData代碼的RVA,已初始化數據的RVA

ImageBasePE文件的優先裝載地址。比如,這個值是0x10000000,則裝載器會將PE文件優先裝載到虛擬內存地址0x10000000中。通常.EXE文件的這個值是0x00400000.DLL文件的是0x10000000

SectionAlignmentPE文件裝載到內存後,節的對齊粒度,必須大於等於FileAlignmentWIN32下,一般是0x1000WIN64下,一般是0x2000

FileAlignmentPE文件中,節的對齊粒度。一般情況下是0x200的倍數。

MajorOperatingSystemVersionMinorOperatingSystemVersion期望的操作系統版本。

MajorImageVersionMinorImageVersion期望的PE文件版本,某些鏈接器不設定這個值。

MajorSubsystemVersionMinorSubsystemVersion期望的子系統版本。

Win32VersionValue這個是保留的,必須是0

SizeOfImagePE文件裝載到內存後,整個鏡像的大小,必須是SectionAlignment的整數倍。

SizeOfHeadersMS-DOS頭、MS DOS 2.0 Stub ProgramMagic NumberPE HeaderOptional header大小之和,必須是FileAlignment的整數倍。

CheckSum對於普通的PE文件,這個值是0

Subsystem聲明PE文件在什麼樣的系統上運行,可以是下表中的值:(對於WINDOWS開發,通常選擇第三項或者第四項)

Constant

Value

Description

IMAGE_SUBSYSTEM_UNKNOWN

  0

未知子系統。

IMAGE_SUBSYSTEM_NATIVE

  1

設備驅動以及WINDOWS內部程序。

IMAGE_SUBSYSTEM_WINDOWS_GUI

  2

WINDOWS GUI 程序。

IMAGE_SUBSYSTEM_WINDOWS_CUI

  3

WINDOWS控制檯程序。

IMAGE_SUBSYSTEM_POSIX_CUI

  7

Posix字符子系統程序。

IMAGE_SUBSYSTEM_WINDOWS_CE_GUI

  9

Windows CE

IMAGE_SUBSYSTEM_EFI_APPLICATION

10

可擴展固件程序。

IMAGE_SUBSYSTEM_EFI_BOOT_ SERVICE_DRIVER

11

啓動服務的EFI驅動。

IMAGE_SUBSYSTEM_EFI_RUNTIME_ DRIVER

12

運行時的EFI驅動。

IMAGE_SUBSYSTEM_EFI_ROM

13

EFI只讀鏡像。

IMAGE_SUBSYSTEM_XBOX

14

XBOX

DllCharacteristics聲明DLL文件的性質,可以是下表中的值:(如果沒有特別需要,這個值是零)

常量

描述

 

0x0001

保留的,必須爲零。

 

0x0002

保留的,必須爲零。

 

0x0004

保留的,必須爲零。

 

0x0008

保留的,必須爲零。

IMAGE_DLL_CHARACTERISTICS_

DYNAMIC_BASE

0x0040

DLL可以在運行時被重置。

IMAGE_DLL_CHARACTERISTICS_

FORCE_INTEGRITY

0x0080

強制進行代碼完整性檢查。

IMAGE_DLL_CHARACTERISTICS_

NX_COMPAT

0x0100

映像是NX兼容的。

IMAGE_DLLCHARACTERISTICS_ NO_ISOLATION

0x0200

不隔離映像文件。

IMAGE_DLLCHARACTERISTICS_ NO_SEH

0x0400

不使用結構化異常處理。

IMAGE_DLLCHARACTERISTICS_ NO_BIND

0x0800

不綁定映像

 

0x1000

保留的,必須爲零。

IMAGE_DLLCHARACTERISTICS_ WDM_DRIVER

0x2000

WDM驅動。

IMAGE_DLLCHARACTERISTICS_ TERMINAL_SERVER_AWARE

0x8000

終端服務器

SizeOfStackReserve預留棧的大小,一般默認爲0x10000

SizeOfStackCommit提交棧的大小,一般默認爲0x1000

SizeOfHeapReserve預留堆的大小,一般默認爲0x10000

SizeOfHeapCommit提交堆的大小,一般默認爲0x1000

LoaderFlags保留的,必須爲零。

NumberOfRvaAndSizes之後的數據目錄的數量,強烈建議使用默認的16

DataDirectory數據目錄,每一個對應一個節,聲明該節的RVA和大小。

     Section headers

每一個節對應一個與之相關的節頭,節頭聲明瞭節的大小、RVA以及的性,在winnt.h中,節頭定義如下:

#define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _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;

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

其中:

Name一個8字節長度的變量,給出節的名字。如果名字中的字符少於8字節,則用NULL填充;如果剛好等於8字節,則不需要以NULL結束。一般情況下,代碼節名稱爲“.text”,數據節爲“.data”

Misc這是一個聯合體,在可執行映像中,使用的是VirtualSize,聲明對應的節的大小。

VirtualAddressPE文件讀入內存後,對應節的RVA

SizeOfRawData磁盤上,節根據FileAlignment對齊後的大小,必須是FileAlignment的倍數。

PointerToRawData從文件開頭到對應節的偏移量。

PointerToRelocations

PointerToLinenumbers

NumberOfRelocations

NumberOfLinenumbers以上四個變量在可執行文件中用不到。

Characteristics聲明節的性質:可以是下表中的值,並可以按位或:

標誌

描述

IMAGE_SCN_CNT_CODE

0x00000020

節包含可執行代碼。

IMAGE_SCN_CNT_INITIALIZED_DATA

0x00000040

節包含已經初始化的數據。

IMAGE_SCN_CNT_UNINITIALIZED_ DATA

0x00000080

節包含未初始化的數據。

IMAGE_SCN_LNK_INFO

0x00000200

節包含註釋或其他信息。只用於目標文件。

IMAGE_SCN_LNK_REMOVE

0x00000800

節不是映像的一部分,只用於目標文件。

IMAGE_SCN_LNK_COMDAT

0x00001000

節包含COMDAT數據。只用於目標文件。

IMAGE_SCN_GPREL

0x00008000

節包含引用全局指針的數據。

IMAGE_SCN_LNK_NRELOC_OVFL

0x01000000

節包含擴展重定位。

IMAGE_SCN_MEM_DISCARDABLE

0x02000000

根據需要,節可被廢棄。

IMAGE_SCN_MEM_NOT_CACHED

0x04000000

節不可被緩存。

IMAGE_SCN_MEM_NOT_PAGED

0x08000000

節不可被分頁。

IMAGE_SCN_MEM_SHARED

0x10000000

節可在內存中被共享。

IMAGE_SCN_MEM_EXECUTE

0x20000000

節可以執行。

IMAGE_SCN_MEM_READ

0x40000000

節可被讀取。

IMAGE_SCN_MEM_WRITE

0x80000000

節可被寫入。

 

 

PE文件結構()
[2008/4/2 15:07:00| By:perfecter]

     Sections

每一個節對應一個節頭,節的數量必須與PE HeaderNumberOfSections聲明的相一致。幾個比較常見的節是:輸出符號節、輸入符號節、數據節、重定位節和代碼節。比較複雜的是輸出符號節、輸入符號節和重定位節:

I.            輸出符號節

輸出符號節,包含一些可以供其他映像文件使用的符號信息。GetProcAddress()函數就是通過這個節找到需要的函數的。

輸出符號包含若干個表,見下表。通常只需要輸出目錄表(Export directory table)和輸出地址表(Export address table)。

表名

描述

Export directory table

這個表說明其他輸出標的位置和大小。

Export address table

輸出表的RVA數組,是可執行文件內可執行代碼節和數據節中的輸出函數和數據的真實地址。利用這個表,其他的映像可以使用這些符號。

Name pointer table

按升序排列的公共輸出名的數組。

Ordinal table

Name pointer table的成員順序排序的數組。因此,Name pointer table Ordinal table相同數量的成員。 每一個序數都是一個指向Export address table的索引。

Export name table

一組連續的以NULL結尾的ASCII字符。Name pointer table的成員指向這個區域。這些是輸入或輸出符號的公共名稱;它們沒有必要和在映像內部使用的私有名稱相同。

當其他的映像文件利用名稱導入一個符號,Win32裝載器在Name pointer table中尋找與之符合的字符。如果找到相符的字符,序號被用來在Ordinal table中查找相應的成員(就是說,兩個表有相同的索引)。找到的序號是指向Export address table的一個索引,指向的成員給出了期望的符號的真實位置。

如果其他的映像文件利用序號導入一個符號,就不需要在Name pointer table中來查找符合的字符。直接使用序號效率會更高。

?  Export directory table

winnt.h中,Export directory table被定義爲如下結構:

typedef struct _IMAGE_EXPORT_DIRECTORY {

    DWORD   Characteristics;

    DWORD   TimeDateStamp;

    WORD    MajorVersion;

    WORD    MinorVersion;

    DWORD   Name;

    DWORD   Base;

    DWORD   NumberOfFunctions;

    DWORD   NumberOfNames;

    DWORD   AddressOfFunctions;     // RVA from base of image

    DWORD   AddressOfNames;         // RVA from base of image

    DWORD   AddressOfNameOrdinals;  // RVA from base of image

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

Characteristics保留的,必須爲零。

TimeDateStamp輸出數據被建立的時間。

MajorVersion主版本數字,可以被用戶設定。

MinorVersion次版本數字,可以被用戶設定。

Name包含此DLL名稱的ASCII字符串的地址,與鏡像基地址相關。

Base輸出符號的起始數字,通常是1

NumberOfFunctionsExport address table中的入口個數。

NumberOfNamesName pointer table中的名稱個數。

AddressOfFunctionsExport address table的地址,與鏡像基地址相關。

AddressOfNamesName pointer table的地址,與鏡像基地址相關。

AddressOfNameOrdinalsExport name table的地址,與鏡像基地址相關。

? 

 

表間圖示

II.           輸入符號節

所有需要導入符號的影響文件,都需要一個稱之爲.idata的節。導入信息的典型結構如下圖所示:

Directory Table

 

 

 

Null Directory Entry

DLL1 Import Lookup Table

 

Null

DLL2 Import Lookup Table

 

Null

DLL3 Import Lookup Table

 

Null

Hint-Name Table

 

?  Import Directory Table

導入表由一系列的IMAGE_IMPORT_DESCRIPTOR結構組成,結構的數量取決於程序要使用的DLL文件的數量,每個結構對應一個DLL文件,例如,如果一個PE文件從10個不同的DLL文件中引入了函數,那麼就存在10IMAGE_IMPORT_DESCRIPTOR結構來描述這些DLL文件,在所有這些結構的最後,由一個內容全爲0IMAGE_IMPORT_DESCRIPTOR結構作爲結束。

IMAGE_IMPORT_DESCRIPTOR結構的定義如下:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

    union {

        DWORD   Characteristics;

        DWORD   OriginalFirstThunk;

    };

    DWORD   TimeDateStamp;                 

    DWORD   ForwarderChain;

    DWORD   Name;

    DWORD   FirstThunk;

} IMAGE_IMPORT_DESCRIPTOR;

typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

OriginalFirstThunk導入查詢表(import lookup table)的RVACharacteristics不使用。

TimeDateStamp在映像被綁定前,這個值是零,在映像被綁定後,這個值是DLL被創建的時間。

ForwarderChain第一個轉發引用的索引。

Name這是一個RVA,指向一個以 null 爲結束字符的 ASCII 字符串,內含imported DLL 的名稱。

FirstThunk導入地址表(import address table)的RVA

?  Import Lookup Table

一個Import Lookup Table實際上就是一個雙字,在winnt.h中定於如下:

typedef struct _IMAGE_THUNK_DATA32 {

    union {

        DWORD ForwarderString;

        DWORD Function;

        DWORD Ordinal;

        DWORD AddressOfData;

    } u1;

} IMAGE_THUNK_DATA32;

typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

當雙字(就是指結構!)的最高位爲1時,表示函數是以序號的方式導入的,這時雙字的低位就是函數的序號。可以用預定義值IMAGE_ORDINAL_FLAG32(或80000000h)來對最高位進行測試,當雙字的最高位爲0時,表示函數以字符串類型的函數名方式導入,這時雙字的值是一個RVA,指向Hint-Name Table

?  Hint/Name Table

winnt.h中,Hint/Name Table被定義爲如下格式:

typedef struct _IMAGE_IMPORT_BY_NAME {

    WORD    Hint;

    BYTE    Name[1];

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

Hint表示函數的序號,不過這個字段是可選的,有些編譯器總是將它設置爲0

NameName1字段定義了導入函數的名稱字符串,這是一個以0爲結尾的字符串。

?  表間圖示

 

圖中示意了可執行文件導入了Kernel32.dll中的ExitProcessReadFileWriteFilelstrcmp函數的情況,其中,前面3個函數按照名稱方式導入,最後的lstrcmp函數按照序號導入,這4個函數的序號分別是02f6h0111h002bh0010h

 

PE文件中的導入表.JPG 

PE文件中的導入表

PE文件被裝入內存後,內存中的映像就被Windows裝載器修正成了下圖所示的樣子,其中由FirstThunk字段指向的那個數組中的每個雙字都被替換成了真正的函數入口地址,之所以在PE文件中使用兩份IMAGE_THUNK_DATA數組的拷貝並修改其中的一份,是爲了最後還可以留下一份拷貝用來反過來查詢地址所對應的導入函數名:

 

內存中的導入表.JPG內存中的導入表

III.          重定位節

當鏈接器產生一個可執行文件,它假設這個文件會被加載內存的某處,並且把code data的相關假設地址都寫入 EXE 文件中。在Optional header中的ImageBase成員,記錄了這個文件期望的加載地址,如果windows加載起沒有把PE文件加載的它期望的地址上,則需要對code data的相關假設地址都加以修正。這就是重定位的作用。

重定位節可以分爲多個重定位塊,每個重定位塊描述映像中的4k1000h)的重定位信息。每個重定位塊都以一個相同的結構開始,在winnt.h中定義如下:

typedef struct _IMAGE_BASE_RELOCATION {

    DWORD   VirtualAddress;

    DWORD   SizeOfBlock;

} IMAGE_BASE_RELOCATION;

typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

VirtualAddress這是一個頁面RVA

SizeOfBlock重定位塊的總大小。

緊接着這個結構,就是一系列重定位的信息了,一個重定位信息包存在一個WORD值中,這個前4位保存這個重定位信息的性質,後12位則是一個以上面VirtualAddress爲基準的偏移。其中前四位的定義如下:

 

 

描述

IMAGE_REL_BASED_ABSOLUTE

0

可以跳過這個重定位塊,僅僅是用來對齊。

IMAGE_REL_BASED_HIGH

1

32位的高16位需要修正。

IMAGE_REL_BASED_LOW

2

32位的低16位需要修正。

IMAGE_REL_BASED_HIGHLOW

3

整個32位需要被修正。

IMAGE_REL_BASED_HIGHADJ

4

16位的區域是一個32WORD值的高位。這個32WORD值的低16位跟在這個重定位的後面。

IMAGE_REL_BASED_MIPS_JMPADDR

5

重定位用於MIPS跳轉指令。

 

6

保留的,必須是零。

 

7

保留的,必須是零。

IMAGE_REL_BASED_MIPS_JMPADDR16

9

重定位用於MIPS16跳轉指令。

下面的例子舉出了一個重定位表的實際情況,假設模塊被裝入00400000h處:

重定位表偏移  數據          說明

0000h        00001000h     第一個塊:頁面起始地址是00401000h

0004h        00000010h     重定位塊長度是10h

0008h        3012h         16位重定位項,重定位位置:00401012h

000ah        3040h         16位重定位項,重定位位置:00401040h

000ch        306fh         16位重定位項,重定位位置:0040106fh

000eh        0000h         用於對齊的空白數據

0010h        00002000h     第二個塊:頁面起始地址是00402000h

0014h        0000000Ch     重定位塊長度是0Ch

0018h        3080h         16位重定位項,重定位位置:00402080h

001ah        30f0h         16位重定位項,重定位位置:004020f0h

001ch        00000000h     重定位

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章