PE格式系列_0x05:输出表和重定位表(.reloc)

2023-10-20 14:20

本文主要是介绍PE格式系列_0x05:输出表和重定位表(.reloc),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:PE文件的格式就先介绍这么多,不建议继续学习重定位表和输出表了,因为边际收益在下降;其实学会了输入表的手动分析,重定位表和输出表的分析是类似的,也要简单很多

只要知道当发生基址重定位时会涉及到重定位表,dll会有一份输出给别人用的函数列表涉及到输出表就可以了,用到哪个再系统学一下就ok了

建议是好的,但是不写完这部分总感觉烂尾了,所以花了点业余时间将几个重要的表知识整理了一下

文章目录

  • 1.输出表
  • 2.基址重定位表
  • 3.编写PE格式展示工具
  • 4.参考

1.输出表

输出表简单理解就是一个表格,记录输出函数的信息

// Export Format
typedef struct _IMAGE_EXPORT_DIRECTORY {DWORD   Characteristics;		//未使用,总是0DWORD   TimeDateStamp;WORD    MajorVersion;WORD    MinorVersion;DWORD   Name;					//DLL的真实名称,如ntdll.dllDWORD   Base;					//基数,序号减去这个基数就是函数地址数组(EAT)的索引DWORD   NumberOfFunctions;		//EAT相关的DWORD   NumberOfNames;          //ENT相关的DWORD   AddressOfFunctions;     // RVA from base of image,指向函数地址数组(地址数组,EAT)DWORD   AddressOfNames;         // RVA from base of image,函数名字的指针地址(名字数组,ENT)DWORD   AddressOfNameOrdinals;  // RVA from base of image,指向输出序号数组
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

流程:PE装载器访问PE文件输出表时,通过AddressOfFunctions获取一个函数的地址,通过AddressOfNames获取一个函数的名称,但是此时还没有建立对应关系,通过AddressOfNameOrdinals来建立名称和地址的联系

注意:一个名称只有一个地址,但是一个地址可以关联多个名称(类似于别名)

示例1:DllDemo中只有一个导出函数MsgBox

#1.查看加载基址
0:006> lmvm DllDemo
start    end        module name
004c0000 004c6000   DllDemo    (deferred) #2.查看输出表相关信息汇总
0:006> !dh DllDemo -e_IMAGE_EXPORT_DIRECTORY 004c4000 (size: 00000045)	#绝对地址Name: DllDemo.DLL  			Characteristics: 00000000 Ordinal base: 1.			Number of Functions: 1. Number of names: 1. 		EAT: 004c4028.ordinal hint target   name1    0 004C1008 MsgBox#3.dump内存,根据数据格式手动分析(节选)          
0:006> dd /c 1 004c4000
004c400c  00004032		#Name,da 00004032+004c0000可直接查看dll名称		
004c4010  00000001		#Base
004c4014  00000001		#NumberOfFunctions
004c4018  00000001		#NumberOfNames
004c401c  00004028		#EAT
004c4020  0000402c		#ENT
004c4024  00004030		#AddressOfNameOrdinals
#查询dll名称
0:006> da 00004032+004c0000
004c4032  "DllDemo.DLL"
#查询EAT
0:006> dd 00004028+004c0000 L1
004c4028  00001008				#得到的是RVA
#查询ENT
0:006> dd 0000402c+004c0000 L1
004c402c  0000403e				#得到的是RVA
0:006> da 0000403e++004c0000
004c403e  "MsgBox"

使用PE工具查看输出表

在这里插入图片描述

示例2:kernel32.dll的输出表汇总查看

0:006> !dh kernel32 -e
_IMAGE_EXPORT_DIRECTORY 77382d30 (size: 0000dc14)
Name: KERNEL32.dll 
Characteristics: 00000000 
Ordinal base: 1.
Number of Functions: 1607. 
Number of names: 1607. 
EAT: 77382d58.ordinal hint target   name4    0          AcquireSRWLockExclusive5    1          AcquireSRWLockShared6    2 77310AC0 ActivateActCtx7    3 77310400 ActivateActCtxWorker
...

2.基址重定位表

通常重定位表只有dll文件和开了ASLR的exe才需要关心,因为此时不能保证加载时默认的装载地址不会被其他模块占用

  • 如果没有被占用,就没重定位什么事了
  • 如果被占用,就需要重定位表对需要重定位的数据进行修正

简单理解,对于PE加载器来说,他不关心需要修正的地址的具体用途,只要知道有一组需要修正的数据即可

原理:比如基址默认是ImageBase,一个地址相对于ImageBase的偏移是B;加载到内存中的真正基址是ImageBaseNew,则B修正后有如下公式:B_new = (ImageBaseNew - ImageBase) + B

下面是重定位的示意图

在这里插入图片描述

在PE文件中,重定位表一般单独作为一个section,用.reloc表示

基址重定位数据采用类似按页分割的组织方式,是由许多重定位块串联成的,有如下要求:

  • 每个重定位块:大小都是4KB的重定位信息(_IMAGE_BASE_RELOCATION是每个块的起始结构)

    结束标志VirtualAddress0的一个_IMAGE_BASE_RELOCATION结构

  • 每个重定位数据:必须是以4 bytes对齐的,TypeOffset数组记录要重定位的地址

    结束标志:SizeOfBlock会指定大小

// Based relocation format.
typedef struct _IMAGE_BASE_RELOCATION {DWORD   VirtualAddress;			//重定位数据的开始RVA地址,需要重定位地址要加上这个值DWORD   SizeOfBlock;
//  WORD    TypeOffset[1];			//重定位项数组,高4位(重定位类型) + 低12位(重定位地址)
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

其中:TypeOffset描述的是每个重定位项的数组,定义中是一个可变数组,高4位的类型如下

// Based relocation types.
#define IMAGE_REL_BASED_ABSOLUTE     0  //什么也不做,存在是为4 bytes对齐和标识TypeOffset数组结束
#define IMAGE_REL_BASED_HIGH         1
#define IMAGE_REL_BASED_LOW          2
#define IMAGE_REL_BASED_HIGHLOW      3	//x86文件都是这种类型,重定位指向的整个地址都需要修正

3.编写PE格式展示工具

如果写过壳,会发现写PE分析工具很简单;要充分利用微软的ImageHlp库提供的操作PE Image的函数,编写思路:

  • 1.检查文件格式
  • 2.读取File Headers和Optional Headers的内容
  • 3.得到数据目录表信息
  • 4.得到区块表信息
  • 5.得到输出表、输入表等结构信息

下面是一个简单实现的PE查看器截图:

在这里插入图片描述

简单使用StudPE验证写的PE工具的正确性,基本信息获取都是正确的

在这里插入图片描述

4.参考

  • 1.《加密与解密》第11章 PE文件格式
  • 2.《逆向工程核心原理》第13章 PE文件格式

这篇关于PE格式系列_0x05:输出表和重定位表(.reloc)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/247683

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Mysql常见的SQL语句格式及实用技巧

《Mysql常见的SQL语句格式及实用技巧》本文系统梳理MySQL常见SQL语句格式,涵盖数据库与表的创建、删除、修改、查询操作,以及记录增删改查和多表关联等高级查询,同时提供索引优化、事务处理、临时... 目录一、常用语法汇总二、示例1.数据库操作2.表操作3.记录操作 4.高级查询三、实用技巧一、常用语

利用Python脚本实现批量将图片转换为WebP格式

《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统

CSS Anchor Positioning重新定义锚点定位的时代来临(最新推荐)

《CSSAnchorPositioning重新定义锚点定位的时代来临(最新推荐)》CSSAnchorPositioning是一项仍在草案中的新特性,由Chrome125开始提供原生支持需... 目录 css Anchor Positioning:重新定义「锚定定位」的时代来了! 什么是 Anchor Pos

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式

《C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式》Markdown凭借简洁的语法、优良的可读性,以及对版本控制系统的高度兼容性,逐渐成为最受欢迎的文档格式... 目录为什么要将文档转换为 Markdown 格式使用工具将 Word 文档转换为 Markdown(.

Java中JSON格式反序列化为Map且保证存取顺序一致的问题

《Java中JSON格式反序列化为Map且保证存取顺序一致的问题》:本文主要介绍Java中JSON格式反序列化为Map且保证存取顺序一致的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录背景问题解决方法总结背景做项目涉及两个微服务之间传数据时,需要提供方将Map类型的数据序列化为co

Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题

《Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题》:本文主要介绍Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录一、前言二、系统架构检测三、卸载旧版 Go四、下载并安装正确版本五、配置环境变量六、验证安装七、常见

使用Python开发Markdown兼容公式格式转换工具

《使用Python开发Markdown兼容公式格式转换工具》在技术写作中我们经常遇到公式格式问题,例如MathML无法显示,LaTeX格式错乱等,所以本文我们将使用Python开发Markdown兼容... 目录一、工具背景二、环境配置(Windows 10/11)1. 创建conda环境2. 获取XSLT