【第34节】windows原理:PE文件的导出表和导入表

目录

一、导出表

1.1 导出表概述

1.2 说明与使用

二、导入表

2.1 导入表概述

2.2 说明与使用


一、导出表

1.1 导出表概述

(1)导出行为和导出表用途:PE文件能把自身的函数、变量或者类,提供给其他PE文件使用,这种行为就叫导出。导出表专门用来存放这些导出项目的信息。当一个PE文件要调用其他PE文件里的导出函数(变量、类)时,依靠导出表就能迅速找到它们在文件里的位置。一般来说,这些被导出的函数、变量、类,也叫做符号(Symbol)。
(2)导出项序号的特点:每一个被导出的函数(变量、类),都有一个独一无二的序号。在有些情况下,可能找不到对应的函数名(变量、类名),但函数(变量、类)的地址和序号是存在的,听说可以通过序号来调用这类函数。
(3)导出表的内容组成:导出表里面记录的内容,包含了函数(变量、类)的地址、序号,还有函数(变量、类)名。
(4)导出表的查找方法:数据目录表的第一个元素里有相对虚拟地址,利用前面讲过的相对虚拟地址转文件偏移的办法,就能找到导出表的位置(后面会给出具体代码) 。

导出表的数据结构如下:

typedef struct _IMAGE_EXPORT_DIRECTORY  {DWORD   Characteristics;      //1( 没用)保留值,恒为0DWORD  TimeDateStamp;    //2( 没用)和文件头中的时间一样的。WORD   MajorVersion;  //3(没 用)主版本号WORD   MinorVersion;    //4 ( 没用 )次版本号DWORD  Name;             //5(有用)本PE文件的名字,也就是谁导出的这些函数(变量,类)DWORD  Base;             //6(有用)序号基数DWORD  NumberOfFunctions;//7 (重要) 函数数量DWORD  NumberOfNames;    //8   (重要)  函数名称数量DWORD  AddressOfFunctions;//9(重要)函数地址表的相对虚拟地址//RVA from base of imageDWORD AddressOfNames;    //10(重要)函数名称表的相对虚拟地址//RVA from base of imageDWORD AddressOfNameOrdinals;//11(重要)序号表的相对虚拟地址//RVA from base of image
}IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;

1.2 说明与使用

说明
(1)导出表存储位置:导出表一般在.edata段,不过.edata段通常会合并到.rdata段。
(2)序号基数:有个序号基数,从序号表得到的序号得加上它,才是真实函数序号,这方便在函数地址、序号和函数名之间互相查找。
(3)表项地址定位:导出表最后三个成员是相对虚拟地址,转换成文件偏移后,能找到函数地址表、函数名称表和序号表。
(4)函数名称表:函数名称表存的是函数名的相对虚拟地址,得再转换成文件偏移才能用,解析时要注意。
(5)导出表各表关系:
    - 序号顺序:序号不是按顺序排列的。
    - 对应关系:序号和函数名一一对应,两个表相同位置元素对应,所以结构体没设序号数量,因为它和函数名数量一样。
    - 序号中断:序号可能中断,比如缺1、5,但不代表没对应的函数地址。
    - 数量关系:函数个数比函数名个数多,多出来的可能是序号导出函数,也可能是地址填0的无效函数。
    - 表间关联:序号表元素值对应函数地址表位置,该位置的函数地址就是对应函数名的地址,靠这个把三个表联系起来。
    - 序号导出函数:函数地址表有地址值,但序号表没对应序号,说明是序号导出函数,序号就是它在函数地址表中的位置,没函数名。
    - 无效函数:函数地址表元素填0,就是无效函数,没序号和函数名对应。

看下面这张导出表图示,能更好理解导出表。

        函数表5、7位置是无效函数,2、3、4、6、8位置是函数名导出,注意函数名位置和地址表地址位置不同,1、9是序号导出函数,序号就是本身位置。

使用
(1)导出表信息提取:想提取导出表所有信息并过滤无效地址,得用循环,循环次数是函数地址个数。根据函数地址位置,在序号表找对应值,这个值的位置就是函数名位置。

        代码思路如下,假设目标文件已读入内存,首地址为pFile(void类型指针),且用到之前计算偏移的函数:

for(Ordinal=0;Ordinal<函数个数;dwOrdinal++){if(!导出函数数组[Ordinal])continue ;for(Index=0;Index<函数个数;dwIndex++){if(导出序号数组[Index]== Ordinal ){输出带函数名的导出函数信息}elseif(已经遍历完导出表){输出不带函数名的导出函数信息}}
}

在LoadPE中,点击导出表的“...”即可弹出导出表界面,序号代表结构体中成员的序号。

导出表偏移:这个偏移是用数据目录中的相对虚拟地址算出来的

特征:特征值恒0

函数地址:函数地址的相对虚拟地址

函数名地址:函数名称的相对虚拟地址

函数名顺序地址:序号表的相对虚拟地址

名称:名称的相对虚拟地址

字符串名称:根据名称的地址算出编移存储的名称

(2)根据函数名查找函数地址:导出表还有其他用途,比如给定一个函数名,查找其函数地址,这类似于GetProcAddress()函数。在编写壳程序等特殊场景中会用到此功能。该方法比上述代码更简单,直接根据函数名找到其位置,该位置序号的值即为所要查找函数的地址索引。若要查找已加载到内存后的dll中的函数地址,就不应再使用文件偏移,而应直接使用虚拟地址(VA)。

二、导入表

2.1 导入表概述

(1)导入行为和导入表用途:PE文件运行过程中,如果用到其他PE文件里的函数、变量或者类,这种行为就叫做导入。导入表专门记录这部分信息。
(2)导入表的查找方法:数据目录表的第二个元素能帮我们定位导入表,查找的办法和找导出表一样。
(3)导入表的存储内容:导入表会记录从其他PE文件导入的函数名和序号。当PE文件加载到内存后,导入表还会保存这些函数的实际内存地址。
(4)导入表的结构特点:一个PE文件往往需要多个其他PE文件提供支持,所以导入表通常有多个。从结构上来说,导入表是一个结构体数组,数组以一个全零元素作为结束标志,数组里每个元素,都对应着一个PE文件的导入信息 。

2.2 说明与使用

导入表相关数据结构如下:

typedef struct _IMAGE_IMPORT_DESCRIPTOR
union {DWORD   Characteristics;   DWORD  OriginalFirstThunk;//1(重要)指向一个结构体数组的相对虚拟地址(RVA), 结构体数组叫输入名称表
}  DUMMYUNIONNAME;     
DWORD TimeDateStamp;          //2(有用)没用
DWORD ForwarderChain;    //3(有用)转发机制用到,这里不探讨
DWORD Name;         //4(有用)导入的PE文件的名字的相对虚拟地址RVA
DWORD FirstThunk;    //5(重要)指向一个结构体数组的相对虚拟地址(RVA),结构体数组叫做输入地址表(IAT:Import Address Table)
}IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;

说明
(1)指针指向特性:OriginalFirstThunk和FirstThunk这两个指针,都指向IMAGE_THUNK_DATA类型的结构体。
(2)磁盘与内存数据变化:在磁盘上的文件里,OriginalFirstThunk和FirstThunk所指向的数据是一样的。基于此,我们可以把输入名称表(INT)当作输入地址表(IAT)的备份。等到文件加载到内存后,加载器会把对应PE文件里函数的真实地址,填充到输入地址表中。这时,输入地址表才成了真正可用的输入地址表。
(3)输入名称表情况:有些文件的输入名称表内容全为零,处于空白状态。这意味着输入地址表有时没有备份。所以在解析输入表时,优先使用输入地址表;当然,也可以同时解析输入名称表和输入地址表,对比查看。
(4)解析终止条件:这两个指针指向的结构体数组,是以全零元素作为结尾的。我们可以利用这一特性,作为解析过程的结束标志。
(5)相关结构体介绍:

typedef struct _IMAGE_THUNK_DATA32 {union {DWORD ForwarderString;   //转发用到DWORD Function;          //导入函数的地址,在加载到内存后,这里才起作用DWORD Ordinal;            //假如是序号导入的,用到这里DWORD AddressOfData;     //假如是函数名导入的,用到这里,它指向一个PIMAGE_IMPORT_BY_NAME结构体}ul;
}IMAGE_THUNK_DATA32;

        在磁盘文件中,起作用的只有后两个成员。该结构占4个字节,若最高位为1,则序号导入起作用,只需输出一个序号;若最高位为0,则最后一个成员起作用,指向一个PIMAGE_IMPORT_BY_NAME。可使用系统提供的宏IMAGE_SNAP_BY_ORDINAL32()判断最高位是否为1,参数为该结构体。

typedef struct _IMAGE_IMPORT_BY_NAME {WORD   Hint;CHAR Name[1];
}IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;

该结构包含序号和函数名。

使用:

//循环打印INT的内容
while(pINT->u1.Ordinal)
{//判断最高位是否不为1,是的话则打印其AddressOfData的内容if(!IMAGE_SNAP_BY_ORDINAL32(pINT->u1.Ordinal)){PIMAGE_IMPORT_BY_NAME pBN =获取ByName;printf("%04X %s\r\n",pBN->Hint,pBN->Name);}pINT++;continue;
}
//如果最高位为1,则直接打印Ordinal部分
printf("%04X %s\r\n",pINT->u1.Ordinal&0xFFFF,"(Null)");
pINT++;

原始 FirstThunk:导入名称表的RVA

FirstThunk:导入地址表的RVA

正向链:转发用

ThunkEVA:每-个Thunk统构的RVA(算的)

Thunk 偏移:Thunk结构的编移(算的)

Hint:函数的序号

API名称:函数的名称

        计算每个Thunk结构的相对虚拟地址(RVA)时,只要知道第一个结构的RVA,后续结构的RVA依次加4就能得出。偏移计算方法也是一样,算出第一个偏移后,后续偏移每次加4。

        LoadPE软件会对输入名称表(INT)和输入地址表(IAT)这两个数据域进行解析。软件默认展示INT的解析结果,如果点击软件下方“总是查看FirstThunk”复选框,软件就会显示IAT的解析结果。

        到这里,关于导出表和导入表的解析说明就结束了。

 

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

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

相关文章

【计算机网络】深入解析TCP/IP参考模型:从四层架构到数据封装,全面对比OSI

TCP/IP参考模型 导读一、历史背景二、分层结构2.1 网络接口层&#xff08;Network Interface Layer&#xff09;2.2 网络层&#xff08;Internet Layer&#xff09;2.3 传输层&#xff08;Transport Layer&#xff09;2.4 应用层&#xff08;Application Layer&#xff09; 三、…

项目实战-角色列表

抄上一次写过的代码&#xff1a; import React, { useState, useEffect } from "react"; import axios from axios; import { Button, Table, Modal } from antd; import { BarsOutlined, DeleteOutlined, ExclamationCircleOutlined } from ant-design/icons;const…

LeetCode1两数之和

**思路&#xff1a;**懒得写了&#xff0c;如代码所示 /*** Note: The returned array must be malloced, assume caller calls free().*/ struct hashTable {int key;//存值int val;//存索引UT_hash_handle hh; }; int* twoSum(int* nums, int numsSize, int target, int* re…

去噪算法大比拼

目录 效果图: 实现代码: 密集抖动 pip install pykalman 效果图: 实现代码: import numpy as np import cv2 import matplotlib.pyplot as plt from scipy.ndimage import gaussian_filter1d from scipy.signal import butter, filtfilt, savgol_filter from pykalma…

STM32_HAL开发环境搭建【Keil(MDK-ARM)、STM32F1xx_DFP、 ST-Link、STM32CubeMX】

安装Keil(MDK-ARM)【集成开发环境IDE】 我们会在Keil(MDK-ARM)上去编写代码、编译代码、烧写代码、调试代码。 Keil(MDK-ARM)的安装方法&#xff1a; 教学视频的第02分03秒开始看。 安装过程中请修改一下下面两个路径&#xff0c;避免占用C盘空间。 Core就是Keil(MDK-ARM)的…

深入理解MySQL聚集索引与非聚集索引

在数据库管理系统中&#xff0c;索引是提升查询性能的关键。MySQL支持多种类型的索引&#xff0c;其中最基础也是最重要的两种是聚集索引和非聚集索引。本文将深入探讨这两种索引的区别&#xff0c;并通过实例、UML图以及Java代码示例来帮助您更好地理解和应用它们。 一、概念…

【leetcode】拆解与整合:分治并归的算法逻辑

前言 &#x1f31f;&#x1f31f;本期讲解关于力扣的几篇题解的详细介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…

wx162基于springboot+vue+uniapp的在线办公小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

陈宛汮签约2025火凤凰风赏大典全球形象大使

原标题&#xff1a;陈宛汮签约2025火凤凰风赏大典全球形象大使 共工新闻社香港3月29日电 陈宛汮&#xff0c;华语原创女歌手。“星宝在闪耀”公益活动联合发起人&#xff0c;自闭症儿童康复推广大使。代表作:《荣耀火凤凰》《爱在醉千年》。 从2025年1月1日至2025年12月31日&a…

【深度学习入门_机器学习理论】极致梯度提升原理(XGBoost)

XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是一种高效、灵活且广泛应用的机器学习算法&#xff0c;属于梯度提升决策树&#xff08;Gradient Boosting Decision Tree, GBDT&#xff09; 的优化实现。它在分类、回归、排序等结构化/表格数据的预测任务中表现尤为…

Oracle初识:登录方法、导入dmp文件

目录 一、登录方法 以sys系统管理员的身份登录 &#xff0c;无需账户和密码 以账户密码的用户身份登录 二、导入dmp文件 方法一&#xff1a;PLSQL导入dmp文件 一、登录方法 Oracle的登录方法有两种。 以sys系统管理员的身份登录 &#xff0c;无需账户和密码 sqlplus / a…

STM32F103_LL库+寄存器学习笔记01 - 梳理CubeMX生成的LL库最小的裸机系统框架

《STM32 - 在机器人领域&#xff0c;LL库相比HAL优势明显》在机器人、自动化设备领域使用MCU开发项目&#xff0c;必须用LL库。 本系列笔记记录使用LL库的开发过程&#xff0c;首先通过CubeMX生成LL库代码&#xff0c;梳理LL库源码。通过学习LL库源码&#xff0c;弄清楚寄存器的…

Vue3当中el-tree树形控件使用

tree悬停tooltip效果 文本过长超出展示省略号 如果文本超出悬停显示tooltip效果 反之不显示 这里直接控制固定宽度限制 试了监听宽度没效果<template><el-treeshow-checkbox:check-strictly"true":data"data"node-key"id":props"…

最大数字(java)(DFS实现)

1.最大数字 - 蓝桥云课 因为N最大是10 的17次方&#xff0c; 所以可以利用字符串来处理输入的数字的每一位 并且是从高到低依次处理的 然后通过函数charAt(i)来获取第i位的字符 再减去‘0’就可以将字符转化为整型了 假设每一位数字都是x 然后通过两种操作 加或者减来操…

04 单目标定实战示例

看文本文,您将获得以下技能: 1:使用opencv进行相机单目标定实战 2:标定结果参数含义和数值分析 3:Python绘制各标定板姿态,查看图像采集多样性 4:如果相机画幅旋转90,标定输入参数该如何设置? 5:图像尺寸缩放,标定结果输出有何影响? 6:单目标定结果应用类别…

手机销售终端MPR+LTC项目项目总体方案P183(183页PPT)(文末有下载方式)

资料解读&#xff1a;手机销售终端 MPRLTC 项目项目总体方案 详细资料请看本解读文章的最后内容。在当今竞争激烈的市场环境下&#xff0c;企业的销售模式和流程对于其发展起着至关重要的作用。华为终端正处于销售模式转型的关键时期&#xff0c;波士顿 - 华为销售终端 MPRLTC …

如何在 vue 渲染百万行数据,vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染

vxe-table 渲染百万行数据性能对比&#xff0c;超大量百万级表格渲染&#xff1b;如何在 vue 渲染百万行数据&#xff1b;当在开发项目时&#xff0c;遇到需要流畅支持百万级数据的表格时&#xff0c; vxe-table 就可以非常合适了&#xff0c;不仅支持强大的功能&#xff0c;虚…

ubuntu24 部署vnc server 使用VNC Viewer连接

前提条件 已创建一台Ubuntu 24.04(20.22通用)操作系统的云服务器&#xff0c;并且为云服务器绑定弹性公网IP&#xff0c;确保可以连接互联网。 已在本地PC安装VNC Viewer客户端。 操作步骤 服务器内安装vnc server以及桌面环境 apt update sudo apt install xfce4 xfce4-…

【数据结构】栈 与【LeetCode】20.有效的括号详解

目录 一、栈1、栈的概念及结构2、栈的实现3、初始化栈和销毁栈4、打印栈的数据5、入栈操作---栈顶6、出栈---栈顶6.1栈是否为空6.2出栈---栈顶 7、取栈顶元素8、获取栈中有效的元素个数 二、栈的相关练习1、练习2、AC代码 个人主页&#xff0c;点这里~ 数据结构专栏&#xff0c…

06-SpringBoot3入门-常见注解(简介)

1、Controller ResponseBody Controller是Spring MVC 中的注解&#xff0c;负责处理 HTTP 请求。 ResponseBody是Spring MVC 中的注解&#xff0c;用于直接将方法的返回值作为 HTTP 响应体。 2、RestController RestController Controller ResponseBody 3、RequestMappin…