导出表
一、定位导出表
可选PE头的最后一个成员属性IMAGE_DATA_DIRECTORY DataDirectory
,成员属性有16个,第一个存储就是导出表的位置
struct _IMAGE_DATA_DIRECTORY {
0x00 DWORD VirtualAddress; //导出表在哪里(RVA)
0x04 DWORD Size; //导出表大小(包含导出表所有表和子表所有的数据大小,可以删掉)
};
二、导出表的结构
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics; // 未使用
DWORD TimeDateStamp; // 时间戳
WORD MajorVersion; // 未使用
WORD MinorVersion; // 未使用
DWORD Name; // 指向该导出表文件名字符串
DWORD Base; // 导出函数起始序号
DWORD NumberOfFunctions; // 所有导出函数的个数(不准确,有可能是错的)
DWORD NumberOfNames; // 以函数名字导出的函数个数
DWORD AddressOfFunctions; // 导出函数地址表RVA
DWORD AddressOfNames; // 导出函数名称表RVA
DWORD AddressOfNameOrdinals; // 导出函数序号表RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
1、导出函数序号表和导出函数名称表一样长
2、导出函数地址表的个数由NumberOfFunctions决定
3、导出函数名称表的个数由NumberOfNames决定
三、按名字找函数地址
1、先找AddressOfNames(导出函数名称表),将RVA转换为FOA,AddressOfNames存的是一个地址
2、根据FOA找到表,循环遍历这张表(这张表里存的是函数名的地址)
3、遍历得到函数名的索引
4、到AddressOfNameOrdinals表中找到索引对应的值
5、用AddressOfNameOrdinals表中得到的值当AddressOfFunctions的下标查找对应函数的地址
如图:
四、按序号找函数地址
用导出序号 - base 得到的值就是AddressOfFunctions的下标