【PE结构】4.导出表

一、前言
二、PE整体结构
三、DOS头
四、NT头
五、区段头

六、导出表

七、导入表
八、资源表
九、其他表

1.概念

导出 是指PE文件导出的供其他PE文件使用的函数、变量、或者类的行为。
符号 这些导出的函数、变量、类一般称为符号。
导出表 是存储导出的这些符号的表。通过导出表,能够定位这些符号。

2.导出表定位

前面提到的 NT头->扩展头->数据目录表->第一个元素->相对虚拟地址(RVA)
还用010Editor打开百度云盘看一下
这里写图片描述
可以看到,数据目录表中第一个元素的结构体内有两个数据

  • 相对虚拟地址
    相对虚拟地址只是一个偏移值,虚拟地址才是真正定位的值。
    虚拟地址 = 程序加载基址(通常是0x400000) + 虚拟地址
    因为有文件对齐的问题,未加载0x200对齐,加载后0x1000对齐,改地址并不能直接在文件中找到导出表的位置。
    需要将虚拟地址,转换成,文件偏移。
    文件FOA = 导出表RVA - 区段RVA + 区段FOA
    导出表应该在.edata段中,但通常这个段会合并到.rdata中。

  • 大小
    EXE文件通常是没有导出内容的
    大小,Size,值为0

我们换一个DLL文件看一下
这里写图片描述

3.导出表结构

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;               // 当前PE文件名
    DWORD   Base;               // 序号基数
    DWORD   NumberOfFunctions;  // 函数数量
    DWORD   NumberOfNames;      // 函数名称数量
    DWORD   AddressOfFunctions;     // RVA 地址表
    DWORD   AddressOfNames;         // RVA 名称表
    DWORD   AddressOfNameOrdinals;  // RVA 序号表
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

函数序号 需要通过序号基数加上序号表里的序号才是真正的函数序号。

4.函数地址表

上面结构体中,AddressOfFunctions,该字段为导出函数地址表的**相对虚拟地址**RVA。
文件未加载时,需要转换为**文件偏移**VA后才能使用。
文件加载后,需要转为为**虚拟地址**FOA才能使用。
找到导出函数地址表后,每条4个字节为一条数据,共有NumberOfFunctions个。

5.函数名称表

上面结构体中,AddressOfNames,该字段为导出函数名称表的**相对虚拟地址**RVA。
表内存储的是函数名称的相对虚拟地址
文件未加载时,需要转换为文件偏移后才能使用。
文件加载后,需要转为为虚拟地址才能使用。
找到导出函数地址表后,每条4个字节为一条数据,共有NumberOfFunctions个。每条数据为一个地址,指向函数名称字符串。

6.函数序号表

上面结构体中,AddressOfNameOrdinals,该字段为导出函数序号表的**相对虚拟地址**RVA。
文件未加载时,需要转换为**文件偏移**VA后才能使用。
文件加载后,需要转为为**虚拟地址**FOA才能使用。
找到导出函数序号表后,每条2个字节为一条数据,共有NumberOfFunctions个。

7.地址表、名称表、序号表关系

序号表 与 名称表,两表内容按索引值一一对应。
序号表 与 地址表,序号表内容 与 地址表索引加一的数据相对应。
地址表内容可能会比名称表多,没对应上的部分可能是用序号导出的函数,也可能是无效函数,地址为0。

这里写图片描述

上一篇 :【PE结构】3.区段头
下一篇 :【PE结构】5.导入表

猜你喜欢

转载自blog.csdn.net/chy_chenyang/article/details/80791249