PE文件格式详解(七)
PE文件格式详解(七)
Ox00 前言
前面好几篇在讲输入表,今天要讲的是输出表和地址的是地址重定位。有了前面的基础,其实对于怎么找输出表地址重定位的表已经非常熟悉了。
0x01 输出表结构
当创建一个DLL文件时,实际上创建了一组能让EXE或者其他DLL调用的一组函数,PE装载器根据DLL文件中输出信息修正正在执行文件的IAT。当一个DLL函数能被EXE或者DLL文件使用时,它被称为输出了。其中输出信息被保存在输出表中,DLL文件通过输出表向系统提供输出函数名,序号和入口信息。
对于EXE文件一般不存在输出表,而大部分DLL文件都有输出表。输出表是由一个叫做IMAGE_EXPORT_DIRECTORY(简称IED)组成。IED存放着输出函数名,输出序数等信息,他的结构如下:
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics; // 未使用,总为0
DWORD TimeDateStamp; // 文件创建时间戳
WORD MajorVersion; // 未使用,总为0
WORD MinorVersion; // 未使用,总为0
DWORD Name; // 指向一个代表此 DLL名字的 ASCII字符串的 RVA
DWORD Base; // 函数的起始序号
DWORD NumberOfFunctions; // 导出函数的总数
DWORD NumberOfNames; // 以名称方式导出的函数的总数
DWORD AddressOfFunctions; // 指向输出函数地址的RVA
DWORD AddressOfNames; // 指向输出函数名字的RVA
DWORD AddressOfNameOrdinals; // 指向输出函数序号的RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
下面介绍几个重要字段:
Name:指向的是的ASCII字符串的RVA
NumberOfFunctions:输出表EAT表中的数据条目数。
NumberOfName:输出表ENT表中的数据条目数,ENT也是一个RVA地址,不过每项指向的是函数名字的ascii码。
AddressOfFunctions:是指向EAT的RVA值EAT是RVA一个数组,每一项指向了被输出的函数的地址。
AddressOfNames:是指向ENT的RVA值,ENT也是一个数组,每项指向被输出函数的名字。
下图是他们之间的关系图:
0x02实例分析输出表结构
1)用hexworkshop打开DLLDemo.DLL文件,找到数据目录表的第一项,它在文件头偏移78h处。如下图:
值为RVA=4000h,转化为FileOffset=800h。此处即为输出表结构所在地址。
2)跳往800h,依次读出几个重要字段的值如下图:
由上图可知各个字段的RVA值,Name=0000 4032,NumberOfFunctions=0000 0010 NumberOfNames:0000 0010
AddressOfFunctions=0000 4028 ,AddressOfNames=0000 402c 。两个Address字段全都转化为FileOffset值。
Name=832h,AddressOfFunctions=828h,AddressOfNames=82ch。跳往832h如下图:
可知输出的DLL名字叫做DLLDemo.DLL,跳往828h即可找到输出函数的EAT表,跳往82ch即可找到输出函数的ENT表。
0x03 输出实现过程总结
PE装载器调用GetProcAddress来查找DLLDemo.DLL里的api函数,系统通过定位DLLDemo.DLL的IMAGE_EXPORT_DIRECTORY(出书目录表)结构开始工作,从这个结构中他获得输出函数名称表(ENTb表)的起始地址,进而知道这个数组只有一个元素,他对名字进行二进制查找直到发现字符串“MegBox”。PE装载器发现MsgBox是数组的第一个元素,加载器然后从输出序数表读取相应的第一个值,这个值是MsgBox的输出序数。使用输出序数作为进入EAT的索引,他得到MsgBox的值是1008h,1008h加上DllDemo.DLL的装入地址得到MsgBox的实际地址。
0x04 基址重定位概念
当连接器生成一个PE文件时,他假设这个文件执行时会被装入默认的基址处,并且把code和data的相关地址写入PE文件中。如果装入是按照默认的值作为基址装入,则不需要基址重定位,但是如果可执行文件被装在到内存中的另一个地址,链接器所登记的地址就是错的这时就需要用重定位表来调整。在PE文件中,它往往单独分为一块,用“.reloc”来表示。PE文件重定位过程。
0x05 详细解读基址重定位
基址重定位表放在一个位于.relo的区域中,但是找到它需要通过数据目录表的第五项成员Base reloction Table,这项所指向重定位的基本结构IMAGE_BASE_RELOCATION。
IMAGE_BASE_RELOCATION的基本定义如下:
struct IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;//重定位数据开始RVA
DWORD SizeOfBlock;//重定位块的长度
WORD TypeOffset;//重定位项位数组
}
IMAGE_BASE_RELOCATION ENDS
下面分别解释一下这几个字段:
VirtualAddress:是这一组重定位数据的开始的RVA地址。其实就是原来的地址加上这个值就完成了重定位。
SizeOfBlock:当前重定位结构的大小,因为VirtualAddress和SizeOfBlock都是固定的四个字节,所以SizeOfBlock的值减去8就得到了重定位块的大小。
TypeOffset:这个字段很有意思,一个两个字节16位,高四位代表重定义类型,低12位装入的是我们需要重定位的地址,即这个地址加上前面的字段VirtualAddress的值完成重定位。注意Typeoffset是一个数组他的值有SizeOfBlock-8决定。
下图位重定位示意图:
0x06 实例讲解地址重定位
1)hexWrokShop打开PE文件DllDemo.DLL。通过数据目录表的第五项找到重定位结构IMAGE_BASE_RELOCATION,即在PE文件头偏移地址为A0h处,跳往a00h处,下图标黑地方即为结构IMAGE_BASE_RELOCATION数据。
我们注意到第一个字段VritualAddress=0000 1000h,SizeOfBlock=0000 0010h,由此可得数组TypeOffset共八个个字节。每个元素两个字节则共四组数据。整理得出下表:
项目 |
重定位数据1 |
重定位数据2 |
重定位数据3 |
重定位数据4 |
原始数据 |
0F 30 |
23 30 |
00 00 |
00 00 |
TypeOffset值 |
30 0F |
30 23 |
00 00 |
00 00 |
TypeOffset高四位 |
3 |
3 |
||
TypeOffset低12位 |
00F |
023 |
||
低12位加上VritualAddress |
100F(RVA值) |
1023(RVA值) |
||
转换成FileOffset |
20F |
223 |
重定位后的地址如下图:
PE文件格式详解(七)的更多相关文章
- PE文件格式详解,第一讲,DOS头文件格式
PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...
- PE文件格式详解,第二讲,NT头文件格式,以及文件头格式
PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) PS:本篇博客 ...
- PE文件格式详解,第三讲,可选头文件格式,以及节表
PE文件格式详解,第三讲,可选头文件格式,以及节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶可选头结构以及作 ...
- PE文件格式详解(一)
PE文件格式介绍(一) 0x00 前言 PE文件是portable File Format(可移植文件)的简写,我们比较熟悉的DLL和exe文件都是PE文件.了解PE文件格式有助于加深对操作系统的理解 ...
- PE文件格式详解(下)
作者:MSDN译者:李马 预定义段 一个Windows NT的应用程序典型地拥有9个预定义段,它们是.text..bss..rdata..data..rsrc..edata..idata..pdata ...
- PE文件格式详解(上)
作者:MSDN 译者:李马 摘要 Windows NT 3.1引入了一种名为PE文件格式的新可执行文件格式.PE文件格式的规范包含在了MSDN的CD中(Specs and Strategy, Spec ...
- PE 文件格式详解
PE文件 是微软 Win32 环境下可执行文件的标准格式. 所谓的可执行文件并不仅仅是常见的 EXE 文件,DLL,SYS,VXD 等文件也都属于 PE 格式. |-------> DOS_MZ ...
- PE文件格式详解(六)
0x00 前言 前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以 ...
- PE文件格式详解(八)
0x00 前言 前面了解了PE文件的输入和输出,今天来看看另一个重要的结构——资源.资源结构是很典型的树形结构,层层查找,最终找到资源位置. 0x01 资源结构介绍 Windows程序的各种界面成为资 ...
随机推荐
- effictive c++
c++条款 num 1:尽量以const enum inline替换#define 1)对于单纯常量,最好以const对象或enums替换#defines 2)对于形似函数的宏,最好改用inline函 ...
- Java基础(九)
一.总述 多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务.通常,每一个任务称为一个线程,它是线程控制的简称.可以同时运行一个以上线程的程序称为多线程程序. 多进程与多线程的区别: ...
- 实践案例丨基于ModelArts AI市场算法MobileNet_v2实现花卉分类
概述 MobileNetsV2是基于一个流线型的架构,它使用深度可分离的卷积来构建轻量级的深层神经网,此模型基于 MobileNetV2: Inverted Residuals and Linear ...
- 熬夜之作:一文带你了解Cat分布式监控
Cat 是什么? CAT(Central Application Tracking)是基于 Java 开发的实时应用监控平台,包括实时应用监控,业务监控. CAT 作为服务端项目基础组件,提供了 Ja ...
- 【分区】使用 GPT 分区表分区并格式化 (非 FreeBSD 系统)
新购买的 Linux 云服务器,由于数据盘未做分区和格式化,无法使用. 注意: 数据盘中的数据在格式化后将全部被清空.请在格式化之前,确保数据盘中没有数据或已对重要数据进行备份.为避免服务发生异常,格 ...
- 【转载】图解NumPy
目录 1. 读写文件 2. 内建向量/矩阵 3. 切片操作 4. 聚合函数 4.1. 向量 4.2. 矩阵 5. 矩阵的转置和重构 6. 常用操作API 7. 应用实例 7.1. 生成向量.矩阵 7. ...
- @uoj - 310@ 【UNR #2】黎明前的巧克力
目录 @description@ @solution@ @accepted code@ @details@ @description@ Evan 和 Lyra 都是聪明可爱的孩子,两年前,Evan 开 ...
- c常用函数-strcpy和strncpy
strcpy和strncpy strcpy在脚本开发中经常用到,例如处理参数等,它的作用是把一个字符串复制到另一个字符串中. strncpy的作用是把一个字符串中的指定长度复制到另一个字符串中,如果指 ...
- (一)maven搭建和idea的配置
一.下载安装 前往 https://maven.apache.org/download.cgi 下载最新版的Maven程序.解压到任意目录 (要养成不起中文路径的好习惯,否则有时间出问题真的很难找) ...
- 带你学够浪:Go语言基础系列 - 8分钟学复合类型
★ 文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) " 对于一般的语言使用者来说 ,20% ...