pe格式从入门到图形化显示(七)-导出表
文章目录
- 前言
- 一、什么是Windows PE格式中的导出表?
- 二、解析导出表并显示
- 1.导出表的结构
- 2.解析导出表
- 3.显示导出表
前言
通过分析和解析Windows PE格式,并使用qt进行图形化显示
一、什么是Windows PE格式中的导出表?
PE文件格式的导出表是PE文件中用于记录程序导出函数信息的数据结构。导出表位于数据目录表的第一项,索引值为0。导出表记录了当前文件对外开放的函数接口,使得其他程序可以通过这些接口调用该文件中的函数。
二、解析导出表并显示
1.导出表的结构
IMAGE_EXPORT_DIRECTORY结构体包含了导出表的特征、时间戳、版本号、导出函数数量、导出函数名称数量、导出函数地址表、导出函数名称表和导出函数序号表等信息。IMAGE_EXPORT_DIRECTORY的定义如下:
typedef struct _IMAGE_EXPORT_DIRECTORY {DWORD Characteristics;DWORD TimeDateStamp;WORD MajorVersion;WORD MinorVersion;DWORD Name;DWORD Base;DWORD NumberOfFunctions;DWORD NumberOfNames;DWORD AddressOfFunctions; // RVA from base of imageDWORD AddressOfNames; // RVA from base of imageDWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
IMAGE_EXPORT_DIRECTORY中的字段包括:
Characteristics:导出表的特征值,用于描述导出表的特性。
TimeDateStamp:时间戳,表示导出表创建或最后修改的时间。
MajorVersion和MinorVersion:导出表的主次版本号,用于标识导出表的版本信息。
Name:导出表的名称,通常为一个字符串,用于描述导出表的功能或用途。
Base:导出表中函数的起始序号,用于定位导出函数在文件中的位置。
NumberOfFunctions:导出表中导出的函数数量。
NumberOfNames:以名称导出的函数数量。
AddressOfFunctions:导出函数地址表在文件中的虚拟地址。
AddressOfNames:导出函数名称表在文件中的虚拟地址。
AddressOfNameOrdinals:导出函数序号表在文件中的虚拟地址。
2.解析导出表
bool PEParser::parserFileData(const QByteArray &fileData)
{//判断是否是MZ开头的文件if (fileData.left(2) != "MZ"){return false;}//解析DOS头parserDOSHeader(fileData.left(sizeof(IMAGE_DOS_HEADER)));//DOSStub数据m_dosStubData = fileData.mid(sizeof(IMAGE_DOS_HEADER), m_dosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER));long peAddress = m_dosHeader.e_lfanew;if (fileData.mid(peAddress, 2) != "PE"){return false;}m_fileData = fileData;//去除前4个字节的PE头标识long fileHeaderIndex = peAddress + 4;//记录文件头索引m_fileHeaderIndex = fileHeaderIndex;//解析标准PE文件头paserFileHeader(fileData.mid(fileHeaderIndex, sizeof(IMAGE_FILE_HEADER)));//解析扩展PE文件头long optionHeaderIndex = fileHeaderIndex + sizeof(IMAGE_FILE_HEADER);//记录扩展PE文件头索引m_optionHeaderIndex = optionHeaderIndex;//解析扩展PE文件头parserOptionHeader(fileData.mid(optionHeaderIndex, m_fileHeader.SizeOfOptionalHeader));//解析节表long sectionHeaderIndex = optionHeaderIndex + m_fileHeader.SizeOfOptionalHeader;//节表结构在文件中开始的偏移m_sectionHeaderIndex = sectionHeaderIndex;//解析节表parserSectionHeader(fileData.mid(sectionHeaderIndex,m_fileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)));//解析数据目录parserDataDirectory();//解析导出表parserExportTable();return true;
}void PEParser::parserExportTable()
{DWORD address = 0;if (m_x86Flag){address = m_optionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;}else{address = m_optionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;}if (address == 0){return;}//将虚拟地址转换为文件地址RVA2FOAInfo info = RVA2FOA(address);//获取导出表数据IMAGE_EXPORT_DIRECTORY exportTable;memcpy(&exportTable, m_fileData.data() + info.FOA, sizeof(IMAGE_EXPORT_DIRECTORY));QList<DWORD> functionAddressList;QList<WORD> functionOrdinalsList;//获取导出函数序号表数据info = RVA2FOA(exportTable.AddressOfNameOrdinals);QByteArray ordinalsTempData = m_fileData.mid(info.FOA, exportTable.NumberOfFunctions * sizeof(WORD));//获取导出函数地址表数据info = RVA2FOA(exportTable.AddressOfFunctions);QByteArray addrTempData = m_fileData.mid(info.FOA, exportTable.NumberOfFunctions * sizeof(DWORD));//遍历导出表中导出函数的数据for (int i = 0; i < exportTable.NumberOfFunctions; ++i){DWORD addr = 0;memcpy(&addr, addrTempData.data() + i * sizeof(DWORD), sizeof(DWORD));functionAddressList.append(addr);WORD ordinal = 0;memcpy(&ordinal, ordinalsTempData.data() + i * sizeof(WORD), sizeof(WORD));functionOrdinalsList.append(ordinal);}//获取导出函数名称表数据info = RVA2FOA(exportTable.AddressOfNames);QByteArray nameTempData = m_fileData.mid(info.FOA, exportTable.NumberOfFunctions * sizeof(DWORD));//遍历导出表中以名称导出的数据QList<ExportFunctionInfo> exportFunctionInfo;for (int i = 0; i < exportTable.NumberOfNames; ++i){DWORD nameRVA = 0;memcpy(&nameRVA, nameTempData.data() + i * sizeof(DWORD), sizeof(DWORD));DWORD nameFOA = RVA2FOA(nameRVA).FOA;int index = m_fileData.indexOf('\0', nameFOA);ExportFunctionInfo info;info.name = m_fileData.mid(nameFOA, index - nameFOA);info.address = functionAddressList[functionOrdinalsList[i]];info.ordinal = functionOrdinalsList[i];exportFunctionInfo.append(info);}//按序号排序std::sort(exportFunctionInfo.begin(), exportFunctionInfo.end(), [=](const ExportFunctionInfo &info1, const ExportFunctionInfo &info2) -> bool{return info1.ordinal < info2.ordinal;});emit sendExportTable(exportFunctionInfo);
}
3.显示导出表
void MainWindow::showExportTable(const QList<ExportFunctionInfo> &exportTable)
{ui->tableWidget_exportTable->clearContents();ui->tableWidget_exportTable->setRowCount(0);for (int i = 0; i < exportTable.size(); ++i){ui->tableWidget_exportTable->insertRow(i);ui->tableWidget_exportTable->setItem(i, 0, new QTableWidgetItem(exportTable[i].name));ui->tableWidget_exportTable->setItem(i, 1, new QTableWidgetItem(QString::asprintf("%08lX", exportTable[i].address)));ui->tableWidget_exportTable->setItem(i, 2, new QTableWidgetItem(QString::asprintf("%08lX", exportTable[i].ordinal)));}
}
相关文章:
pe格式从入门到图形化显示(七)-导出表
文章目录 前言一、什么是Windows PE格式中的导出表?二、解析导出表并显示1.导出表的结构2.解析导出表3.显示导出表 前言 通过分析和解析Windows PE格式,并使用qt进行图形化显示 一、什么是Windows PE格式中的导出表? PE文件格式的导出表是P…...
图片地址生成二维码(通过前端实现)
文章目录 概要安装插件代码实例 概要 要将图片地址生成二维码,你可以使用 QrCode 库(假设你已经在项目中引入了该库)。以下是一个简单的示例代码,演示了如何使用 QrCode 库将图片地址转换为二维码并显示在页面上 安装插件 先下载…...
window安装maven和hadoop3.1.4
前面的文章已讲解如何安装idea和进行基本设置,本文主要带着大家安装配置好maven和hadoop. 大家不用去官网下载,直接使用我发给大家的压缩文件,注意解压后的文件夹不要放在中文目录下,课堂上我们讲解过原因。 这是我电脑上的路径&a…...
Redis系列之主从复制集群搭建
在上一篇博客,我们已经知道怎么搭建一个redis单机版,这篇博客基于之前的基础,来搭建一个redis主从同步,本博客框架是一主二从,一个主节点,其它两个从节点 实验环境 CentOS7Xshell6XFtp6Redis6.2.2 主从关…...
spring框架介绍
spring 1.优点 1)针对接口编程,解耦合 2)aop:变向切面编程,动态增加功能 3)方便集成框架,mybatis,hibernate,strust等 4)降低j2ee接口的使用难度 2.spring是干什么的 管理bean及bean…...
如果在 Ubuntu 系统中两个设备出现两个相同的端口号解决方案
问题描述: 自己的移动机器人在为激光雷达和IMU配置动态指定的端口时,发现激光雷达和深度相机配置的 idVendor 和 idProduct 相同,但是两个设备都具有不同的ttyUSB号,如下图所示 idVendor:代表着设备的生产商ID,由USB设…...
随手分享的APP链接,可能会让你“大型社死”
早晨上班路上,你在地铁百无聊赖地刷着短视频,看到一则好笑的,随手分享给了你的公司“饭搭子”,并配上了一串“哈哈哈哈哈哈”。 晚上下班路上你再次打开视频APP,发现首页弹窗给你推荐了一组“可能认识的人”ÿ…...
国内AI大模型已近80个,哪个最有前途?
根据中国新一代人工智能发展战略研究院发布的报告显示,目前全国已有3k+家人工智能企业,国内的AI大模型应该也近在200了!!! (原图图片过长了,这里就先放了20个) 面对如…...
美团一面:说说synchronized的实现原理?问麻了。。。。
引言 在现代软件开发领域,多线程并发编程已经成为提高系统性能、提升用户体验的重要手段。然而,多线程环境下的数据同步与资源共享问题也随之而来,处理不当可能导致数据不一致、死锁等各种并发问题。为此,Java语言提供了一种内置…...
P1123 取数游戏(dfs算法)
题目描述 一个 NM 的由非负整数构成的数字矩阵,你需要在其中取出若干个数字,使得取出的任意两个数字不相邻(若一个数字在另外一个数字相邻 8个格子中的一个即认为这两个数字相邻),求取出数字和最大是多少。 输入格式 第…...
交叉验证(Cross-Validation)
交叉验证的基本概念 交叉验证通常用于评估机器学习模型在未知数据上的性能。它将数据集分成k个不同的子集,然后进行k次训练和验证。在每次迭代中,选择一个子集作为测试集,其余的子集作为训练集。这样,每个子集都用作过测试集&…...
【kears】(01)keras使用介绍
文章目录 一.特点二.keras如何支持TensorFlow、CNTK 和 Theano2.1 使用 TensorFlow 后端引擎训练和评估模型2.2 使用 TensorFlow 后端引擎训练和评估模型2.3 使用 Theano后端引擎训练和评估模型2.4 不同深度学习框架如何选择1.1 keras.datasets:包含多种常用数据集1…...
2. TypeScript 安装与环境配置指南
TypeScript 是 JavaScript 的一个超集,它为 JavaScript 增加了类型系统和对 ES6 的支持。TypeScript 不仅能够帮助开发者捕获代码中的错误,还能提供更好的编辑器支持,包括代码补全、接口提示等。本文将详细介绍如何在您的开发环境中安装和配置…...
python pygame库的略学
文章目录 概述1. pygame的初始化和退出2. 创建游戏窗口(1)set_mode()(2)set_capyion()(3)update() 3. 游戏循坏与游戏时钟4. 图形和文本绘制(1)图形绘制(2)文…...
大模型日报2024-04-09
大模型日报 2024-04-09 大模型资讯 苹果预告超越ChatGPT的新AI模型ReaLM 摘要: 苹果公司最新宣布,即将推出一款名为ReaLM的人工智能模型。这款AI技术在理解复杂屏幕用户指令方面表现出高超的能力,并能与用户进行自然流畅的对话。ReaLM的推出预示着苹果在…...
抖音视频如何下载保存(方法分享)
有时刷抖音视频,看的喜欢的视频想要下载到本地,但是有很多视频无法下载或者下载下来是有水印的,那怎么办呢? 抖音视频下载有两种情况: 一种是可以直接点击分享下载,然后可以直接点击保存到相册。 视频就自动下载…...
MySQL-用户与权限管理:用户管理、权限管理、角色管理
用户与权限管理 用户与权限管理1.用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其它用户密码 2. 权限管理2.1 权限列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限 访问控制连接核实阶段请求核实阶段 3. 角色管理…...
Vue.js中如何使用Vue Router处理浏览器返回键的功能
在Vue.js中,Vue Router默认提供了处理浏览器返回键的功能。当用户点击浏览器的返回键时,Vue Router会自动导航到历史记录中的上一个路由。然而,如果你想自定义返回键的行为或者在特定的页面上进行特殊处理,你可以使用Vue Router的…...
QT drawPixmap和drawImage处理图片模糊问题
drawPixmap和drawImage显示图片时,如果图片存在缩放时,会出现模糊现象,例如将一个100x100 的图片显示到30x30的区域,这个时候就会出现模糊。如下: 实际图片: 这个问题就是大图显示成小图造成的像素失真。 当…...
YOLOv9改进策略 :小目标 | 新颖的多尺度前馈网络(MSFN) | 2024年4月最新成果
💡💡💡本文独家改进:多尺度前馈网络(MSFN),通过提取不同尺度的特征来增强特征提取能力,2024年最新的改进思路 💡💡💡创新点:多尺度前馈网络创新十足,抢先使用 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
