PE格式解析-NT头与地址换算

PE文件格式是什么?
在Windows下,我们使用的exe、dll等文件都是使用的PE文件格式。当我们双击一个exe文件的时候,OS是根据PE格式来知道文件里面的代码以及数据的分布的。

1、了解文件偏移地址、虚拟地址、相对虚拟地址
文件偏移地址:数据在文件内相对于文件头的偏移
虚拟地址(VA):数据(代码以及真正的data)加载到内存后,在内存里面的地址
相对虚拟地址(RVA):数据(代码以及真正的data)加载到内存后,其中的一条指令或数据相对于VA的地址

2、文件偏移地址与相对虚拟地址相同吗?
答案是:不相同
了解这个之前,我们先来了解下文件对齐值与内存对齐值(块对齐值)

文件的对齐值大小:200h,也就是512字节。因为硬盘的一个扇区大小为512字节,设置文件对齐值为512字节是为了提升硬盘的工作效率(对于所有的硬盘驱动来说,都是以一个扇区来进行读写,每次发一个信号要读取数据的时候,它最少读取512字节数据)
例如:
我们的代码段为300字节时,在内存里面占用的空间为512字节,剩余的212字节填充为0,凑足512字节,方便我们读取出来的时候一次性读写,而不必再去识别这512字节里面哪里为代码段,哪里为数据段,一次提升操作硬盘的效率。
如果代码段为513字节,在硬盘上就会占用1024个字节,剩余的511字节为0

内存对齐值大小:1000h,也就是4096字节。同文件的对齐值相似,只要你少于4096字节时,它都会占用4096字节的空间,即时你只有一个字节,它也会占用4096字节的空间

文件对齐值与内存对齐值(块对齐值)
示意图

通过以上了解,我们可以得知,文件偏移地址与相对虚拟地址是不相同的。首先,一个是在硬盘一个是在内存中,其次它们的对齐值不同导致了他们的偏移量也会不相同。我们可以看以下示意图(注:图中释义不是来自于上图的实际值)
对齐值

映像:文件被加载到内存后,才叫做一个映像。
我们不难发现,映像大小和实际文件的大小又不相同,毕竟内存里面为0x1000对齐,硬盘为0x200对齐
(附属一句:文件的实际大小与文件占用空间的不相同的原因,因为操作系统(OS)会对我们的文件进行一些属性之类的标识,所以它们的大小不相同)

3、PE格式解析
推荐几款解析PE文件的工具:WinHex、Stud_PE、LoadPE
PE文件一半

通过以上PE格式示意图,使用WinHex+Stud_PE进行解析(对于区段及之后内容下次再解析)
解析1
注释内容
这里写图片描述

程序入口点RVA:程序被加载起来后,windows 执行的第一条指令“在内存中的地址”
起始RVA
基址:我们的应用程序应该被加载到内存的哪一片区域(如果使用的可变基址,操作系统在加载应用程序的时候,会进行基址的随机变换)
通过两次加载,我们不难看出,随机基址导致每次程序加载到内存后的基址都不相同
这里写图片描述

这里写图片描述

4、文件偏移与RVA值的换算
首先我们要知道,PE格式里面,大量采用的是RVA值,而此时如果我没有将程序(一个PE文件)加载到内存的时候,我是怎么知道它的RVA值呢?
要求:转换一个内存地址RVA到一个文件的偏移是多少,怎么实现?
1、把PE文件中的所有区段信息全部读取出来
2、RVA属于哪一个区段
3、RVA - RVA(用需要查找的RVA减去整个区段头的RVA,
计算出指定的内存地址相对于区段头的偏移量) + File offset(区段头在文件里面的偏移)
(区段:就是.text、.data等段,下次再详细解释)
区段
举个例子:
如果此时我的RVA值为1014,那么文件偏移为多少?
1、.text段的RAV(VirtualOffset)为1000,大小为4B48字节,明显我们的1014属于这个范围。对于的.text段的文件偏移(RawOffset)为400.
2、(1014-1000)+ 400 = 414,这就是我们的文件偏移值
这里写图片描述
注:虚拟地址为基址加上相对虚拟地址,而第一张图或者PE文件的解析中我们可以发现,基址为400000,所以虚拟地址为400000+1014=101014.

本文难免有所错误,如有问题欢迎留言

发布了54 篇原创文章 · 获赞 38 · 访问量 8万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章