本文共 1647 字,大约阅读时间需要 5 分钟。
PE知识复习之PE的导入表
在之前的讲解中,我们已经了解了导出表的概念。导出表是一个PE文件提供给其他程序使用时所需的函数、函数地址、函数顺序等信息的集合。而导入表则是PE文件描述其依赖模块及这些模块中函数的信息。导入表的主要作用是帮助PE文件在运行时确定需要加载的模块、依赖的函数以及这些函数的具体地址。
导入表的定位位置位于扩展头中的数据目录结构体中,第二个字段保存的是导入表的RVA(虚拟地址)和大小。通过这个信息,我们可以确定导入表在内存中的具体位置。
导入表的结构由以下几个关键成员组成:
导入表的大小为20个字节(0x14),以16进制为一行,共有五个字段,每个字段占4个字节。
Name成员的作用是确定依赖的模块的名字。它是一个RVA,指向一个ASCII字符串,字符串结尾为0。通过分析Name成员的RVA值加上PE文件的基址,我们可以获取依赖模块的名称。
例如,在导入表的RVA位置0x1A4A6处,我们可以通过加上PE文件的基址(如0x400000),计算得到VA(虚拟地址)为0x41A4A6。通过内存查找该地址的内容,我们可以确定依赖的模块名称为VCRUNTIME140D.dll。从名称中可以看出,这是一个调试版本的运行库,140表示使用了VS2015编译器。
导入表的第一个成员(INT表)和最后一个成员(IAT表)共同作用于函数名称的确定。INT表记录的是依赖模块中的函数名称,而IAT表记录的是这些函数的具体地址。
INT表和IAT表的主要区别在于它们的存储位置和内容。INT表中的数据在PE文件加载前就已经确定,而IAT表中的数据则在PE文件加载后才被填充。通过检查INT表或IAT表的高位值,我们可以判断其内容:
例如,在INT表的RVA位置0x1A2A8处,VA为0x41A2A8。该表的内容显示,高位为0,0x1A48E是RVA,指向IMAGE_IMPROT_BY_NAME结构。该结构中的HINT字段为0x0000,表示无编译器索引,NAME字段存储了函数名称。
在程序运行时,当需要调用DLL中的函数时,会生成间接调用(通过函数指针)。导入表中的IAT表正是存储这些函数地址的重要信息。
例如,在IAT表的RVA位置0x1A098处,VA为0x41A098。该表存储的数据为0x6AD79CF0,即__Vcrt_loadlibraryExW函数的地址。通过查找该地址在内存中的实际值,我们可以确定函数的具体实现。
需要注意的是,导入表中的IAT表在PE文件加载前和加载后存在差异。在加载前,IAT表中的内容与INT表相同;在加载后,IAT表的内容被填充为实际函数地址。
导入表的大小为20个字节(0x14),主要包含以下关键信息:
在PE文件加载过程中,导入表的内容会根据需要被填充。通过分析导入表中的INT表和IAT表,我们可以确定依赖模块中的函数及其具体地址。
总之,导入表是PE文件实现对外模块依赖的关键机制,通过其结构和内容,我们可以深入了解PE文件的内工作原理。
转载地址:http://tmvfk.baihongyu.com/