PE文件(十二)导入表

导入表

导入表的引入

当一个PE文件(如.dll/.exe等)需要使用别的模块的函数,也叫做依赖某模块,就需要一个清单来记录使用的模块(一般为.dll文件,为方便理解,以后我们将模块都认为是.dll文件)及使用的函数的相关信息(如使用了哪些DLL、使用了这个DLL里的哪些函数、叫什么名、去哪找等),这个清单就叫做导入表。

定位导入表

一个PE文件的数据目录第二个结构体就是导入表数据目录,根据导入表数据目录的VirtualAddress成员经过RVA转FOA找到导出表

导入表结构

如下是导入表结构:

struct _IMAGE_IMPORT_DESCRIPTOR{                       

    union{                     

        DWORD Characteristics;                                

        DWORD OriginalFirstThunk;

    };                     

    DWORD TimeDateStamp;

    DWORD ForwarderChain;                                     

    DWORD Name;

    DWORD FirstThunk; 

};

一个导入表大小为20字节

DWORD OriginalFirstThunk:该值为指向导入名称表(即INT表)的RVA

DWORD FirstThunk:该值为导出地址表(即IAT表)的RVA

DWORD TimeDateStamp:时间戳,用于判断该.dll文件是否有绑定导入表或IAT表中是否已经绑定绝对地址。当该值为0x00000000时,表示表示这个导入表结构对应的DLL中的函数绝对地址没有绑定到IAT表中。当该值为0xFFFFFFFF时,表示这个导入表结构对应的DLL中函数绝对地址已经绑定到IAT表中

DWORD Name:指向使用到的.dll名字字符串的RVA,该字符串以0结尾。如果Name指向的.dll名称为“user32.dll”,那么这个导入表中记录的就是该PE文件使用user32.dll的相关信息

注意:

1.当一个导入表后跟了一个导入表大小即20个字节长度的0时,表示该PE文件的所有导入表结束。

2.一般来说,程序通过导入表中的信息来装载对应的.dll文件到虚拟内存中(比如通过导入表的所有Name成员,获取系统要装载的.DLL的名字)。但导入表中的某些信息则需要在.DLL装载内存完成后(比如IAT表)才能修复

3.如果导入表的某个结构中OriginalFirstThunk和FirstThunk的值都为0,这意味着该PE文没有使用这个DLL中的任何函数。此时操作系统就不会加载这个导入表结构对应的DLL

4.一个PE文件使用到的.dll文件的数量就是该PE文件的导入表数量。

INT表

定位INT表

INT表定位:通过OriginalFirstThunk找到INT表

INT表结构

结构如下图:

上图是一般情况下INT表的样子,元素有IMAGE_THUNK_DATA也有数值,但实际上这些元素都是属于IMAGE_THUNK_DATA32这一种结构体的不同形式表现。实际上的INT表如下:

图中表的成员为结构体,结构如下:

struct _IMAGE_THUNK_DATA32{                         

    union{                        

        BYTE ForwarderString;                          

        DWORD Function;                         

        DWORD Ordinal;     

        _IMAGE_IMPORT_BY_NAME* AddressOfData;

    };                         

};                  

这个结构体其实就是一个联合体,4字节大小。

元素表现形式不同的原因:一个.DLL中的函数可以以函数名称导出,也可以以序号(NONAME)导出,所以当一个PE文件使用别的.DLL中的函数时要考虑这个函数的名字和序号两种情况。因此INT表中的元素有IMAGE_THUNK_DATA和序号两种形式。

元素形式的判断方法如下:

如果INT表的元素最高位为1:那么除去最高位剩下31位的值,就是函数的导出序号

如果INT表的元素最高位为0:那么这个值为指向IMAGE_IMPORT_BY_NAME结构体的RVA

注意:

1.INT表中的元素个数就是该PE文件使用INT表对应的.dll文件函数的数量

2.当找到INT表后往后依次遍历出现有连续四字节长度的0时,表示该INT表结束

定位导入函数名称表

定位导入函数名称表:通过INT表中 _IMAGE_IMPORT_BY_NAME* AddressOfData元素,即可找到函数名称表的偏移地址

导入函数名称表结构

_IMAGE_IMPORT_BY_NAME结构体:

struct _IMAGE_IMPORT_BY_NAME{                       

    WORD Hint;

    BYTE Name[1];  //函数名称,以0结尾  

};                      

Hint:这个值由编译器决定是否为空,如果不为空,表示函数在导出表中的索引。一般不使用这个值

Name:由于函数名称的字符个数是不确定的,所以此处只给出一个1字节的字符数组用来存储函数名称的第一个字符。通过Name获取该字符串的首地址,再依次往后遍历,直到遇到字符串的结尾字符\0,便是完整的函数名称

IAT表

IAT表的引入

当我们在程序中使用其他模块中的函数时,我们以程序调用MessageBoxA()为例,进行演示。程序运行后我们进入反汇编开始观察。

我们会发现,系统在调用该函数时,call后跟的不是一个绝对地址,而是一个间接地址。

我们在内存中查找该地址

我们发现,这个地址内容是一张表,记录着我们使用的函数的实际地址。我们在这个程序只使用了MessageBoxA()函数,所以上表中只有第一行四个字节记录了数据,也就是MessageBoxA()函数的地址。而这张表就是IAT表,也叫做导入函数地址表

定位IAT表

方法一:通过导入表中的FirstThunk(RVA)成员,找到IAT表。

方法二:通过PE文件数据目录的第13个结构体中的VirtualAddress(RVA)成员,找到IAT表

导入表和IAT表

IAT表在程序运行前后是不一样的,因此导入表和IAT表的具体关系结构有以下两种:

PE文件运行前:

PE文件运行后:

PE文件运行前:IAT表中的内容和INT表的内容是一样的

PE文件运行后:IAT表中的内容就变成了该PE文件使用的对应的.dll中的函数在内存中的绝对地址

IAT表修改过程

1.装载PE文件到内存:当PE文件运行后,系统先装载.exe,再装载各个使用到的.dll到PE文件的虚拟内存中。

2.调用GetProcAddress()函数:内存装载完成后,系统首先遍历导出表中每个结构的INT表,无论遍历到的是函数名还是序号,都会作为其中一个参数传给系统函数GetProcAddress()

3. IAT表修改:GetProcAddress()函数根据函数名或序号返回对应函数在内存中的绝对地址,接着把绝对地址存入到IAT表的对应位置

4.修改call语句地址:

PE文件运行前:call [0x....]后面间接寻址的地址0x....是INT表中某个元素的地址;

PE文件运行后:call [0x....]后面间接寻址的地址0x....改成了IAT表中某个元素的地址;

INT表和IAT表的关系

原因一:PE文件加载后,INT表作为函数名字的备份。

原因二:当PE文件加壳或加密以后,函数地址发生改变。当程序运行后,IAT表中原本的记录的函数的地址就错了,就无法通过IAT表找函数了。此时通过INT表查找函数到函数地址就可以修复IAT表了。具体流程如下:PE文件运行前后INT表中的元素都指向函数名称或者序号。我们通过遍历该程序导入表的INT表,最终在某一个导出表结构中的INT表中找到要查找的函数名称(或序号)。此时通过将LoadLibrary()返回该函数所属的.dll的句柄(即所属DLL的ImageBase)和函数名称传入GetProcAddress()函数,就可以得到该函数地址。此时就可以修改IAT表了

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python写UI自动化--playwright(通过UI文本匹配实现定位)

本篇简单拓展一下元素定位技巧,通过UI界面的文本去实现定位 目录 匹配XPath 匹配文本元素 .count()统计匹配数量 处理匹配文本返回多个元素 1、使用.nth(index)选择特定元素: 2、获取所有匹配的元素并遍历: 3、错误处理: 匹配XPath 比如我们要定位到下图的…

VScode连接虚拟机运行Python文件的方法

声明:本文使用Linux发行版本为rocky_9.4 目录 1. 在rocky_9.4最小安装的系统中,默认是没有tar工具的,因此,要先下载tar工具 2. 在安装好的vscode中下载ssh远程插件工具 3. 然后连接虚拟机 4. 查看python是否已经安装 5. 下载…

Linux网络:传输层协议TCP(一)

目录 一、TCP协议的定义 二、确认应答机制ACK 三、序号、确认序号 四、超时重传机制 一、TCP协议的定义 TCP 全称为 "传输控制协议(Transmission Control Protocol"). 人如其名, 要对数据的传 输进行一个详细的控制; TCP 协议段格式 • 源/目的端口号: 表示数据…

减轻幻觉新SOTA,7B模型自迭代训练效果超越GPT-4,上海AI lab发布

LLMs在回答各种复杂问题时,有时会“胡言乱语”,产生所谓的幻觉。解决这一问题的初始步骤就是创建高质量幻觉数据集训练模型以帮助检测、缓解幻觉。 但现有的幻觉标注数据集,因为领域窄、数量少,加上制作成本高、标注人员水平不一…

vue3前端开发-小兔鲜项目-登录和非登录状态下的模板适配

vue3前端开发-小兔鲜项目-登录和非登录状态下的模板适配&#xff01;有了上次的内容铺垫&#xff0c;我们可以根据用户的token来判定&#xff0c;到底是显示什么内容了。 1&#xff1a;我们在对应的导航组件内修改完善一下内容即可。 <script setup> import { useUserSt…

抖音直播弹幕数据逆向:websocket和JS注入

&#x1f50d; 思路与步骤详解 &#x1f575;️‍♂️ 思路介绍 首先&#xff0c;我们通过抓包工具进入的直播间&#xff0c;捕获其网络通信数据&#xff0c;重点关注WebSocket连接。发现直播弹幕数据通过WebSocket传输&#xff0c;这种方式比传统的HTTP更适合实时数据的传输。…

细说MCU用定时器控制单路DAC模块设计和输出锯齿波的实现方法

目录 一、参考工程 二、仅提供不同的配置 1、用定时器控制DAC输出 2、配置定时器参数 三、代码修改 四、 运行并观察显示效果 一、参考工程 本工程依赖作者的文章&#xff1a;细说MCU用单路DAC模块设计和输出锯齿波的实现方法-CSDN博客 https://wenchm.blog.csdn.net/ar…

Mamba-yolo|结合Mamba注意力机制的视觉检测

一、本文介绍 PDF地址&#xff1a;https://arxiv.org/pdf/2405.16605v1 代码地址&#xff1a;GitHub - LeapLabTHU/MLLA: Official repository of MLLA Demystify Mamba in Vision: A Linear AttentionPerspective一文中引入Baseline Mamba&#xff0c;指明Mamba在处理各种高…

与Bug较量:Codigger之软件项目体检Software Project HealthCheck来帮忙

在软件工程师的世界里&#xff0c;与 Java 小程序中的 Bug 作战是一场永不停歇的战役。每一个隐藏在代码深处的 Bug 都像是一个狡猾的敌人&#xff0c;时刻准备着给我们的项目带来麻烦。 最近&#xff0c;我就陷入了这样一场与 Java 小程序 Bug 的激烈较量中。这个小程序原本应…

数据结构 | LinkedList与链表

前言 ArrayList底层使用连续的空间,任意位置(尤其是0位置下标)插入或删除元素时,需要将该位置后序元素 整体 往前或往后搬移,故时间复杂度为O(N). 优点(给定一个下标,可以快速查找到对应的元素,时间复杂度为O(1))增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗.增容一…

【Redis进阶】集群

1. 集群分片算法 1.1 集群概述 首先对于"集群"这个概念是存在不同理解的&#xff1a; 广义的"集群"&#xff1a;表示由多台主机构成的分布式系统&#xff0c;称为"集群"狭义的"集群"&#xff1a;指的是redis提供的一种集群模式&…

uniapp中@click或者@tap多层嵌套的问题解决方法

我们在开发页面的过程中。例如要设计一个九宫格的相册&#xff0c;并且加上删除上传图片和点击图片后预览图片大图的功能例如下图的演示功能。 点击图片后显示大图预览图片&#xff0c;点击x号后要删除掉当前的图片&#xff0c;那么我们设计的时候如果我们代码写成如下的格式 …

谷粒商城实战笔记-55-商品服务-API-三级分类-修改-拖拽数据收集

文章目录 一&#xff0c;拖拽后结点的parentCid的更新二&#xff0c;拖拽后结点的父节点下所有结点的sort排序属性的变化更新排序的逻辑代码分析 三&#xff0c;拖拽后结点及其子节点catLevel的变化判断是否需要更新 catLevel获取拖动后的新节点 更新 catLevel完整代码 这一节的…

基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网(2)登录,注册功能实现

技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 登陆页面如下 在这个页面中我们实现了一个登录页面和一个注册页面的Jsp文件&#xff0c;和两个java 的服务层文件 分别是web包下的denglu.jsp和zhuce.jsp以…

“微软蓝屏”事件,给IT行业带来的宝贵经验和教训

“微软蓝屏”事件是指2024年7月19日发生的一次全球性技术故障&#xff0c;主要涉及微软视窗&#xff08;Windows&#xff09;操作系统及其相关应用和服务。 以下是对该事件的详细解析&#xff1a; 一、事件概述 发生时间&#xff1a;2024年7月19日事件影响&#xff1a;全球多个…

2023河南萌新联赛第(二)场 南阳理工学院

A. 国际旅行Ⅰ 题目&#xff1a; 思路&#xff1a; 因为题意上每个国家可以相互到达&#xff0c;所以只需要排序&#xff0c;输出第k小的值就可以了。 AC代码&#xff1a; #include<bits/stdc.h> #define int long long #define IOS ios::sync_with_stdio(0);cin.tie…

基于k8s快速搭建docker镜像服务的demo

基于k8s快速搭建docker镜像服务的demo 一、环境准备 如标题&#xff0c;你需要环境中有和2个平台&#xff0c;并且服务器上也已经安装好docker服务 接下来我来构建一个docker镜像&#xff0c;然后使用harbork8s来快速部署服务demo 二、部署概述 使用docker构建镜像&#x…

HTML常见标签——超链接a标签

一、a标签简介 二、a标签属性 href属性 target属性 三、a标签的作用 利用a标签进行页面跳转 利用a标签返回页面顶部以及跳转页面指定区域 利用a标签实现文件下载 一、a标签简介 <a>标签用于做跳转、导航&#xff0c;是双标签&#xff0c;记作<a></a>&#…

zyx青岛实训day14 7/25

Git 一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更 一&#xff0e;Git的主要功能&#xff1a; 二&#xff0e;准备git机器 修改静态ip&#xff0c;主机名 三&#xff0e;git仓库的建立&#xff1a; 1.安装git [rootgit ~]# yum -y install git 2.创建一个…

ROS2入门到精通—— 2-8 ROS2实战:机器人安全通过狭窄区域的方案

0 前言 室内机器人需要具备适应性和灵活性&#xff0c;以便在狭窄的空间中进行安全、高效的导航。本文提供一些让机器人在狭窄区域安全通过的思路&#xff0c;希望帮助读者根据实际开发适当调整和扩展 1 Voronoi图 Voronoi图&#xff1a;根据给定的一组“种子点”&#xff0…