0x01  导出表结构

    导出表是由数据目录表中的第一个成员DataDirectory[0]指出的:

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

   

    导出表就是记载着动态链接库的一些导出信息。通过导出表,DLL 文件可以向系统提供导出函数的名称、序号和入口地址等信息,比便Windows 加载器通过这些信息来完成动态连接的整个过程。扩展名为.exe 的PE 文件中一般不存在导出表,而大部分的.dll 文件中都包含导出表。但这并不是绝对的。例如纯粹用作资源的.dll 文件就不需要导出函数啦,另外有些特殊功能的.exe 文件也会存在导出函数。

    当PE文件被加载为模块时候,Windows加载器会将导入表中登记的DLL文件一并装入,再根据DLL文件中的函数导出信息对被执行文件的IAT表进行修正。

    Windows 在加载一个程序后就会在内存中为该程序开辟一个单独的4G虚拟地址空间(x86下)。有一些函数很多程序都会用到,为每一个程序所调用的相同的函数都占用一次内存空间显得很浪费,因此Windows提出了了动态链接库的概念,将一些常用的函数封装成动态链接库,等到需要的时候通过直接加载动态链接库,将需要的函数映射到自己的地址空间中,从而提高了内存的利用率。

  

     导出表的结构成员: 1 typedef struct _IMAGE_EXPORT_DIRECTORY {

     DWORD   Characteristics;        //未使用,总是定义为0
DWORD TimeDateStamp; //文件生成时间
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;            //模块的真实名称RVA
DWORD Base;            //导出函数序号的起始值,将AddressOfFunctions 字段指向的入口地址表的索引号加上这个起始值就是对应函数的导出序号。假如Base 字段的值为x,那么入口地址表指定的第1个导出函数的序号就是x;第2个导出函数的序号就是x+1。总之,一个导出函数的导出序号等于Base 字段的值加上其在入口地址表中的位置索引值。
DWORD NumberOfFunctions;   //导出函数的个数 DWORD NumberOfNames;      //名称方式导出的函数的总数。有的导出函数是没有名字的,只有序号
DWORD AddressOfFunctions; //一个RVA 值,指向包含全部导出函数入口地址的双字数组(EAT)。数组中的每一项是一个RVA 值,数组的项数等于NumberOfFunctions 字段的值。
DWORD AddressOfNames; //一个RVA 值,指向函数名字符串地址表。这个地址表是一个双字数组,数组中的每一项指向一个函数名称字符串的RVA。数组的项数等NumberOfNames 字段的值,所有有名称的导出函数的名称字符串都定义在这个表中
DWORD AddressOfNameOrdinals; //一个RVA 值,指向另一个word 类型的数组(注意不是双字数组)。数组项目与文件名地址表中的项目一一对应,项目值代表函数入口地址表的索引,这样函 数名称与函数入口地址关联起来,起到一个桥梁的作用。
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

  

0x02  关键问题

(1)通过函数序号得到函数地址: 

    1>由DOS头定位到PE头。

    2>由PE头定位到PE头中的中的 可选头IMAGE_OPTIONAL_HEADER32 结构中取出数据目录表,并从第一个数据目录中得到导出表的RVA。

    3>从导出表的 Base 字段得到起始序号。

    4>将需要查找的导出序号减去起始序号,得到函数在入口地址表中的索引。

    5>检测索引值是否大于导出表的 NumberOfFunctions 字段的值,如果大于后者的话,说明输入的序号是无效的。

    6>用这个索引值在 AddressOfFunctions 字段指向的导出函数入口地址表中取出相应的项目,这就是函数入口地址的RVA 值,当函数被装入内存的时候,这个RVA 值加上模块实际装入的基地址,就得到函数真正的入口地址。

(2)通过函数名称得到函数地址:

    1>由DOS头定位到PE头。(同上)

    2>由PE头定位到PE头中的中的 可选头IMAGE_OPTIONAL_HEADER32 结构中取出数据目录表,并从第一个数据目录中得到导出表的RVA。(同上)   

    3>从导出表的NumberOfNames 字段得到已命名函数的总数,并以这个数字作为循环的次数来构造一个循环。

    4>从AddressOfNames 字段指向得到的函数名称地址表的第一项开始,在循环中将每一项定义的函数名与要查找的函数名相比较,如果没有任何一个函数名是符合的,表示文件中没有指定名称的函数。

    5>如果某一项定义的函数名与要查找的函数名符合,那么记下这个函数名在字符串地址表中的索引值,然后在AddressOfNamesOrdinals 指向的数组中以同样的索引值取出数组项的值,我们这里假设这个值是x。

    6>以 x 值作为索引值,在 AddressOfFunctions 字段指向的函数入口地址表中获取的 RVA 加上模块基地址就是函数的入口地址。

PE文件 02 导出表的更多相关文章

  1. 【学习】Windows PE文件学习(一:导出表)

    今天做了一个读取PE文件导出表的小程序,用来学习. 参考了<Windows PE权威指南>一书. 首先, PE文件的全称是Portable Executable,可移植的可执行的文件,常见 ...

  2. 【C#进阶系列】02 PE文件,程序集,托管模块,元数据——还是那个Hello world

    好了,还是这张图,还是一样的Hello world. 因为本章其实很多都是讲一些命令行编译啊什么鬼的配置类的东西,要用的时候直接百度或者回头查书就可以了, 所以了解一下也就行了,也没有记录下来,接下来 ...

  3. 浅析MSIL中间语言——PE文件结构篇

    一.开篇 开篇我想讲一下于本文无关的话题,其实我很想美化一下自己博客园一直没时间弄,无意间找了博客园李宝亨的博客园里面有一篇分享自己主题的文章,我就将这个模板暂时用作我的blog主题,我要讲述一个关于 ...

  4. .NET的PE文件结构篇(转)

    一.开篇 开篇我要讲述一个关于PE文件结构的文章,这篇文章动手能力比较强,希望大家能够动手进行操作,这边文章篇幅有可能会长一些,为了方便大家阅读我可以将其分为几个部分进行讲解,主要分为以下几个部分: ...

  5. PE文件学习系列三-PE头详解

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com 最近比较忙 ...

  6. 修改PE文件的入口函数OEP

    修改入口函数地址.这个是最省事的办法,在原PE文件中新增加一个节,计算新节的RVA,然后修改入口代码,使其指向新增加的节.当然,如果.text节空隙足够大的话,不用添加新节也可以. BOOL Chan ...

  7. PE文件之资源讲解

    资源是PE文件中非常重要的部分,几乎所有的PE文件中都包含资源,与导入表与导出表相比,资源的组织方式要复杂得多,要了解资源的话,重点在于了解资源整体上的组织结构. 我们知道,PE文件资源中的内容包括: ...

  8. 手写PE文件(一)

    DOS Header(IMAGE_DOS_HEADER)->64 Byte DOS头部 DOS Stub 112字节 "PE"00(Signature) 4个字节 IMAGE ...

  9. 打造XP下可运行的微型PE文件

    前几天和朋友交流技术,提到手工打造微型PE文件,他说现在网上流传的大部分版本在XP SP3下都不能运行,于是心血来潮,拍着胸脯说:“你放心,忙完了帮你做一个.”后来花了半天时间,终于打造出一个XP下可 ...

随机推荐

  1. 服务器--远程桌面选择"本地资源"下不显示"本地磁盘"的解决办法(转)

    转自:http://blog.sina.com.cn/s/blog_4cd978f90102wsvc.html “远程连接桌面”,每次连接候,我都选择了“本地资源”下面的“磁盘驱动器”,都会在远程电脑 ...

  2. C#生成XSD规范

    首先在开始菜单中找到:Visual Studio 2005 命令提示 大柏树按:VS2010在:开始—> Microsoft Visual Studio 2010 —> Visual St ...

  3. LeetCode--459--重复的字符串

    问题描述: 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超过10000. 示例 1: 输入: "abab" 输出: T ...

  4. 微信小程序获取腾讯经纬度,得到具体地址

    getCityNameOFLocation: function() { var that = this; wx.getLocation({ type: 'wgs84', // 默认为 wgs84 返回 ...

  5. ubuntu下安装CAJ阅读器

    目录 1.ubuntu下wine的基本介绍 (1)wine的介绍 (2)wine的安装 (3)exe文件的安装 (4)exe程序的卸载 (6)wine的基本使用 2.CAJ阅读器的安装 (1)首先放上 ...

  6. 2-SET 前缀优化建图

    1, Duff in Mafia CodeForces - 587D 2, Ants CodeForces - 1007D

  7. XML注释与取消注释快捷键

    IntelliJ IDEA和eclipse中编辑Java文件时,注释和取消注释的快捷键都是: "CTRL + / " 编辑xml文件时, 注释:CTRL + SHIFT + / 取 ...

  8. python – time.sleep – 睡眠线程

    import time from threading import Thread class worker(Thread): def run(self): for x in xrange(0,11): ...

  9. InnoDB存储引擎介绍-(6) 一. Innodb Antelope 和Barracuda区别

    分类 Antelope是innodb-base的文件格式,Barracude是innodb-plugin后引入的文件格式,同时Barracude也支持Antelope文件格式.两者区别在于: 文件格式 ...

  10. loj 10000 活动安排

    ****这是一个贪心题,把结束时间排个序,然后留出更多的时间给后面的活动. #include<cstdio> #include<cstring> #include<alg ...