《Windows PE》4.2 绑定导入表

news2025/4/6 0:05:16

绑定导入表(Bound Import Table)是文件中的一个数据结构,用于存储已经绑定(即完成绑定导入)的外部函数的信息。

本节必须掌握的知识点:

        绑定导入表数据结构

        实例分析

4.2.1 绑定导入表数据结构

绑定导入是指在程序加载时,将程序所依赖的外部函数的地址与程序的IAT(Import Address Table,导入地址表)进行绑定的过程。这样,程序就可以直接通过IAT中的函数指针来调用这些外部函数,而无需再进行动态链接的过程。

绑定导入可以分为静态绑定和动态绑定两种方式:

●静态绑定:

在编译时,链接器将外部函数的地址直接嵌入到程序的IAT中。

静态绑定生成的可执行文件会包含被依赖函数的实际地址,因此在程序加载时无需进行额外的动态链接操作。

静态绑定的优点是加载速度快,无需运行时动态链接库的支持。但缺点是可执行文件的大小会增加,并且无法在运行时动态地加载新的函数或库。

●动态绑定:

在程序加载时,操作系统会根据IAT中的函数名称来查找并绑定外部函数的实际地址。

动态绑定通过操作系统的动态链接器(如Windows的LoadLibrary和GetProcAddress函数)来实现。

动态绑定的优点是可执行文件的大小较小,可以在运行时动态加载新的函数或库。但缺点是加载过程相对较慢,因为需要进行额外的符号解析和地址重定位操作。

绑定导入的具体实现方式取决于操作系统和编程语言。在Windows环境下,可以使用PE文件格式、IAT表和动态链接库(DLL)来实现绑定导入。在Linux环境下,可以使用ELF文件格式和动态链接器(ld.so)来实现绑定导入。

当可执行文件被绑定时,IAT 中的IMAGE_THUNK_DATA结构将被导入函数的实际地址覆盖。磁盘上的可执行文件具有其 IAT 中其他 DLL 中 API 的实际内存中地址。加载绑定的可执行文件时,Windows 加载程序可以绕过查找每个导入的 API 并将其写入 IAT 的步骤。正确的地址已经在那里了!

您可能对可执行绑定的安全性持怀疑态度。毕竟,如果绑定可执行文件并且它导入的 DLL 发生变化怎么办?比如kernel32.dll,在Windows 2000中其加载到进程空间的基地址为 0x77e60000,而在Windows XP SP3中其加载地址则是0x7c800000。发生这种情况时,IAT 中的所有地址都无效。在为PE加入绑定导入机制的时候,微软就已经考虑到了这个问题,所以假定PE加载前对IAT的修正都是正确的。那么PE的加载速度是加快的,即使绑定以后的EXE程序在其他的兼容系统中运行时,其地址出现错误,PE加载也有检测错误的机制。如果地址检测出错误, PE加载器会重新接管这项工作,加载时对IAT进行修正。

微软提供了一个绑定工具bind.exe程序,该程序可以把导入表中IAT表项IMAGE_ THUNK_DATA32的内容都静态替换成虚拟内存地址,然后在数据目录表的第12项指定的位 置声明这些更改。Windows在加载目标PE相关的动态链接库时,会首先检査这些地址是否正确合法,这些检查包括当前系统的DLL版本是否符合绑定导入结构中描述的版本号,如果不符合或者DLL需要被重新定位,加载器就会去遍历OriginalFirstThunk指向的数组(也就是 INT),计算新的地址。如果导入表是单桥结构,此时的遍历会失效,所以说单桥结构无法实 施静态绑定操作。

 注意

绑定导入是一种静态链接的方式,因此在程序运行期间无法更改绑定的外部函数地址。如果需要在运行时动态加载新的函数或库,可以考虑使用延迟加载或手动加载的方式。

本节我们讲述PE文件中的静态绑定导入,我们将在下一小节讲述延迟加载,在第十章详细讲述动态手动加载。

●绑定导入表描述符的结构如下:

typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {

    DWORD TimeDateStamp;    //时间戳

    WORD OffsetModuleName;// 指向DLL的名称

    WORD NumberOfModuleForwarderRefs;// ModuleForwarderRef 数目

    // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows

} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR;

TimeDateStamp,一个 DWORD,其中包含导入的 DLL 的时间/日期戳。

OffsetModuleName,一个 WORD,其中包含指向具有导入 DLL 名称的字符串的偏移量。此字段是与第一个IMAGE_BOUND_IMPORT_DESCRIPTOR的偏移量(不是 RVA)。

NumberOfModuleForwarderRefs,一个 WORD,其中包含紧跟此结构的IMAGE_BOUND_FORWARDER_REF结构数。这些结构与IMAGE_BOUND_IMPORT_DESCRIPTOR相同,只是保留了最后一个 WORD(NumberOfModuleForwarderRefs)。

在简单的情况下,每个导入的DLL的IMAGE_BOUND_IMPORT_DESCRIPTORs将是一个简单的数组。但是,当绑定到转发到另一个DLL的API时,还必须检查转发的DLL的有效性。因此,IMAGE_BOUND_FORWARDER_REF结构与IMAGE_BOUND_IMPORT_DESCRIPTORs结构交织在一起。

假设您链接到HeapAlloc,它被转发到NTDLL中的RtlAllocateHeap。然后在可执行文件上运行BIND。在你的EXE中,你会有一个IMAGE_BOUND_IMPORT_DESCRIPTOR for KERNEL32.DLL,然后是一个IMAGE_BOUND_FORWARDER_REF for NTDLL.DLL。紧随其后的可能是您导入和绑定的其他dll的附加IMAGE_ BOUND_IMPORT_DESCRIPTORs。

绑定导入表中的每个元素都是一个被绑定的外部函数的地址。这些地址在程序加载时由操作系统或动态链接库进行填充,以便程序可以直接调用这些函数。

 注意

1.绑定导入表是可选的,不是所有的PE文件都会包含绑定导入表。只有在编译时进行了绑定导入操作,并且保留了绑定导入表的信息,才会在PE文件中存在绑定导入表。

2.绑定导入表的目的是为了提高程序的运行效率,避免了每次运行时都进行动态链接的开销。通过在程序加载时将外部函数的地址直接嵌入到绑定导入表中,可以加快程序的启动速度。

       3.同一操作系统的不同版本导入函数地址可能存在差异,这就意味着绑定导入函数的地址可能存在兼容问题的风险。如果绑定导入函数地址错误,操作系统PE加载器会启用导入表实现IAT表的重新绑定。

       4.绑定导入表通常会存在于32位PE文件中,64位PE文件并不包含绑定导入表。

4.2.2 实例分析

实验二十九:绑定导入表的定位及解析

       绑定导入表的RVA地址及大小信息位于数据目录项的第11项。我们以32位记事本程序为例:

       ●数据目录项:第11项。

将notepad32.exe拖入WinHex,并找到数据目录项,如下所示:

00000150   00 00 00 00 10 00 00 00  00 00 00 00 00 00 00 00   ................

00000160   04 76 00 00 C8 00 00 00  00 B0 00 00 20 7F 00 00   .v..?...?. ...

00000170   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000180   00 00 00 00 00 00 00 00  50 13 00 00 1C 00 00 00   ........P.......

00000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001A0   00 00 00 00 00 00 00 00  A8 18 00 00 40 00 00 00   ........?..@...

000001B0   50 02 00 00 D0 00 00 00  00 10 00 00 48 03 00 00   P...?......H...

000001C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001D0   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   .........text...

       数据目录项第11项中记录绑定导入表的RVA地址为:00000250H,大小为D0H。

●绑定导入表:位于文件偏移地址250H地址处。

      

00000250   A2 BD 02 48 58 00 00 00  B6 BD 02 48 65 00 00 00   ⒔.HX...督.He...

00000260   CA BD 02 48 71 00 00 00  6C BD 02 48 7E 00 00 00   式.Hq...l?H~...

00000270   6C BD 02 48 8B 00 00 00  89 BD 02 48 96 00 00 00   l?H?..壗.H?..

00000280   C6 BD 02 48 A3 00 01 00  C5 BD 02 48 B0 00 00 00   平.H?..沤.H?..

00000290   81 BD 02 48 BA 00 00 00  BD BD 02 48 C4 00 00 00   .?H?..浇.H?..

000002A0   00 00 00 00 00 00 00 00  63 6F 6D 64 6C 67 33 32   ........comdlg32

000002B0   2E 64 6C 6C 00 53 48 45  4C 4C 33 32 2E 64 6C 6C   .dll.SHELL32.dll

000002C0   00 57 49 4E 53 50 4F 4F  4C 2E 44 52 56 00 43 4F   .WINSPOOL.DRV.CO

000002D0   4D 43 54 4C 33 32 2E 64  6C 6C 00 6D 73 76 63 72   MCTL32.dll.msvcr

000002E0   74 2E 64 6C 6C 00 41 44  56 41 50 49 33 32 2E 64   t.dll.ADVAPI32.d

000002F0   6C 6C 00 4B 45 52 4E 45  4C 33 32 2E 64 6C 6C 00   ll.KERNEL32.dll.

00000300   4E 54 44 4C 4C 2E 44 4C  4C 00 47 44 49 33 32 2E   NTDLL.DLL.GDI32.

00000310   64 6C 6C 00 55 53 45 52  33 32 2E 64 6C 6C 00 00   dll.USER32.dll..

      

 

总结

       Notepad32.exe中共有10个_IMAGE_BOUND_IMPORT_DESCRIPTOR绑定导入表描述符结构,对应10个DLL模块名。

       每个绑定导入表描述符的前4个字节为时间戳。

       OffsetModuleName字段指向DLL模块名。以第一个绑定导入表描述符为例,RVA地址为0058H,FOA地址=0058H+250H=2A8H,即comdlg32.dll。

       NumberOfModuleForwarderRefs字段为ModuleForwarderRef (模块转发器)数目。以284H地址处的A3 00 01 00为例,A3指向2F3H地址处的KERNEL32.dll,模块转发器数量为1,即紧随其后的B0 00 00 00,指向300H地址处的NTDLL.DLL。

       接下来我们再观察一下IAT导入函数地址表。IAT表的RVA地址为数据目录项的第12项,RVA值为00001000H,大小为348H。位于.text节区的起始位置,即文件偏移地址00000400H地址处。

       ●节表:绑定导入表位于.text节区400H文件偏移地址处。

000001D0   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   .........text...

000001E0   48 77 00 00 00 10 00 00  00 78 00 00 00 04 00 00   Hw.......x......

000001F0   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ............ ..`

00000200   2E 64 61 74 61 00 00 00  A8 1B 00 00 00 90 00 00   .data...?......

00000210   00 08 00 00 00 7C 00 00  00 00 00 00 00 00 00 00   .....|..........

00000220   00 00 00 00 40 00 00 C0  2E 72 73 72 63 00 00 00   ....@..?rsrc...

00000230   20 7F 00 00 00 B0 00 00  00 80 00 00 00 84 00 00    ....?..€...?.

00000240   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 40   ............@..@

       ●IAT导入函数地址表:大小384H,以被填充导入函数的实际VA地址。

00000400   EF 6F DA 77 17 6C DA 77  25 BA DC 77 05 BD DC 77   飋趙.l趙%很w.杰w

00000410   AB 7A DA 77 42 78 DA 77  57 D7 DA 77 00 00 00 00   珃趙Bx趙W宗w....

00000420   70 D2 18 77 00 00 00 00  19 DC F0 77 05 4A F2 77   p?w.....莛w.J騱

00000430   A9 DE F0 77 5F 6E EF 77  56 F4 F0 77 9D 7F EF 77   ┺饂_n飛V麴w..飛

00000440   28 BE EF 77 25 4B F2 77  BB A5 EF 77 AC 7E EF 77   (撅w%K騱互飛瑍飛

00000450   95 56 F2 77 22 FB F1 77  C1 61 EF 77 B3 83 EF 77   昖騱"w羇飛硟飛

00000460   69 5A EF 77 8F 93 EF 77  FA 6B EF 77 B9 7D EF 77   iZ飛.擄w鷎飛箎飛

00000470   DB 5E EF 77 B7 D4 EF 77  05 3A F0 77 AE 3A F0 77   踍飛吩飛.:饂?饂

00000480   10 94 EF 77 70 5B EF 77  00 00 00 00 B8 97 80 7C   .旓wp[飛....笚€|

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2194056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AIGC】ChatGPT是如何思考的:探索CoT思维链技术的奥秘

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯什么是CoT思维链CoT思维链的背景与技术发展需求 💯CoT思维链的工作原理💯CoT思维链的应用领域💯CoT思维链的优势💯CoT思维…

动态内存管理笔试题

目录 1.第一题1.1如何修改 2.第二题2.1题想2.2深刻理解 3.第三题4.第四题 1.第一题 void GetMemory(char* p) {p (char*)malloc(100); } void Test(void) {char* str NULL;GetMemory(str);strcpy(str, "hello world");printf(str); }请问运⾏Test 函数会有什么样的…

解锁数字化营销成功密码

在趋势部分,列举了移动优先、社交媒体主导、个性化营销、视频营销崛起和数据驱动决策等方面,让读者快速了解数字化营销的发展方向。策略部分强调了明确目标受众、制定整合营销策略、优化用户体验、重视内容营销和社交媒体营销以及利用搜索引擎优化和数据…

jQuery——平滑翻页

平滑翻页 param next true:下一页 false:下一页 本文分享到此结束,欢迎大家评论区相互讨论学习,下一篇继续分享jQuery中循环翻页的学习。

Docker 实践与应用举例

Docker 实践与应用举例 Docker 已经成为现代软件开发和部署中的重要工具,通过容器化技术,开发者可以轻松管理应用的依赖环境、简化部署流程,并实现跨平台兼容性。本篇博客将详细介绍 Docker 的基本概念、实践操作以及应用场景,帮…

工业缺陷检测深度学习方法

工业缺陷检测深度学习方法 基于深度学习的工业缺陷检测方法可以降低传统人工质检的成本, 提升检测的准确性与效率, 因而在智能制造中扮演重要角色, 并逐渐成为计算机视觉领域新兴的研究热点之一. 其被广泛地应用 于无人质检、智能巡检、质量控制等各种生产与运维场景中. 本综述…

跨设备剪贴板同步服务ClipCascade

什么是 ClipCascade ? ClipCascade 是一款开源的轻量级工具,可以自动同步您的剪贴板在多个设备之间,无需按键。它确保设备之间无缝的剪贴板共享,并以端对端加密优先保护隐私。无论您是在不同工作站之间切换,还是仅仅希…

检索增强思考 RAT(RAG+COT):提升 AI 推理能力的强大组合

在人工智能领域,大型语言模型(LLMs)已经取得了显著的进展,能够生成类似人类的文本并回答各种问题。然而,它们在推理过程中仍面临一些挑战,例如缺乏对事实的准确把握以及难以处理复杂的多步骤问题。为了解决…

Unity3D 单例模式

Unity3D 泛型单例 单例模式 单例模式是一种创建型设计模式,能够保证一个类只有一个实例,提供访问实例的全局节点。 通常会把一些管理类设置成单例,例如 GameManager、UIManager 等,可以很方便地使用这些管理类单例,…

用YOLO和LLM增强的OCR

虽然最近我花了很多时间在大型语言模型 (LLM) 上进行实验,但我对计算机视觉的热情始终未减。因此,当我有机会将两者融合在一起时,我迫不及待地想要立即开始。在 Goodreads 上扫描书籍封面并将其标记为已读一直感觉有点神奇,我很兴…

SSM外卖点餐软件APP-计算机毕业设计源码30768

目 录 摘要 1 绪论 1.1 研究背景 1.2研究目的 1.3论文结构与章节安排 2 外卖点餐软件APP系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能…

这些编程工具竟然能让我效率翻倍?开发者必备神器盘点!

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

基于深度学习多层感知机进行手机价格预测

数据集介绍 数据集采用了Kaggle实战数据集,链接如下,如有需要可自行下载 https://www.kaggle.com/datasets/atefehmirnaseri/cell-phone-price/data 数据集简要介绍 • battery_power:电池的总能量存储(毫安时) • blue:设备…

人工智能对未来工作影响的四种可能性

随着人工智能(AI)技术的迅速发展,其对人类工作的影响已成为讨论的热点话题。我们经常听到有关AI威胁论的观点,担心它将取代人类工作,但也有专家认为AI将成为一种辅助工具,帮助人类提升工作效率。宾夕法尼亚…

嵌入式硬件设计

嵌入式硬件设计是指针对嵌入式系统(一种专用的计算机系统,通常嵌入到其他设备中)进行的硬件设计工作。嵌入式系统广泛应用于消费电子、工业控制、医疗设备、汽车电子、航空航天等领域。以下是嵌入式硬件设计的主要内容和步骤: 1.…

括号匹配——(栈实现)

题目链接 有效的括号https://leetcode.cn/problems/valid-parentheses/description/ 题目要求 样例 解题代码 import java.util.*; class Solution {public boolean isValid(String str) {Stack<Character> stacknew Stack<>();for(int i0;i<str.length();i)…

传统流程图和N-S流程图的区别

传统流程图和N-S流程图在表示算法和逻辑结构时有不同的特点和用途。以下是它们的主要区别&#xff1a; ### 传统流程图 1. **符号多样**&#xff1a;传统流程图使用多种几何形状表示不同的操作类型&#xff0c;如椭圆表示开始和结束&#xff0c;平行四边形表示输入输出&#…

JumperServer入门

一、安装部署 官方安装文档&#xff1a;快速入门 - JumpServer 文档 机器准备 CentOS7 ip 角色 192.168.252.145 主节点 192.168.252.146 被控节点1 192.168.252.148 被控节点2 安装JumperServer curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver…

数据结构——七种排序(java)实现

文章目录 直接插入排序希尔排序选择排序冒泡排序快速排序归并排序计数排序 直接插入排序 思想&#xff1a; /*** 直接插入排序* 具有稳定性* 时间复杂度为&#xff1a;&#xff08;计算时间复杂度的时候应计算执行次数最多的语句类&#xff0c;在直接插入排序中次数最多的语句…

【AI大模型】深入Transformer架构:编码器部分的实现与解析(下)

目录 &#x1f354; 编码器介绍 &#x1f354; 前馈全连接层 2.1 前馈全连接层 2.2 前馈全连接层的代码分析 2.3 前馈全连接层总结 &#x1f354; 规范化层 3.1 规范化层的作用 3.2 规范化层的代码实现 3.3 规范化层总结 &#x1f354; 子层连接结构 4.1 子层连接结…