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

小甲鱼pe详解打包 小甲鱼pe详解打包 全了 立即下载
小甲鱼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
基于Yolo11的无人机小目标检测系统的设计与性能优化改进项目实现 该项目旨在开发一个基于YOLO11的无人机目标检测系统,能够实时识别并定位无人机拍摄过程中捕捉的小目标。考虑到无人机拍摄的目标通常较小,系统将采用特定的调优策略,以提高小目标的检测精度和召回率。 阅读详情

相关推荐

scratch航天梦主题课程作品分享,包含ppt、素材包

而今年多国都将发射探测器尝试登陆月球,2023年或将称为“登月年”,请大家发挥创新思维,以“星辰大海”为创作主题,搜集相关信息 、展开联想,为实现升空 、探测 、取样贡献创意!即使去淘宝买的素材,也要从百度网盘,但素材太多大了或者太多文件,也要充值百度网盘超级会员才能保存,提高下载速度。同学们大家好,今天我们就要开始航天主题-嫦娥五号探月工程系列的编程课程了,不仅可以学习到很多航天知识,了解本次嫦娥五号的发射历程,还能让我们用编程遨游太空呢。即使下载了,也要上传,不是特别方便,尤其是不好查找。

少儿编程吕口口 2485

获取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的专栏 2132

解决turmex安装kali报错问题

在手机上安装好turmex后,都喜欢安装一个Linux系统,我当时安装的时kali,但是安装过程中,报错不断。 2019.8.24更新 1,出现问题首先看下载kali源文件是否完整 安装步骤中,会显示[解压中.....] ,可以看到解压的大小。 如图所示,完整源文件不小于81M。 如果源文件过小,则说明下载错误,而且在remove kali这个命令下,是不会删除源文件的,下一次安装只...

WeiLuckyStrike的博客 1万+

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

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

Jave.Lin 的学习笔记 7998

告别wx.showActionSheet:微信小程序自定义底部弹框的5种实现方式对比

本文深入对比了微信小程序中替代原生wx.showActionSheet的五种自定义底部弹框实现方案。从基础视图层模拟到组件化封装,再到利用第三方UI库、CSS3动画及Page-Meta组件,详细分析了各方案的优缺点与适用场景,旨在帮助开发者根据项目需求,选择最合适的方案以实现高度定制化、交互丰富的弹框效果。

weixin_29005499的博客 191

灰度发布、蓝绿部署、双活架构与数据同步/备份/迁移

本文系统介绍了现代互联网系统的核心部署策略与数据管理技术体系。主要内容包括:1)三种服务发布策略(灰度发布、蓝绿发布、滚动发布)的原理、实现方式和适用场景对比;2)高可用架构设计(同城双活、异地双活、异地多活)的技术方案;3)数据同步机制、备份策略与迁移方案的设计要点。文章通过架构图、流程图和配置示例详细展示了各类技术的实施方法,并分析了不同方案的优劣及风险控制措施,为构建高可用、高可靠的分布式系统提供了完整的技术指南。

zane的博客 516

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

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

brook0344的专栏 1893

IAR链接器配置文件(.icf)实战指南:从内存映射到代码布局

本文深入解析了IAR链接器配置文件(.icf)的核心作用与实战配置方法。作为嵌入式开发的“内存地图”,.icf文件精确控制代码与数据在Flash和RAM中的布局。文章从定义存储空间、划分区域、预留栈堆,到精确放置中断向量表、代码段及初始化控制,提供了完整的配置指南与避坑技巧,帮助开发者优化内存使用,解决链接错误,是掌握嵌入式系统底层内存管理的关键。

fun88的博客 918

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

内容 根据函数名字和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的博客 557

Armbian 国内源一键配置:告别卡顿,加速软件更新

本文详细介绍了如何为Armbian系统配置国内软件源,以解决默认国外源导致的更新缓慢、连接超时等问题。通过手动修改配置文件或使用高效的一键换源脚本,可将源切换至清华大学、阿里云等国内镜像站,实现apt更新与软件安装速度的质的飞跃,让Armbian开发体验更加流畅高效。

weixin_29215815的博客 246

FoundationPose复现及Realsense应用

FoundationPose是一个统一的基础模型,用于6D对象姿态估计和跟踪,支持基于模型和无模型的设置。在测试时可以立即应用于未见过的新对象,无需微调,只要给出其CAD模型,或者捕获少量RGBD参考图像。得益于统一框架,下游姿态估计模块在两种3D模型设置中都是相同的,当没有CAD模型时,使用神经隐式表示进行高效的新视角合成。通过大规模合成训练,辅以大型语言模型(LLM)、一种基于transformer的新架构和对比学习公式,实现了强大的泛化能力。

m0_56661101的博客 1万+

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

原文出自:www.fishc.com 小甲鱼PE详解之输出表(导出表)详解(PE详解09) 当PE 文件被执行的时候,Windows 加载器将文件装入内存并将导入表(Export Table) 登记的动态链接库(一般是DLL 格式)文件一并装入地址空间,再根据DLL 文件中的函数导出信息对被执行文件的IAT 进行修正。 基础补充:很多朋友可能看到这里会有点懵,各位看官请允许小甲鱼

阿特图 1212

iverilog+GTKwave使用总结

iverilog是一个开源的硬件描述语言(HDL)仿真工具,用于对硬件描述语言(如Verilog)编写的数字电路进行仿真。它可以将Verilog代码编译为仿真模型,并通过仿真运行来验证设计的正确性。iverilog支持IEEE 1364-2005 Verilog语言标准,并提供了丰富的功能,包括对多种Verilog语言特性的支持、模块化设计、测试平台等。它还可以与其他工具(如GTKWave波形查看器)配合使用,以便进行仿真后的波形查看和分析。

争取早日成为硅农 2万+
上一篇: 小甲鱼PE详解之输入表(导入表)详解2(PE详解08)
下一篇: 小甲鱼PE详解之基址重定位详解(PE详解10)
M-先生
博客等级 码龄17年 60粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值