解析导出表

引言

假设现在有一个exe程序使用了一个dll,对于这个exe程序而言,dll文件就相当于一个黑盒子,里面装的内容exe一点也不清楚。
所以什么是导出表?
导出表就是dll的一份清单,里面记录了它有多少个函数,函数的地址等相关信息
在这里插入图片描述
补充:exe并不是没有导出表,而是大部分exe没有导出表

另外,数据目录表有16个,其中第一个就是导出表

typedef struct _IMAGE_DATA_DIRECTORY {                
    DWORD   VirtualAddress;                
    DWORD   Size;                
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;  

导出表结构

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;

在这里插入图片描述
可以看出,整个导出表结构里面又包括了三张表,分别是AddressOfFunctions(导出函数地址表)、AddressOfNameOrdinals(导出函数序号表)以及AddressOfNames(导出函数名称表)
其中,AddressOfFunctions表储存了每个导出函数的地址(RVA),个数由NumberOfFunctions决定,需要加上ImageBase才是真正的函数地址,表宽为4字节;AddressOfNames表储存了每个导出函数的名称的地址(RVA),需要将这些RVA转换成FOA才能找到函数名称的真正位置,表宽4字节;AddressOfOrdinals表储存的是函数的导出序号,这个序号需要加上Base所存的值才是真正的导出序号,表宽2字节

  1. AddressOfFunctions通常比AddressOfNames大,因为可能存在没有以名字导出的函数。但存在一种可能,一个函数有多个名字指向同一地址,就会使AddressOfFunctions小于AddressOfNames
  2. AddressOfNameOrdinals的数量由AddressOfNames,他们的数量相等
  3. 而AddressOfFunctions的序号并不直接是AddressOfNameOrdinals中的值,而是它里面的值加上导出表结构里面的Base所存的值
  4. 导出函数方法分两种,一种是按名字导出,另一种是按序号导出

过程

1.名称导出

假设我们提供的函数名为Test。
先找到AddressOfNames表,将函数名Test和这个表里面存的地址指向的函数名一个一个比较,直到两者相同,此时这个函数名字的地址在AddressOfNames表中的索引为2。
再找到AddressOfOrdinals表,拿着刚刚找到的索引值去找到AddressOfOrdinals表中索引值与它相同的序号,此时这个序号为4。
最后再找到AddressOfFunctions表,将刚刚找到的序号4对应找到该表索引为4的地方所存的地址,该地址即为Test函数的地址。

2.序号导出

假设我们提供的序号是10,Base值为2。
用这个序号10减去Base值2得到一个序号8,就可以直接拿着这个序号8直接前往AddressOfFunctions找到索引为8的地方所存的地址,即为所找的函数地址。

另外,所有导出函数的个数=最后一个序号-第一个序号+1;
所以当序号表是乱序时,NumberOfFunctions的值就是错误的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值