PE導出表、重定位詳解

此文檔主要講解導出表,重定位信息:

使用例子爲: Windows.UI.Xaml.dll、010editor

1、導出表,重定位表的地址存放在哪裏

DOS頭-àPE頭文件(_IMAGE_NT_HEADERS)-à擴展頭(IMAGE_OPTIONAL_HEADER32)-à數據目錄表

數據目錄表中的內容:

structIMAGE_DATA_DIRECTORY  Export                   (1)

……

StructIMAGE_DATA_DIRECTORY BaseRelocationTable (6)

 

Typedef  struct IMAGE_DATA_DIRECTORY {

DWORDVirtualAddress ; //此處地址爲在內存中的地址

DWORD  size ;

}

如下圖信息:


2、這裏是VirtualAddress,如何轉變成相對文件地址:

根據pe文件的區段表進行轉換:

去段表的結構:

Typedefstruct  _IMAGE_SECTION_HEADER{

BYTEName[0x8];

Union{

DWORDPhysicalAddress;

DWORDVirtualSize ;

}

DWORDVirualAddress ;

DWORDSzieOfRawData;

DWORDPointerToRawData;

DWORDPointerToRelocations;

DWORDPointerToLinenumbers;

WORDNumberOfRelocations;

WORDNumberOfLinenumbers;

DWORDCharacteristics;

}

查看需要轉換的RVA在哪一個區段中。比如:VirualAddress (比如:此地址爲第一個模塊地址)<RVA <VirualAddres(第二個模塊地址),那麼RVA應該依據第一個模塊進行轉換:RVA-VirualAddress+PointerToRawData=offset(相對文件偏移)


1、   導出表地址指向一個數據結構,該結構爲:

Typedef struct _IMAGE_EXPROT_DIRECTORY{

DWORD Characteristics;              //0x0

DWORD TimeDataStamp;                     //0x4

WORD MajorVersion;                              //0x8

WORD MinorVersion;               //0xA

DWORD Name;                        //0xC

DWORD Base;                          //0x10

DWORD NumberOfFuncions;            //0x14

DWORD NumberOfName;                //0x18

DWORD  AddressOfFunctions;        //0x1c  導出地址表

DWORD AddressOfName;                //0x20   導出名稱表

DWORD AddressOfNameOrdinals;   //0x24    指向導出序列號數組

}

如何利用導出名稱表中的名稱找到函數導出的地址:

導出名稱表與導出序列號數組是相互對應的,序號與導出地址表的數組索引對應。

 

AddressOfName 找出你需要的函數名,從AddressOfNameOrdinals;中找出與之對應的序列號,根據序列號找到導出地址。比如:序列號爲5,那麼就找導出地址表中的第六個數據(導出地址表從0開始)。

實戰:

根據PEID我們可以看到我們看到到處函數信息:(依據此信息驗證手工尋找)


第一步:


第二步:


第三步:

計算offset: BC2D40-1000+400 = BC2140


第四部:


第五步:計算:

Offsets   AddressOfFunctions 00BC2D68-1000+400 = BC2168

Offsets  AddressOfName:00BC2DA0-1000+400 = BC21A0

Offsets  AddressOfNameOrdinals:00BC2DD8-1000+400 = BC21D8

第六步尋找createString RVA地址:

尋找字符串:


00BC2E08-1000+400 = BC2208


尋找Oridinal:


尋找0號索引地址:

 

地址:00864ac0

 

 

2、   重定位表的信息。

根據擴展表找到重定位表的RVA,通過段表將RVA轉換成offset.

Offset指向的位置爲一個數據結構:

typedef struct _IMAGE_BASE_RELOCATION{

DWORD     VirtualAddress;     //0x0    重定位頁的起始地址

DWORD      SizeOfBlock;  //0x4    本結構+重定位數組

}

此數據結構之後是:

Struct {

WORD Offset:12;  //重定位偏移

WORD  Type:4;       //重定位類型

}

Type  == 0x3 (大部分重定位都是該值):重定位偏移指向的整個4字節大小的地址都需要修正。

 

如何計算重定位位置:

VirtualAddress +offset+ImageBase(PE結構中的數據)-ImageBase(實際裝入的地址) = 需要重定位的RVA

下一步:

DWORD PTR [需要重定位的RVA] = DWORD PTR(需要重定位的RVA) -ImageBase(PE結構中的數據)+ImageBase(實際裝入的地址)

 

循環多少次此分頁重定位結束:

N = (SizeOfBlock-Sizeof(_IMAGE_BASE_RELOCATION))/sizeof(struct{WORD Offset:12,WORD Type:4})

 

N次之後,開啓下一個分頁的重定位信息。

實戰:

第一步:


第二步:


第三步計算:

BFA000-BFA000+BF5000 = BF5000

第四步:

 

VirtualAddress = 00001000;

SizeOfBlock = 00000808

重定位的個數:

N = (00000808-8)/2 =0x400;

第五步:

00 30 的意思是:

imagebase+重定位00001000+0地址處的四個字節。

 

 

Windows.UI.Xaml加載基址默認爲10000000,第一個需要重定位的數據爲:10B377A0.

我們手動改變dll的加載基址,變成707A0000.需要重定位的位置爲:707A0000+1000.

原來數據爲:10B377A0,重定位後的數據:


10B377A0-10000000+707A0000  =  712D77A0

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