PE文件到内存的映射,说白了就是将磁盘上的文件放到内存中,但事实上并不是这样。在执行一个PE文件的时候,Windows并不是一开始就将整个文件映射到内存,而是采用与内存映射文件类似的机制。Windows装载器在装载的时候建立好虚拟地址和PE文件之间的映射关系。真正执行某个内存页中的指令或者访问某一页中的数据时,这个页面才会被从磁盘提交到物理内存。
Windows装载器在装载DOS部分、PE文件头部分和区表部分是不进行任何特殊处理的,而在装载区块的时候则会自动按区块的属性做不同的处理。
Windows装载器在装载DOS部分、PE文件头部分和区表部分是不进行任何特殊处理的,而在装载区块的时候则会自动按区块的属性做不同的处理。
一般来说有以下几个方面的内容:
1.内存页的属性;
2.节的偏移地址
3.节的尺寸;
4.不进行映射的节。
例如说内存页的属性:对于磁盘映射文件来说,所有的页都是按照磁盘映射文件函数指定的属性设置的。(只读/只写/读写)但是在装载可执行文件时,与节对应的内存页属性要按照节的属性来设置。
例如说节的偏移地址:节的起始地址是IMAGE_OPTIONAL_HEADER32结构的FileAlignment字段的值进行对齐的,而被加载到内存时是按照同一结构中的SectionAlignment字段的值对齐的,两者的值可能不同,所以一个节被装入内存后相对于文件头的偏移和在磁盘文件中的偏移可能是不同的。
节表事实上一个地图,它存储着后面各个区块的地址,起到了索引的作用,起规定了区块的一些属性。要学习节表就要学习IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节。
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //节表名
union
{
DWORD PhysicalAddress; //物理地址
DWORD VirtualSize; //真实长度
} Misc;
DWORD VirtualAddress; //节区的RVA
DWORD SizeOfRawData; //在文件中对齐后的尺寸
DWORD PointerToRawData; //在文件中的偏移量
DWORD PointerToRelocations; //在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; //行号表的偏移
WORD NumberOfRelocations; //在OBJ文件中使用,重定位项数目
WORD NumberOfLinenumbers; //行号表中行号的数目
DWORD Characteristics; //节属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;