节是PE文件的主体部分,代码、全局数据等,都是以节进行存放的。一个PE文件中具体包含的节的数量,是由PE文件头中的NumberOfSections变量决定的。通过读取这个变量,可确定文件中的节的数量。
每个节都有一个对应的节头对其进行描述,所有节的节头统一存放在PE文件中的节头表中,这个表紧跟着PE文件头。下面是节头的定义:
下面对其中几个关键的字段进行描述:
(1)Name:每个段都有一个8字符长的名称域,并且第一个字符必须是一个句点。
(2)VirtualAddress:即节的虚拟相对地址,实际的内存装入地址,由这个域的值加上可选头部结构中的ImageBase虚拟地址得到。注意,如果这个映像文件是一个DLL,那么这个DLL就不一定会装载到ImageBase要求的位置。一旦这个文件被装载进入了一个进程,实际的ImageBase值应该通过使用GetModuleHandle来检验。
(3)SizeOfRawData:这个域表示了节的实体尺寸。(www.xing528.com)
(4)PointerToRawData:节在文件中的具体位置,是一个文件相对地址。通过这个地址以及SizeOfRawData变量,即可从文件中找到节的具体位置和大小。
PE文件中有几个节,则节头表中会包含几个节头。节头后面则跟着具体的节数据。在文件中寻找一个具体的节的时候,必须通过节的名字来查找。下面是一段根据节的名字,来获得对应节头的代码:
对于节来说,再重点说明几点:
(1)节在文件内的位置,与被加载到内存后的位置会不同。这样的一个结果就是,不能直接把PE文件加载到内存,不作处理地直接跳转到入口处运行。而必须根据PE头和节头的相关信息,对节进行重新定位。在操作系统的开发中,最开始的时候还没有PE文件加载程序,因此必须对PE文件进行处理,使得其在磁盘上的位置,跟加载到内存后的布局保持一致。这样引导程序就可直接把PE文件读入内存,直接跳转执行。完成这项工作的,就是即将介绍的辅助工具。
(2)有些节在内存中是存在的,而在文件中却不一定存在。比如.BSS节,这是未初始化的全局变量节。这个节在文件中存储的时候,只有一个节头,说明其大小,而无需存储具体的节。因为对于未初始化的全局变量,只需要在内存中预留空间即可,无需进行初始化。这时候为了直接加载和运行的目的,必须用工具把这些在文件中“不存在”的节,补充到文件中。这也是辅助工具的工作。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。