第13章:PE文件格式(3)

EAT

是一种核心机制,使不同的应用程序可以调用库文件中提供的函数.PE中的结构体Image_Export_Directory保存着导出信息,且只有一个结构体.

DataDirectory[0]结构体中的第一个元素是地址,第二个是大小.

 有下面几个重要的成员:

1#.NumberOfFunctions

实际Export函数的个数.

2#.NumberOfNames

Export函数中具名的函数个数.

3#.AddressOfNames

函数名称地址数组.

4.AddressOfFunctions

Export函数地址数组.

5#.AddressOfNameOrdinals

Ordinal地址数组.

注意这个结构体在notepad.exe中显示是NULL.

下面展示在kernel.dll中的Image_Export_Directory结构体:

RVA 地址转换为 FileOffset,262C 转化为 1A2C.

 如图所示:实际Export函数的个数:3b9,函数地址数组的起始地址:2654,函数名称数组的起始地址:3538,Ordinal地址数组:441C.(全是RVA)

从这里可以知道GetProcAddress()到底是如何工作的了:

1.在库文件的DataDirectory[0]中找到ExportDirectory,然后找到结构体中的AddressOfNames成员.每一个地址都对应一个函数名(连续的).

2.通过strcmp()函数对比查找指定的函数名称.

3.从AddressOfNameOrdinals找到ordinal数组.2字节表示一个ordinal值.将在找名称中拿到的索引值(x)用来查找相应的ordinal值(ordinal[x]).

4.利用AddressOfFunctions成员转到EAT.4字节为一个地址.用ordinal值用作数组索引查找指定函数的地址.

注意:若函数没有名称,则ordinal 无法匹配函数名称中的索引值.此时:

MSDN中写到: GetProcAddress 采用 DLL 模块句柄(由 LoadLibrary 、AfxLoadLibrary 或 GetModuleHandle 返回)作为参数,并采用要调用的函数的名称或函数的导出序号" 因此ordinal是可以直接作为参数传递进去的.就可以找到函数地址.

猜你喜欢

转载自www.cnblogs.com/Rev-omi/p/13194195.html