5. 导出表

DEF文件如下所示:

EXPORTS

    Inject @12

    MyAdd @14

    MySub @17

    MyMul @11 NONAME

    MyDiv @19

    g_szInject @15

 

用调试器加载编译好的dll文件,查看导出信息:

 

 

 

 

 

用十六进制编辑器打开dll文件,定位到导出表,可以发现导出的字符串是按ASCII顺序排列的,方便系统折半查找

 

 

 

 

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,索引值是2字节的word,代表在AddressOfFunctions中的索引

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

 

 

 

 

通过序号查询函数,例如GetProcAddress(hModule, 14)

  1. 序号14减去Base,得到3
  2. 去地址表中找到下标为3的项,得到00001014
  3. 00001014加上hModule,即为函数地址

 

通过名称查询函数,例如GetProcAddress(hModule, “MyAdd”)

  1. 定位到名称表,对比字符串,发现000020D9指向的是“MyAdd”
  2. 000020D9在名称表中下标为1,所以找到序号表下标为1的项,其值为0003
  3. 地址表中找到下标为3的项,结果为00001014
  4. 00001014加上hModule,即为函数地址

 

关于转发:

如果查询到的地址在导出表范围内(加载后的地址,即VA),则为转发,需要递归调用自己实现的GetProcAddress,如果不在导出表范围内,则可直接返回。 

 

 

posted @ 2020-11-03 21:11  八转达人  阅读(114)  评论(0编辑  收藏  举报