pe格式从入门到图形化显示(八)-导入表
文章目录
- 前言
- 一、什么是Windows PE格式中的导入表?
- 二、解析导入表并显示
- 1.导入表的结构
- 2.解析导入表
- 3.显示导入表
前言
通过分析和解析Windows PE格式,并使用qt进行图形化显示
一、什么是Windows PE格式中的导入表?
在Windows中,PE文件格式中的导入表(Import Table)是一个关键的数据结构,它记录了程序在运行时所需调用的外部动态链接库(DLL)中的函数和变量。导入表的主要作用是在程序加载时,帮助操作系统定位并加载这些外部库,以便程序能够正确地调用其中的函数和访问变量。
导入表由一系列_IMAGE_IMPORT_DESCRIPTOR结构组成,每个结构都包含一个指向外部库的导入地址表(Import Address Table,IAT)的指针。IAT是一个包含函数名和对应函数地址的列表,它提供了程序在运行时查找和调用外部库函数所需的信息。
当程序被加载到内存中时,操作系统会使用导入表中的信息来解析IAT,从而将外部库的函数地址填充到正确的位置。这样,当程序调用一个外部库函数时,它可以通过IAT直接找到正确的函数地址,并执行相应的操作。
总之,PE文件格式中的导入表是连接程序与外部动态链接库的关键桥梁,它确保了程序在运行时能够正确地调用外部库中的函数和访问变量。
二、解析导入表并显示
1.导入表的结构
导入表的结构如下:
IMAGE_IMPORT_DESCRIPTOR结构数组:这是一个可变长度的数组,每个元素描述一个导入的模块。数组的最后一个元素的所有字段都为零,表示数组的结束。
struct IMAGE_IMPORT_DESCRIPTOR {union {DWORD Characteristics;DWORD OriginalFirstThunk;};DWORD TimeDateStamp;DWORD ForwarderChain;DWORD Name;DWORD FirstThunk;
};
每个IMAGE_IMPORT_DESCRIPTOR结构包含以下字段:
OriginalFirstThunk:指向一个IMAGE_THUNK_DATA结构数组,该数组包含了导入函数的原始名称或序号。
TimeDateStamp:时间戳,表示导入表的创建时间。如果此值为零,表示导入表未被绑定。
ForwarderChain:链表的前一个结构的索引,用于处理转发器导入。
Name:以null结尾的字符串,表示导入的模块名称。
FirstThunk:指向一个IMAGE_THUNK_DATA结构数组,该数组包含了导入函数的序号或地址。
IMAGE_THUNK_DATA结构:这个结构表示一个导入函数的信息。它的大小取决于操作系统(32位或64位)。 对于32位系统,IMAGE_THUNK_DATA结构定义如下:
typedef struct _IMAGE_THUNK_DATA32 {union {DWORD ForwarderString;DWORD Function;DWORD Ordinal;DWORD AddressOfData;} u1;
} IMAGE_THUNK_DATA32, *PIMAGE_THUNK_DATA32;
对于64位系统,IMAGE_THUNK_DATA结构定义如下:
typedef struct _IMAGE_THUNK_DATA64 {union {ULONGLONG ForwarderString;ULONGLONG Function;ULONGLONG Ordinal;ULONGLONG AddressOfData;} u1;
} IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64;
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();//解析导入表parserImportTable();return true;
}void PEParser::parserImportTable()
{DWORD address = 0;int iatSize = 0;if (m_x86Flag){address = m_optionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;iatSize = sizeof(IMAGE_THUNK_DATA32);}else{address = m_optionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;iatSize = sizeof(IMAGE_THUNK_DATA64);}QList<ImportTableInfo> importTable;RVA2FOAInfo info = RVA2FOA(address);int i = 0;char endFlag[20] = {0};while (1){ImportTableInfo tableInfo{};//获取导入表数据IMAGE_IMPORT_DESCRIPTOR table;memcpy(&table, m_fileData.data() + info.FOA + i * sizeof(IMAGE_IMPORT_DESCRIPTOR), sizeof(IMAGE_IMPORT_DESCRIPTOR));//20个0 导入表结束if (memcmp(&table, endFlag, sizeof(endFlag)) == 0){break;}RVA2FOAInfo nameInfo = RVA2FOA(table.Name);int index = m_fileData.indexOf('\0', nameInfo.FOA);//获取dll名称tableInfo.dllName = m_fileData.mid(nameInfo.FOA, index - nameInfo.FOA);tableInfo.originalFirstThunk = table.OriginalFirstThunk;tableInfo.forwarderChain = table.ForwarderChain;tableInfo.name = table.Name;tableInfo.timeDateStamp = table.TimeDateStamp;tableInfo.firstThunk = table.FirstThunk;RVA2FOAInfo originalFirstThunkInfo = RVA2FOA(table.OriginalFirstThunk);RVA2FOAInfo firstThunkInfo = RVA2FOA(table.FirstThunk);int j = 0;while (1){ThunkInfo thunkInfo{};memcpy(&thunkInfo.thunkValue, m_fileData.data() + firstThunkInfo.FOA + j * iatSize, iatSize);//IAT表结束if (thunkInfo.thunkValue == 0){break;}memcpy(&thunkInfo.thunkRVA, m_fileData.data() + originalFirstThunkInfo.FOA + j * iatSize, iatSize);//最高位为1 表示函数导出序号if (thunkInfo.thunkRVA & 0X80000000){thunkInfo.functionName = "@" + QString::number(thunkInfo.thunkRVA - 0X80000000).toUtf8();}else{//获取函数名称RVA2FOAInfo functionNameInfo = RVA2FOA(thunkInfo.thunkRVA);thunkInfo.thunkFOA = functionNameInfo.FOA;memcpy(&thunkInfo.hint, m_fileData.data() + functionNameInfo.FOA, sizeof(WORD));int functionNameFOA = functionNameInfo.FOA + sizeof(WORD);index = m_fileData.indexOf('\0', functionNameFOA);thunkInfo.functionName = m_fileData.mid(functionNameFOA, index - functionNameFOA);}tableInfo.thunkList.append(thunkInfo);j++;}importTable.append(tableInfo);i++;}emit sendImportTable(importTable);
}
3.显示导入表
void MainWindow::showImportTable(const QList<ImportTableInfo> &importTable)
{ui->tableWidget_importTable->clearContents();ui->tableWidget_importTable->setRowCount(0);for (int i = 0; i < importTable.size(); ++i){ui->tableWidget_importTable->insertRow(i);ui->tableWidget_importTable->setItem(i, 0, new QTableWidgetItem(importTable[i].dllName));QTableWidgetItem *item = ui->tableWidget_importTable->item(i, 0);item->setData(100, QVariant::fromValue(importTable[i]));ui->tableWidget_importTable->setItem(i, 1, new QTableWidgetItem(QString::asprintf("%d", importTable[i].thunkList.size())));ui->tableWidget_importTable->setItem(i, 2, new QTableWidgetItem(QString::asprintf("%08lX", importTable[i].originalFirstThunk)));ui->tableWidget_importTable->setItem(i, 3, new QTableWidgetItem(QString::asprintf("%08lX", importTable[i].timeDateStamp)));ui->tableWidget_importTable->setItem(i, 4, new QTableWidgetItem(QString::asprintf("%08lX", importTable[i].forwarderChain)));ui->tableWidget_importTable->setItem(i, 5, new QTableWidgetItem(QString::asprintf("%08lX", importTable[i].firstThunk)));}
}void MainWindow::on_tableWidget_importTable_clicked(const QModelIndex &index)
{if (ui->tableWidget_importTable->rowCount() > index.row()){QTableWidgetItem *item = ui->tableWidget_importTable->item(index.row(), 0);ImportTableInfo info = item->data(100).value<ImportTableInfo>();ui->tableWidget_iatTable->clearContents();ui->tableWidget_iatTable->setRowCount(0);for (int i = 0; i < info.thunkList.size(); ++i){ui->tableWidget_iatTable->insertRow(i);ui->tableWidget_iatTable->setItem(i, 0, new QTableWidgetItem(QString::asprintf("%016llX", info.thunkList[i].thunkValue)));ui->tableWidget_iatTable->setItem(i, 1, new QTableWidgetItem(QString::asprintf("%016llX", info.thunkList[i].thunkRVA)));ui->tableWidget_iatTable->setItem(i, 2, new QTableWidgetItem(QString::asprintf("%016llX", info.thunkList[i].hint)));ui->tableWidget_iatTable->setItem(i, 3, new QTableWidgetItem(info.thunkList[i].functionName));}}
}
相关文章:
pe格式从入门到图形化显示(八)-导入表
文章目录 前言一、什么是Windows PE格式中的导入表?二、解析导入表并显示1.导入表的结构2.解析导入表3.显示导入表 前言 通过分析和解析Windows PE格式,并使用qt进行图形化显示 一、什么是Windows PE格式中的导入表? 在Windows中࿰…...
如何将Paddle(Lite)模型转换为TensorFlow(Lite)模型
模型间的相互转换在深度学习应用中很常见,paddlelite和TensorFlowLite是移动端常用的推理框架,有时候需要将模型在两者之间做转换,本文将对转换方法做说明。 环境准备 建议使用TensorFlow2.14,PaddlePaddle 2.6 docker pull te…...
最新Zibll子比主题V7.1版本源码 全新推出开心版
源码下载地址:Zibll子比主题V7.1.zip...
响应式布局(其次)
响应式布局 一.响应式开发二.bootstrap前端开发框架1.原理2.优点3.版本问题4.使用(1)创建文件夹结构(2)创建html骨架结构(3)引入相关样式(4)书写内容 5.布局容器(已经划分…...
arhtas idea plugin 使用手册
arthas idea plugin 使用文档 语雀...
数组算法——查询位置
需求 思路 使用二分查找找到第一个值,以第一个值作为界限,分为左右两个区间在左右两个区间分别使用二分查找找左边的7,:找到中间位置的7之后,将中间位置的7作为结束位置,依次循环查找,知道start>end,返回…...
【解决leecode打不开的问题】使用chrome浏览器和其他浏览器均打不开leecode
问题描述: 能进入leetcode力扣官网但是对某些栏目加载不出来,比如学习栏目能完成加载、题库栏目不能加载。 解决方法一:cookies缓存问题 首先尝试删除浏览器cookie缓存。 因为以下原因: Cookies损坏或过期:有些网站…...
尝试在手机上运行google 最新开源的gpt模型 gemma
Gemma介绍 Gemma简介 Gemma是谷歌于2024年2月21日发布的一系列轻量级、最先进的开放语言模型,使用了与创建Gemini模型相同的研究和技术。由Google DeepMind和Google其他团队共同开发。 Gemma提供两种尺寸的模型权重:2B和7B。每种尺寸都带有经过预训练&a…...
56、巴利亚多利德大学、马德里卡洛斯三世研究所:EEG-Inception-多时间尺度与空间卷积巧妙交叉堆叠,终达SOTA!
本次讲解一下于2020年发表在IEEE TRANSACTIONS ON NEURAL SYSTEMS AND REHABILITATION ENGINEERING上的专门处理EEG信号的EEG-Inception模型,该模型与EEGNet、EEG-ITNet、EEGNex、EEGFBCNet等模型均是专门处理EEG的SOTA。 我看到有很多同学刚入门,不太会…...
ORA-00600: internal error code, arguments: [krbcbp_9]
解决方案 1、清理过期 2、control_file_record_keep_time 修改 恢复时间窗口 RMAN (Recovery Manager) 是 Oracle 数据库的备份和恢复工具。在 RMAN 中,可以使用“恢复窗口”的概念来指定数据库可以恢复到的时间点。这个时间点是基于最近的完整备份或增量备份。 …...
uni-app实现分页--(2)分页加载,首页下拉触底加载更多
业务逻辑如下: api函数升级 定义分页参数类型 组件调用api传参...
前端工程化理解 (2024 面试题)
最好介绍远古世界最好随性一点,不要太刻板 ,不然像背书 什么是前端工程化? - 知乎 前端工程化的历史 互联网初期,09 年以前,页面只需要展示一些列表、表格、文章内容以及简单图片即可,其目的是为了传送信…...
10 Php学习:循环
在 PHP 中,提供了下列循环语句: while - 只要指定的条件成立,则循环执行代码块do…while - 首先执行一次代码块,然后在指定的条件成立时重复这个循环for - 循环执行代码块指定的次数foreach - 根据数组中每个元素来循环代码块 当…...
FreeSWITCH 1.10.10 简单图形化界面17 - ubuntu22.04或者debian12 安装FreeSWITCH
FreeSWITCH 1.10.10 简单图形化界面17 - ubuntu22.04或者debian12 安装FreeSWITCH 界面预览00、先看使用手册0、安装操作系统1、下载脚本2、开始安装3、登录网页FreeSWITCH界面安装参考:https://blog.csdn.net/jia198810/article/details/132479324 界面预览 http://myfs.f3…...
ZStack Cloud 5.0.0正式发布——Vhost主存储、隔离PVLAN网络、云平台报警优化、灰度升级增强四大亮点简析
近日,ZStack Cloud 5.0.0正式发布,推出了包含Vhost主存储、隔离PVLAN网络、云平台报警优化、灰度升级增强在内的一系列重要功能。云主机管理、物理机运维、密评合规、灾备服务等诸多使用场景和功能模块均有更新,为您带来更完善的平台服务、更…...
商标没有去注册有哪些不好的影响!
有些商家咨询普推知产老杨,商标没有去注册有哪些不好的影响,其实对企业来说还有许多实际不利的影响,有时代价比注册一个商标要大很多。 想的商标名称没去注册商标,如果别人抢注拿下商标注册证,那就会涉及侵权…...
【小程序】常用方法、知识点汇总1
欢迎来到《小5讲堂》 这是《小程序》系列文章,每篇文章将以博主理解的角度展开讲解, 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言请求超时Markdown解析逐行显示效果文本变动事件转发…...
AugmentedReality之路-平面检测(5)
本文介绍通过AR检测水平平面和垂直平面,并将检测到的平面转化为Mesh 1、在首页添加功能入口 在首页添加一个按钮,命名为Start World Track 2、自定义ExecStartAREvent 创建ARSessionConfig并取名为ARSessionConfig_World 自定义ExecStartAREvent&…...
MQ:延迟队列
6.1场景: 1.定时发布文章 2.秒杀之后,给30分钟时间进行支付,如果30分钟后,没有支付,订单取消。 3.预约餐厅,提前半个小时发短信通知用户。 A -> 13:00 17:00 16:30 延迟时间: 7*30 * 60 *…...
Element ui 动态展示表格列,动态格式化表格列的值
需求 后台配置前端展示的表格列,遇到比如 文件大小这样的值,如果后台存的是纯数字,需要进行格式化展示,并且能控制显示的小数位数,再比如,部分列值需要加单位等信息,此外还有状态类࿰…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
