PE格式概貌,以下只是PE格式的大致结构
+---------------+
| DOS MZ header |
+---------------+
| DOS stub |
+---------------+
| PE header |
+---------------+
| Section table |
+---------------+
| Section 1 |
+---------------+
| Section 2 |
+---------------+
| Section ... |
+---------------+
| Section n |
+---------------+
1) DOS MZ header
这一模块有64个字节(大都如此),我们所关心的是开始和结尾的四个字节.
开始的四个字节是 16BIT的标志位IMAGE_DOS_HEADER 4D 5A(ASC2码就是'MZ')
最后的四个字节是 从文件起始到PE header模块的偏移量.
2) DOS STUB
这一模块没有什么好说的.实际上是个有效的EXE,在不支持 PE文件格式的操作系统中,
它将简单显示一个错误提示,类似于字符串 "This program requires Windows"
3) PE header
这一模块比较重要.包含很多重要的信息(如:支持在什么样的机器上运行,有多少section
是EXE还是DLL等.这个模块的起始地址可由DOS MZ header模块的的最后四个字节读出。
如读到的是 E0 00 00 00则此模块的起始地址是0000000E,这样PE LOADER可根据此地址跳过
DOS STUB直接定位到此模块。
4) section table
PE格式真正的内容都是以section为单位的,section table是一个结构数组,该数组中成员的
个数就是该文件的SECTION个数,由PE header模块读出。每个SECTION对应一个结构其
包含对应节的属性、文件偏移量、虚拟偏移量等。
5) 以下就是各个SECTION的内容了 比如:
.text section 其中包含着代码,所有 OBJ 文件中的代码都被合并到这个section 里。
.data section 中为所有已初始化的数据以及静态的数据;
.bss section 里装的是未初始化的数据;
.rdata section 里包含字符串和常量之类的只读数据还有其它只读结构,如 debug directory(即.pdb 文件的路径,见下文dumpbin /headers xxx.exe文件内容)、 Thread Local Storage (TLS) directory 等等,
.edata section 里保存着从 DLL 中 exported 的函数的信息;(用dumpbin查找了几个DLL,发现竟然没有.edata section,通过查看export directory 发现,export信息被放在了.rdata section。见此文章评论)
.idata section 则保存着从可执行文件/DLL 中的 imported 函数的信息。
.rsrc section 包含着各种资源的数据,比如菜单和对话框。
.reloc section 保存着加载程序时所需的重定位信息。
了解了大概的模块让我们看看PE LOADER的装载顺序:.当PE文件被执行,PE装载器检查DOS MZ header 里的PE header 偏移量。 如果找到,则跳转到PE header。PE装载器检查 PE header 的有效性。如果有效,就跳转到PE header的尾部。紧跟PE header 的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。PE文件映射入内存后,PE装载器将处理PE文件中类似 import table(引入表)逻辑部分。
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://cjbskysea.blogbus.com/logs/74906879.html