从PE格式牵涉到的理论基础的概念疑惑(修改)

来源:互联网 发布:iskyshop b2b2c源码 编辑:程序博客网 时间:2024/04/28 10:51

学习PE的时候遇到了几个问题一直想不明白,这里先记录下来。

1.CreateFile函数的返回值是一个内核对象的句柄。那么什么是内核对象呢?

答:从《windows核心编程》里找到了解释:

什么是内核对象?  

内核对象只是内核分配的一个内存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。有些数据成员(如安全性描述符、使用计数等)在所有对象类型中是相同的,但大多数数据成员属于特定的对象类型。例如,进程对象有一个进程I D 、一个基本优先级和一个退出代码,而文件对象则拥有一个字节位移、一个共享模式和一个打开模式。  

内核对象的数据结构只能被内核访问,因此应用程序无法在内存中找到这些数据结构并直接改变它们的内容。Microsoft 规定了这个限制条件,目的是为了确保内核对象结构保持状态的一致。这个限制也使Microsoft能够在不破坏任何应用程序的情况下在这些结构中添加、 删除和修改数据成员。  

当调用一个用于创建内核对象的函数时,该函数就返回一个用于标识该对象的句柄。为了使操作系统变得更加健壮,这些句柄值是与进程密切相关的。因此,如果将该句柄值传递给另一个进程中的一个线程,那么这另一个进程使用你的进程的句柄值所作的调用就会失败。如果想在多个进程中共享内核对象,要通过一定的机制  如对象句柄的继承性,命名对象,复制对象句柄。  

除了内核对象外,你的应用程序也可以使用其他类型的对象,如菜单、窗口、鼠标光标、刷子和字体等。这些对象属于用户对象图形设备接口(GDI)对象,而不是内核对象。  当初次着手为若要确定一个对象是否属于内核对象,最容易的方法是观察创建该对象所用的函数。

2.映像  与   映射 的区别

答:自己在看参考资料的时候经常将这两个词搞混,弄不清楚到底是什么意思。这里来理解一下。

首先,映像 很明显是一个名词(废话嘛......),英文是Image,其实个人觉得翻译成映像不好,不如翻译  镜像。

如果是镜像的话,那么就好理解了。可以看成是“镜子的反射出来的东西嘛”。也就是说这两个东西是完全一样的。

举个例子,上次那篇博客里有这句c++代码,虽然自己没学过c++

BYTE* pBuffer = new BYTE[dwFileSize];
这段代码的话先暂时理解成是动态分配内存。比如说磁盘里面有一个PE文件,那么 映像出来的就是在内存中的一块 和磁盘中一模一样的东西。

 映射 就是动词了,英文是mapping

我们数学里面学的函数 其实就是一种特殊的映射,也就是多对一的关系 (多个x可以对应一个y值)

而映射的话是可以多对多的。但是这个多对多的概念我们在这里是用不到的,一般我们用一对一理解就可以了。

PE中的文件  映射  内存,这个概念就比较好理解了(具体的话在下面这个文库链接里面也是有的)。


3.CreateFile 函数和CreateFileMapping函数

答:关于这两个函数的具体解释,可以参考百度文库的这篇文章:

http://wenku.baidu.com/view/2605c33b580216fc700afd83.html

简单的说,就是CreateFile函数返回的这个内核句柄指向的只是在磁盘中的那个文件。

跟他类似,CreateFileMapping函数返回的这个内核句柄指向的是将要映射的那个文件,这个文件其实还是在磁盘中,并没有被映射到内存中。

如果要映射,那么就要使用另外一个API   MapViewOfFile 这个函数了


4.ImageBase  基地址的理解

我在学习PE的时候很重视offset 偏移量这个概念,平时我们用UE或者是winhex等其他编辑器打开的时候,在最左边显示的就是偏移量。




PE格式里面的可选映像头IMAGE_OPTIONAL_HEADER这个 数据结构里面有ImageBase这个成员

是程序默认装入基地址。

这个ImageBase就是程序默认装入的基地址,也就是说这个是在  映射到内存的时候才出来的概念。


理解了上面所有这些概念,那么下面这个困扰我很久的问题应该就可以解答了:

我上次写的那个读取PE信息读取的是磁盘里面的文件信息,也就是说先在内存中腾出一块地方来,这块地方的大小跟磁盘中文件的大小是一模一样的,然后  在内存中获得文件的 镜像,我读取的就是这个在内存中的镜像的信息。

所以上篇博客里面的这个pBase 其实只是动态分配内存的指向这块内存的指针,跟这个ImageBase是一点关系都没有的。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

深一步的理解。

今天自己在看PE权威这本书的时候,发现上面讲的东西好像错了。

下面是《windowsPE权威指南》里面的一段话:

内存映射文件 是指将硬盘上的文件不做修改地装载到内存中。这样,文件中字节与字节之间就是顺序排列的了。在硬盘中,文件被分割成若干簇,这些簇不一定会按照原来顺序排列在一起,当我们访问磁盘上的文件时,需要计算机首先将不同位置的内容读取到内存。有了内存映射文件,访问就会变得更轻松和快捷,由于读取磁盘的操作集中到了一起执行,读写效率会提高很多。被一次性读取到内存的文件字节按线性顺序,访问相对简单,速度也提升了不少。所以,许多大型的编辑软件被设计中经常会使用内存映射文件存取磁盘文件。


PE内存映像 是指将PE文件按照一定的规则装载到内存中,装入后的整个文件头内容不会发生变化,但PE文件的某一部分如节的内容会按照字段中的对齐方式在内存中对齐,从而使得内存中的PE映像与装载前的PE文件不用。那么,为什么PE内存映像不能和一般的内存映射文件一样呢?答案很简单:PE文件是由操作系统装载进内存的,其目的是为了运行。为了配合操作系统的运行,方便调度,提高运行效率,PE镜像必须按照一定的格式对齐,所以内存中的PE映像和原来硬盘上的文件是不同的,当然与内存映射文件也就不一样了。


自己将上面的话读了好几遍,每一句话都理解了一下。

也就是说,内存映射文件就是将磁盘上的文件整理起来,映像到内存中。这个时候在内存中是一个连续完整的文件。

PE内存映像是由windows加载器自己执行的,它的原理与内存映射文件的原理有些类似,但有区别的是它的对齐方式不同。


理解到这里,随之而来的问题又来了。如果说有一个文件的大小为3G,而我的内存只有2G,那么这个时候内存映射文件时如何处理的呢?

这个可能就要涉及到虚拟内存的概念了。这里先留下这个问题,先查查资料。

大家如果知道的话,恳请告诉我,谢谢了



原创粉丝点击