关于PE可执行文件的修改(2)

来源:互联网 发布:犀牛5.0中文破解版mac 编辑:程序博客网 时间:2024/05/22 22:18

我们将用“Module”这一术语来表示已装入内存的可执行文件或DLL的代码、数据及资源。除了程序中直接用到的代码和数据以外,一个Module也指Windows中用于判断代码及数据在内存中位置的支撑数据结构。在16位Windows中,支撑数据结构在Module Database中(Hmodule指向这个段)。而在32位Windows中,这些数据结构放在了PE部首中。
对于PE文件,首先应该知道,磁盘中的执行文件与其被Windows装载程序装入后的Module看起来非常相似。Windows装载程序把磁盘文件编程实际执行代码的中作相当简单,装载程序使用文件内存映象机制将磁盘文件映射到虚拟地址空间。打个比方,PE文件象一个活动地房子,装载时只需将某个块放在某个地方,在把它和其它部分拧好即可(比如说,把它和DLL连结在一起)。加载PE文件格式的DLL同样的简单。一旦Module被装入,在Windows中就同其它已经装入的文件一样了。
这种方式与16位的Windows 3.1明显的不同。16位的NE格式文件装载程序读取部分磁盘文件,并生成一个完全不同的数据结构,在内存中建立Module。当代码或数据需要装入时,装载程序必须从全局内存中分配出一块,查找原始数据在文件的什么地方,找到位置后再读取原始的数据,最后再进行一些修整。还有,每一个16位的Module要负责记住现在使用的所有selector(段选择符),该selector表示该段是否已经被抛弃等等。
对于Win32,某Module中的代码、数据、资源、输入表、输出表及其他有用的数据结构等使用的内存都放在一个连续的内存块中,编程人员只要知道装载程序文件映像到内存后的地址即可。通过映像后面的各种指针可以轻易找到Module中所有内容。
我们还应该熟悉Win32中的“相对虚拟地址”(Relative Virual Address,RVA)这个名词。PE文件中的许多项都是以RVA方式指定的,RVA就是某个项相对于文件映象地址的偏移。例如:装载程序将一个PE文件装入到虚拟地址空间中,从10000h开始的内存中,如果PE中某个表在映像中的起始地址是10464h,那么该表的RVA就是464h。将RVA装换为可用的指针,只要将RVA的值加上Module的基址即可。基地址是指装入到内存中的EXE或DLL程序的开始地址,它是Win32中的一个重要概念。为了方便起见,Windows NT或Windows 95将Module的基地址作为Module的实例句柄Instance Handle(Hinstance)。在Win32中称基地址为Hintance,似乎有些混淆,因为Instance Handle一词来源于16为的Windows 3.1,其中每一个执行实例都有自己的数据段,依此来互相区分,这就是Instance Handle的来历。在Win32中,以为不存在共享地址空间,所以已用程序无需加以区别。当然,Win16和Win32中的Hinstance还有些联系:在Win32中可以直接调用GetModuleHandle以取得指向DLL的指针,通过指针访问该DLL Module的内容。
我们还需要知道PE文件中“section”(块)。在PE文件中section大致相当于NE格式中的段或资源。块中包含代码或数据,与段不同的是,块没有大小限制,是一个连续内存块。有些块中包含程序中声明及直接使用的代码和数据,而另外一些数据块由连接器或库管理程序产生,包含对*作系统极其重要的信息。有人把section称为object,但object具有太多的意义。


PE可执行文件的逻辑结构是段,比如代码段“.text”、数据段“.data”、资源段“.rscs”等等。这些段大小都是按文件对齐,也就是说段大小 至少会按10h对齐,一般是1000h(4096字节),这由文件头中指定(链接的时候确定)。但是代码也好数据也好,不可能做到长度刚好是对齐的。也就是说,段的大小是大于段 中代码或数据实际大小的。他们之间的差值就是该段冗余的空间,这个空间被称为“空隙”。
//--------------------------------------
SFlags     DD        ? ; 块属性 
该字段是一组指出块属性(如代码/数据/可读/可写等等)的标志。比较重要的标志如下:
00000020h该块包含代码,通常与可执行标志(10000000h)一起设置。
00000040h该块包含已初始化的数据。
00000080h该块包含未初始化的数据。
02000000h该块可被丢弃,因为它一旦被装入后,进程就不再需要它了。常见的可丢弃的是.reloc(重定位块)
10000000h 该块为共享块
20000000h该块可以执行。通常当00000020h标志被设置时,该标志也被设置。
40000000h 该块可读。可执行文件中的块总是设置该标志。
80000000h该块可写。如果可执行文件没有设置该标志,装载程序就会将内存映像页标记为可读或可执行。 

原创粉丝点击