简谈PE文件和内存

来源:互联网 发布:罗马安全吗 知乎 编辑:程序博客网 时间:2024/05/08 10:39

关于PE文件(可执行文件,Portable Executale)结构的研究以前也看过,很久没回顾了。前两天看了本书又涉及到这方面的知识,在此分享一下个人心得,毕竟本人是还没出茅庐的菜鸟,可能有错误之处恳请大家指正。

我相信大家在接触PE听到的醉多的就是什么RVA,VA,Offset,Rsize,Vsize啥啥啥乱七八糟的名称,还有计算公式。网络上关于这个的解释都是粘过来,复制过去,很多描述这些概念的人我相信他们自己都搞不清楚这些。学习PE文件结构其实就是为了掌握磁盘文件和它在内从里的映射关系。这个说简单,其实还是挺麻烦。PE文件就是可执行文件,但不限于exe文件,还有dll,COM,sys都算是PE文件。在此我们只简单地说下exe文件。PE文件被加载到内存中运行的过程是我们关心的。PE文件是如何在内存中被管理的呢,它又被加载到内存的哪里呢?PE文件被加载到内存中的位置,也就是内存地址,是在PE文件中被设置好的,它会告诉系统,将自己加载到某个地址,而且,32位PE中,这个地址往往是0x00400000。我们往往是运行多个可执行文件,那么肯定会冲突。这个我们不用担心,操作系统会进行内存管理,每个文件在自己的虚拟空间里运行,互不影响。这个地址也就是VA(第一个概念,Virtual Address)。要明白VA不是一个地址,它是一段地址空间,我们很关心运行这个PE文件的内存首地址(Image Base,映像基址,第二个概念)。如果说想了解PE文件的内存结构,必须深入理解PE文件的结构。尤其是节区数据,因为节区数据中存储的是汇编指令和操作数,也就是执行的代码和代码使用的变量,常量等数据。ok,贴张图吧,PE文件结构回头再谈,今天只说下PE文件在内存运行的过程和地址转换的概念性东西,这些很枯燥但是相当重要。


这是节区名为.text的数据开头部分,是代码段。它在内存里面的结构是:


我们可以看到开头数据是对应的。68 F4 20 40 00 ,对应的汇编指令是PUSH 4020F4,内存的地址和PUSH的地址“倒序”了,这个大家应该能够理解,因为Intel芯片的

内存数据是小尾方式,例如varX=0x12345678在内存中存储的是 78 56 34 12。咱们看下第二章图片,指令首地址 0x00401000,还记得前面说过的么,Image Base,

映像基址是0x00400000。.text的数据在文件中的地址(也就是偏移量是0x400),记住我说的是.text的数据,.text节区是在头文件(PE头中的可选头被指出的,你可以理解.text节区是变量名,而.text节区的数据是变量的值)。.text被加载到内存中,地址是0x1000,它在文件中的地址是0x400,因为磁盘文件中存储单位以0x200(512)作为基本单位,在内存中则是0x1000(4096)字节作为基本单位。我们在此只看第一条指令,push 4020F4,也就是把4020F4地址的内容压栈。我使用的是C32Asm所以看不到数据区的内容,只能看到代码段的数据内容。使用OD可以看到数据区的内容,但是我们可以根据地址4020F4去磁盘文件中找到它。记住我们的Image Base是0x400000,那么我们用这个地址减去基址得到0x20F4,(第三个概念,RVA,相对虚拟地址,也就是数据在VA中的地址相对于基址的偏移量Offset)。我们仅仅得到了这个数据的RVA,要想得到它的文件地址(Raw Offset),必须知道这个RVA对应哪个节区,然后在节区中根据地址找到它。所以我们必须分析它的PE结构,在这里可以使用个工具,PEid,或者LordPE,我已经上传到了我的CSDN资源里,大家可以去免费下载。


我使用的是LordPe,.text的VOffset是1000,也就是虚拟地址偏移,节区大小是0x7F4,Roffset也就是文件地址是0x400,Rsize是0x800,跟Vsize有出入,其实在Rsize的有效数据部分大小0x7F4其他部分被0x00填充。那么我们在前面获得的0x20F4存储在文件的哪里呢。根据上面的节区表我们可以知道0x20F4在内存中存储在Voffset开始的F4处,这是属于.rdata节区的,.rdata节区在文件中偏移量,也就是它的地址0xC00(因为文件是以0x00开始存储的,不存在Image Base所以偏移量就是地址)。所以该数据在文件中的地址是0xCF4。


而这个数据就是"helloworld'。这个程序的作用就是打印“helloworld”。我们在对应的数据区修改这个值的话,打印的内容也就会修改。

前几天我使用Python脚本写了一个PE分析工具,大家也可以去我的CSDN资源免费下载。一般的32位PE解析没什么问题,但是解析类似Kernel32.dll出现了问题,而且使用Peid,lordPe解析kernel32结果都有差异。对这个问题表示很疑惑。过些天我再补充关于PE结构的知识。希望大家根据这篇文章能对文件地址,内存地址映射有基本的认识。

0 0