《解密系列-系统篇》第九讲:PE结构详解9
本帖最后由 shuiyu 于 2018-1-23 23:00 编辑越努力,越幸运。欢迎大家来看我的笔记{:10_297:},不对的请各位大佬指正,谢谢{:10_254:}
具体详情可到:http://blog.csdn.net/shuiyu486/article/details/79145514
一、导出表
(1)有一些函数很多程序都会用到,为每一个程序写一个相同的函数看起来似乎有点浪费空间。
因此Windows就整出了动态链接库的概念,将一些常用的函数封装成动态链接库,等到需要的时候通过直接加载动态链接库。
将需要的函数整合到自身中,这样就大大的节约了内存中资源的存放。
(2)导出表就是记载着动态链接库的一些导出信息。通过导出表,DLL 文件可以向系统提供导出函数的名称、序号和入口地址等信息,比便Windows 加载器通过这些信息来完成动态连接的整个过程。
(3)扩展名为.exe 的PE 文件中一般不存在导出表,而大部分的.dll 文件中都包含导出表。但注意,这并不是绝对的。
例如纯粹用作资源的.dll 文件就不需要导出函数啦,另外有些特殊功能的.exe 文件也会存在导出函数。
所以,世事无绝对……好了,我们接下来就对导出表的结构进行分析。
二、导出表结构
(1)导出表(Export Table)中的主要成分是一个表格,内含函数名称、输出序数等。序数是指定DLL 中某个函数的16位数字,在所指向的DLL 文件中是独一无二的。
(2)数据目录表的第一个成员指向导出表,是一个IMAGE_EXPORT_DIRECTORY(以后简称IED)结构,IED 结构的定义如下:
(PS:具体的成员详情到最上面的那个链接里了解吧{:10_264:} )
三、实战讲解 (PS:其实懂了这个就全都会了{:10_256:} )
PS:不论我们是通过序号查找函数入口地址的还是函数名称查找入口地址的,我们跟着小甲鱼的视频操作、了解、最后自己能独立找到就行了(其实是因为看那一大堆文字头晕{:10_250:} )。
开始
(1)把实验程序载入UE和PE_info,从PE 文件头中的 IMAGE_OPTIONAL_HEADER32 结构中取出数据目录表,并从第一个数据目录中得到导出表的RVA。(RVA转成物理地址前面几讲都用到了,就不解释了)
(2)数据目录表的第一个成员指向导出表,是一个IMAGE_EXPORT_DIRECTORY(以后简称IED)结构,我们从IED结构中得到对我们有用的数据:
Name:209C 模块真实的名称
Base:1 基数(加上序号就是函数地址数组的索引值)
NumberOfFunctions:2 导出函数的总数
NumberOfNames:2 以名称方式导出的函数的总数(这个字段和上一个字段就表示所有函数都是以名称方式导出的)
AddressOfFunctions:2088 指向输出函数地址的RVA
AddressOfNames:2090 指向输出函数名字的RVA
AddressOfNameOrdinals:2098 指向输出函数序号的RVA
(3)得到第一个函数的入口地址
1.指向第一个输出函数名字的RVA为:2090 物理地址为:690 物理地址上的值为:20A8
20A8的物理地址为:6A8 可以看到有两个函数的名字:第一个为_DecCount、第二个为_IncCount
2.指向第一个输出函数序号的RVA为:2098 物理地址为:698 物理地址上的值为:00(字形数据)加上Base得到1,
即第一个函数:_DecCount指向第1项
3.那么指向第一个输出函数地址的RVA为:2088 物理地址为:688 物理地址上的值为:1046 即_DecCount函数的入口地址为1046
(4)根据上面求出:第二个函数的入口地址
1.根据指向第二个输出函数序号的RVA为:2098+2 物理地址为:698+2 物理地址上的值为:01(字形数据)加上Base得到2,
即第二个函数:_IncCount指向第2项
2.那么
指向第二个输出函数地址的RVA为:2088+4 物理地址为:688+4 物理地址上的值为:1023 即_IncCount函数的入口地址为1023
(5)验证
因为我们得到的入口地址为一个RVA,是相对于本PE文件的基址的虚拟地址,即基址加上RVA就得到了真正的地址,如下图:
谢谢小甲鱼带来的视频教程,感谢!! {:10_303:}
本节结束,多谢览阅!
越努力,越幸运。谢谢大家来看我的笔记{:10_297:},不对的请各位大佬指教,谢谢{:10_254:}
页:
[1]