IAT和EAT

IAT-import address table

一个普通PE文件的运行往往需要导入多个库文件,在PE文件运行时如何找到库文件中函数的准确入口是程序正确运行的保证。IAT就是提供这样保证的一个机制。

IAT总得来说是一张表,表内存储着每个库文件函数在内存中的地址。

就我的理解,IAT对应着IMAGE_IMPORT_DESCRIPTOR结构体,每个结构体代表一个库,每个库对应一个IAT,PE件正确运行需要加载多少个库就需要多少个IMAGE_IMPORT_DESCRIPTOR结构体。该结构体的位置可以由PE头中可选头DataDirectory[1]成员元素来找到。

IMAGE_IMPOTER_DESCRIPTOR结构体包含有五个成员。第一个成员是一个联合体:一般给出的是OriginalFirstThunk的值,这个值是INT的地址,INT(Import Name Table)是一个存储了库文件函数名称的表。

第二个成员是时间戳。第三个成员是ForwarderChain。第四个成员是Name,存储的是库名称字符数组的地址。第五个成员是FirstThunk,存储的是IAT表的地址。

当PE文件加载到内存时:

第一步:

PE加载器读取结构体成员的值,Name成员找到库名称,然后将库文件加载到内存中来。

第二步:

PE加载器读取OriginalFirstThunk值获得INT地址,然后依次读取INT各项的值,根据函数的标号获取函数的地址。

第三步:

根据FirstThunk的值获取IAT的地址,将上一步获得地址送入IAT中存储。

这里的疑问是:INT应该是一组指针,指向的对象是结构体:IMAGE_IMPORT_BY_NAME,这个结构体中存储的是函数的名称和标号。问题是:这个结构体的数据是什么时候有的,是PE文件源程序编译时就存在的还是库文件加载时写入的。

EAT-export address table

EAT对应的结构体为IMAGE_EXPORT_DESCRIPTOR,位置信息存储在可选头DataDirectory[0]中。

一般PE文件此项值应为0,代表不存在这个表项,只有库文件,才会含有这个表项。

结构体成员包括特征值,时间戳,版本信息等。重要的成员是Name,存储着库文件的名字;Base存储着函数标号从哪里开始;NumberOfFunctions存储着函数的数量;NumberOfNames存储着函数名称的数量(一般情况下这两项相同);AddressOfFunctions函数地址数组的首地址;AddressOfNames函数名称地址数组的首地址;AdressOfNameOrdinals,存储着函数标号的地址信息。

总结

普通PE文件通过IAT表来正确调用库文件的函数,库文件通过EAT表将函数的正确入口告知普通PE文件。

IAT内地址的获得其实是通过INT提供的名称或者标号利用GetProcAddress()API从库文件中获得的,而GetProcAddress()API正是通过访问EAT表来获取的地址。

posted @ 2015-12-16 17:39  半城日暖  阅读(2273)  评论(0编辑  收藏  举报