小甲鱼PE详解之输入表(导出表)详解(PE详解09)

甲鱼PE详解IMAGE_NT_HEADERS结构定义即各个属性的作用(PE详解02) 上一讲:小甲鱼PE详解IMAGE_DOS_HEADER结构定义即各个属性的作用PE HeaderPE相关结构NT映像头(IMAGE_NT_HEADER)的简称,里边包含着许多PE装载器用到的重要字段。下边小甲鱼将为大家详细讲解哈~(视频教程:http://fishc.com 阅读详情
上一讲:小甲鱼PE详解之输入表(导入表)详解2


小甲鱼PE详解之输出表(导出表)详解(PE详解09)


当PE 文件被执行的时候,Windows 加载器将文件装入内存并将导入表(Export Table) 登记的动态链接库(一般是DLL 格式)文件一并装入地址空间,再根据DLL 文件中的函数导出信息对被执行文件的IAT 进行修正。

( 基础补充:很多朋友可能看到这里会有点懵,各位看官请允许小甲鱼啰嗦一下,照顾初学者。我们都明白Windows 在加载一个程序后就在内存中为该程序开辟一个单独的虚拟地址空间,这样的话在各个程序自己看来,自己就拥有几乎任意地址的支配权,所以他自身的函数想放在哪个地址自己说了算。有一些函数很多程序都会用到,为每一个程序写一个相同的函数看起来似乎有点浪费空间,因此Windows就整出了动态链接库的概念,将一些常用的函数封装成动态链接库,等到需要的时候通过直接加载动态链接库,将需要的函数整合到自身中,这样就大大的节约了内存中资源的存放。如图:


有一个重要的概念需要记住:动态链接库是被映射到其他应用程序的地址空间中执行的,它和应用程序可以看成是“一体”的,动态链接库可以使用应用程序的资源,它所拥有的资源也可以被应用程序使用,它的任何操作都是代表应用程序进行的,当动态链接库进行打开文件、分配内存和创建窗口等操作后,这些文件、内存和窗口都是为应用程序所拥有的。所以,动态链接库用小甲鱼的话说就是“寄生虫”! )

那导出表是干啥用的呢? 导出表就是记载着动态链接库的一些导出信息。通过导出表,DLL 文件可以向系统提供导出函数的名称、序号和入口地址等信息,比便Windows 加载器通过这些信息来完成动态连接的整个过程。

友情提示:扩展名为.exe 的PE 文件中一般不存在导出表,而大部分的.dll 文件中都包含导出表。但注意,这并不是绝对的。例如纯粹用作资源的.dll 文件就不需要导出函数啦,另外有些特殊功能的.exe 文件也会存在导出函数。所以,世事无绝对……好了,我们接下来就对导出表的结构进行分析。



导出表结构


导出表(Export Table)中的主要成分是一个表格,内含函数名称、输出序数等。序数是指定DLL 中某个函数的16位数字,在所指向的DLL 文件中是独一无二的。在此我们不提倡仅仅通过序数来索引函数的方法,这样会给DLL 文件的维护带来问题。例如当DLL 文件一旦升级或修改就可能导致调用改DLL 的程序无法加载到需要的函数。

数据目录表的第一个成员指向导出表,是一个IMAGE_EXPORT_DIRECTORY(以后简称IED)结构,IED 结构的定义如下:

IMAGE_EXPORT_DIRECTORY STRUCT Characteristics DWORD ? ; 未使用,总是定义为0 TimeDateStamp DWORD ?      ; 文件生成时间 MajorVersion WORD ? ; 未使用,总是定义为0 MinorVersion WORD ? ; 未使用,总是定义为0 Name DWORD ? ; 模块的真实名称 Base         DWORD ? ; 基数,加上序数就是函数地址数组的索引值 NumberOfFunctions DWORD ? ; 导出函数的总数 NumberOfNames DWORD ? ; 以名称方式导出的函数的总数 AddressOfFunctions DWORD ? ; 指向输出函数地址的RVA AddressOfNames DWORD ? ; 指向输出函数名字的RVA AddressOfNameOrdinals DWORD ? ; 指向输出函数序号的RVA IMAGE_EXPORT_DIRECTORY ENDS

这个结构中的一些字段并没有被使用,有意义的字段说明如下。

  • Name:一个RVA 值,指向一个定义了模块名称的字符串。如即使Kernel32.dll 文件被改名为"Ker.dll",仍然可以从这个字符串中的值得知其在编译时的文件名是"Kernel32.dll"。
  • NumberOfFunctions:文件中包含的导出函数的总数。
  • NumberOfNames:被定义函数名称的导出函数的总数,显然只有这个数量的函数既可以用函数名方式导出。也可以用序号方式导出,剩下的NumberOfFunctions 减去NumberOfNames 数量的函数只能用序号方式导出。该字段的值只会小于或者等于 NumberOfFunctions 字段的值,如果这个值是0,表示所有的函数都是以序号方式导出的。
  • AddressOfFunctions:一个RVA 值,指向包含全部导出函数入口地址的双字数组。数组中的每一项是一个RVA 值,数组的项数等于NumberOfFunctions 字段的值。
  • Base:导出函数序号的起始值,将AddressOfFunctions 字段指向的入口地址表的索引号加上这个起始值就是对应函数的导出序号。假如Base 字段的值为x,那么入口地址表指定的第1个导出函数的序号就是x;第2个导出函数的序号就是x+1。总之,一个导出函数的导出序号等于Base 字段的值加上其在入口地址表中的位置索引值。
  • AddressOfNames 和 AddressOfNameOrdinals:均为RVA 值。前者指向函数名字符串地址表。这个地址表是一个双字数组,数组中的每一项指向一个函数名称字符串的RVA。数组的项数等于NumberOfNames 字段的值,所有有名称的导出函数的名称字符串都定义在这个表中;后者指向另一个word 类型的数组(注意不是双字数组)。数组项目与文件名地址表中的项目一一对应,项目值代表函数入口地址表的索引,这样函数名称与函数入口地址关联起来。(举个例子说,加入函数名称字符串地址表的第n 项指向一个字符串“MyFunction”,那么可以去查找 AddressOfNameOrdinals 指向的数组的第n 项,假如第n 项中存放的值是x,则表示AddressOfFunctions 字段描述的地址表中的第x 项函数入口地址对应的名称就是“MyFunction”复杂吧? 没事,接着看你就懂了,别放弃哦~)


整个流程跟其他PE 结构一样说起来复杂,但看图说话倒是挺容易的。所以小甲鱼还是本着实事求是的精神&……%¥#踏踏实实画图让大家好理解一点吧,来,请上图:


1. 从序号查找函数入口地址

下边小甲鱼带大家来模拟一下Windows 装载器查找导出函数入口地址的整个过程。如果已知函数的导出序号,如何得到函数的入口地址呢 ?

Windows 装载器的工作步骤如下:

  1. 定位到PE 文件头
  2. 从PE 文件头中的 IMAGE_OPTIONAL_HEADER32 结构中取出数据目录表,并从第一个数据目录中得到导出表的RVA
  3. 从导出表的 Base 字段得到起始序号
  4. 将需要查找的导出序号减去起始序号,得到函数在入口地址表中的索引
  5. 检测索引值是否大于导出表的 NumberOfFunctions 字段的值,如果大于后者的话,说明输入的序号是无效的
  6. 用这个索引值在 AddressOfFunctions 字段指向的导出函数入口地址表中取出相应的项目,这就是函数入口地址的RVA 值,当函数被装入内存的时候,这个RVA 值加上模块实际装入的基地址,就得到了函数真正的入口地址


2. 从函数名称查找入口地址

如果已知函数的名称,如何得到函数的入口地址呢?与使用序号来获取入口地址相比,这个过程要相对复杂一点!

Windows 装载器的工作步骤如下:

  1. 最初的步骤是一样的,那就是首先得到导出表的地址
  2. 从导出表的 NumberOfNames 字段得到已命名函数的总数,并以这个数字作为循环的次数来构造一个循环
  3. 从 AddressOfNames 字段指向得到的函数名称地址表的第一项开始,在循环中将每一项定义的函数名与要查找的函数名相比较,如果没有任何一个函数名是符合的,表示文件中没有指定名称的函数
  4. 如果某一项定义的函数名与要查找的函数名符合,那么记下这个函数名在字符串地址表中的索引值,然后在 AddressOfNamesOrdinals 指向的数组中以同样的索引值取出数组项的值,我们这里假设这个值是x
  5. 最后,以 x 值作为索引值,在 AddressOfFunctions 字段指向的函数入口地址表中获取的 RVA 就是函数的入口地址


一帮情况下病毒程序就是通过函数名称查找入口地址的,因为病毒程序作为一段额外的代码被附加到可执行文件中的,如果病毒代码中用到某些 API 的话,这些 API 的地址不可能在宿主文件的导出表中为病毒代码准备好。因此只能通过在内存中动态查找的方法来实现获取API 的地址。关于病毒代码具体的实现分析,小甲鱼在今后将跟大家共同研究讨论这个话题~


输出表结构实例分析(具体过程将在视频中演示,这里不啰嗦啦~)

工具:PEinfo.exe, UltraEdit, W32DasmV10.0
解剖对象:Counter.dll

友情提示:以上工具均可在此处下载无病毒无二次污染版本,在其他地方下载谨慎病毒威胁。



下一讲:小甲鱼PE详解之 基址重定位 详解


Neo4j桌面版导入CVS文件 我们的relation.csv是这样的。 阅读详情

相关推荐

Altair HyperWorks软件二次开发:二次开发成果展示与报告撰写

HyperMesh Python API允许用户通过Python脚本控制HyperMesh的大部分功能,包括模型创建、修改和分析。它提供了丰富的函数库,可以处理节点、元素、材料属性、载荷和边界条件等。二次开发可以用于创建自定义工具,这些工具可以集成到HyperWorks中,提供特定的功能或简化复杂的操作。

kkchenjj的博客 1587

获取windows导出函数地址标准方法

http://www.4hou.com/system/10590.htmlhttps://msdn.microsoft.com/zh-cn/library/ms679291.aspxhttps://bbs.pediy.com/thread-188881.htmhttps://bbs.pediy.com/thread-189324.htm 

CoderAldrich的专栏 2125

甲鱼pe详解打包

甲鱼pe详解打包 全了

强大的W32Dasm反汇编工具使用教程

W32Dasm是一个强大的反汇编工具,操作简单,使用方便。通常被程序员使用,当然也可被用来Crack软件了,很适合Cracker使用。我在这把与crack相关的功能简述如下: 1.0 开始 2.0 保存反汇编文本文件和创建方案文件 3.0 反汇编文本代码的基本操作 4.0 复制汇编代码文本 5.0 装载32位的汇编代码动态调试 6.0 运行,暂停或终止程序 7.0 单步跟踪程序

Jave.Lin 的学习笔记 7992

W32DASM 和 OLLYDBG 配合起来破解反汇编算法

一、W32DASM会总结出每个函数的被调用关系,并且还对应导出函数名字,看起来很方便二、OLLYDBG1、F2是加断点,F7是进入函数,F8是不CALL函数往下2、右键点注释中的地址可以查看内存数据,这非常重要3、调试的时候一定要写注释,保存注释,备份UDD4、右键查看可以选择DLL,有限查看标识可以定位导出函数地址,然后加断点

brook0344的专栏 1888

KERNEL32.dll的ExportTable以及如何查找导出的函数

我的上一篇博客Analysis of notepad process loading涉及的程序是没有ExportTable的,所以这一篇呢,就分析一下DLL里的ExportTable,以KERNEL32.dll为例。 首先在Hex Edit里打开KERNEL32.dll: 可以看出,KERNEL32.dll还是符合PE文件格式滴~① ExportTable(RVA):00 0B 4D E0,Si

乱七八糟の中转站 1744

查看Windows、linux动态库的导出函数

打开vs的命令窗口: 在命令行输入命令:dumpbin /exports dll文件完整路径,即可得到DLL的接口。 如:dumpbin /exports “C:\Windows\System32\user32.dll” 查看静态库的信息要用命令行来实现: dumpbin /LINKERMEMBER Test.lib > 1.txt 上面的功能是将静态库的信息导出保存在1.txt文件中,这样就可以在1.txt文件中查看相关的信息了 linux动态库(参考:ht...

1694

动态链接库是如何建立的(3)如何查看到导出了那些函数?如何查看导入了哪些函数?

1.当我们在写dll的时候,如何查看我们的动态链接库导出了哪些函数呢? 过程1 (1)打开命令提示符 (2)在命令提示符窗口下cd到动态链接库所在的位置 (3)用dunmpbin -exports Dll1.dll查看 过程2 (1)打开命令提示符 (2)在命令提示符窗口下cd到testdll所在的位置 (3)用dunmpbin -imports TestDll1.dll查看 2.代码说

蜕变的博客 1320

软件安全实验 通过导入查找关键函数地址并显示

内容 根据函数名字和kernel32的导出获得更多函数的地址并弹窗显示 在win7下成功编译运行,masm32安装目录需为c:\masm32 代码 .586 .model flat,stdcall option casemap:none include c:\masm32\include\windows.inc include c:\masm32\include\comctl32.inc includelib c:\masm32\lib\comctl32.lib include c:\masm32

Tracy_yi的博客 554

windows 查看DLL导出函数的方法

windows 查看DLL导出函数的方法 点我查看原文 在window下查看动态库的导出函数可以用vs自带的Dependenc工具; 对于VC6.0,VC所带的Depends软件,在VC6安装目录下的tools文件夹里面,可以直接运行。   VS2010中没有了Depends工具,如何查看DLL文件的导出接口呢?  VS2010的操作方法如下: 1. 打开

zhyh1435589631的专栏 5万+

TCP2ComV1.1.5.1免费好用的串口转TCP工具.zip

一个串口转TCP的程序,能很好的满足远程串口传输、调试需求,基本特征如下:1、支持打开物理串口和虚拟串口(不创建虚拟串口,但能打开其他工具创建的虚拟串口)。2、支持通过TCP客户端连接到远程TCP服务器。3、支持TCP客户端自动重连,并可配置重连周期。4、支持TCP服务端监听,支持接入一个TCP连接,不支持多个TCP连接同时接入。5、支持日志跟踪功能。6、支持日志自动清空功能,并能配置。7、支持日志暂停显示功能。8、支持通信计数功能。9、支持通信计数手动清零功能。10、支持配置自动保存功能,软件下次启动自动加载上次配置。

上一篇: 小甲鱼PE详解之输入表(导入表)详解2(PE详解08)
下一篇: 小甲鱼PE详解之基址重定位详解(PE详解10)
fish_c
博客等级 码龄16年 51粉丝 11原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值