PEview小工具
参考链接
https://blog.csdn.net/qq_43633973/article/details/102378477
https://blog.csdn.net/freeking101/article/details/102752048
//本篇blog基本上90%摘抄以上链接,本blog作为备份学习资料使用
https://www.cnblogs.com/findumars/p/5037657.html
PE结构
首先,了解一个文件的格式,最重要的是先看文件头的含义,因为几乎所有的文件格式,重要的信息都包含在头部,顺着头部的信息,可以引导系统解析整个文件
1.什么是PE文件
PE文件是Portable Executable(可移植的可执行文件)的简写。常见的有EXE、DLL、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的可执行文件的总称。它是微软在UNIX平台上的COFF(通用对象文件格式)基础上制作而成的。最初设计是用来提高程序在不同操作系统上的移植性,但实际上这种文件格式仅用在Windows系列操作系统下。
2.基础名词
名称 | 描述 |
---|---|
地址 | 是虚拟地址而不是物理地址。为什么不是“物理地址”呢?因为数据在内存的位置经常在变,这样可以节省内存开支、避开错误的内存位置等的优势。同时用户并不需要知道具体的“真实地址”,因为系统自己会为程序准备好内存空间的(只要内存足够大) |
镜像文件 | 包含以 EXE 文件为代表的 “可执行文件”、以DLL文件为代表的“动态链接库”。为什么用“镜像”?这是因为他们常常被直接“复制”到内存,有“镜像”的某种意思。 |
RVA | 英文全称 Relatively Virtual Address。偏移(又称“相对虚拟地址”)。相对镜像基址的偏移。 |
节 | 节是PE文件中代码或数据的基本单元。原则上讲,节只分为 “代码节” 和 “数据节” 。 |
VA | 英文全称 Virtual Address。基址 |
3.PE结构
事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是任何扩展名。那 Windows 是怎么区分可执行文件和非可执行文件的呢?我们调用LoadLibrary传递了一个文件名,系统是如何判断这个文件是一个合法的动态库呢?这就涉及到PE文件结构了。
PE文件的结构一般来说如下所示:
从起始位置开始依次是DOS头,NT头,节表,及具体的节
用PEview.exe打开一个本地测试程序看一下效果如果:
4.PE文件结构说明
(1)什么是DOS头?
DOS头是用来兼容MS-DOS操作系统的,目的是当这个文件在MS-DOS上运行时提示一段文字,大部分情况下是:This program cannot be run in DOS mode. 还有一个目的,就是指明NT头在文件中的位置。
PE文件头部中的DOS头分为MZ文件头和DOS块(也叫Header和DOS存根),分别对应的是IMAGE_DOS_HEADER和MS-DOS Stub Program。
IMAGE_DOS_HEADER是干嘛的?
Header 结构 (00000000 - 0000003F,共 64 个字节)
1 |
|
DOS块是干嘛的?
DOS存根(00000040 - 000000BF,共128字节)
MS-DOS stub Program中包含了一个字符串,
当PE文件在DOS环境下运行时,就会显示该字符串,来提示用户PE程序必须在Windows下才能运行。
DOS存根则是一段简单的DOS程序,主要用来输出类似“This program cannot be run in DOS mode.”的提示语句。即使没有DOS存根,程序也能正常执行。
(2)NT头
PE最重要的头,由DOS头中的e_lfanew决定 ,表示DOS头之后的NT头相对文件起始地址的偏移
文件头的结构:
具体结构代码:
1 |
|
NumberOfSections参数含义具体可以看图示例:
Characteristics参数每一位具体的属性含义如下
数据位 | 每一个bit位的含义 |
---|---|
Bit 0 | 置1表示文件中没有重定向信息。每个段都有它们自己的重定向信息。这个标志在可执行文件中没有使用,在可执行文件中是用一个叫做基址重定向目录表来表示重定向信息的。 |
Bit 1 | 置1表示该文件是可执行文件(也就是说不是一个目标文件或库文件) |
Bit 2 | 置1表示没有行数信息;在可执行文件中没有使用。 |
Bit 3 | 置1表示没有局部符号信息;在可执行文件中没有使用。 |
Bit 7 | 置1表示小尾方式 |
Bit 8 | 表示希望机器为32位机。这个值永远为1。 |
Bit 9 | 表示没有调试信息,在可执行文件中没有使用。 |
Bit 10 | 置1表示该程序不能运行于可移动介质中(如软驱或CD-ROM)。在这种情下,OS必须把文件拷贝到交换文件中执行。 |
Bit 11 | 置1表示程序不能在网上运行。在这种情况下,OS必须把文件拷贝到交换文件中执行。 |
Bit 12 | 置1表示文件是一个系统文件例如驱动程序。在可执行文件中没有使用。 |
Bit 13 | 置1表示文件是一个动态链接库(DLL)。 |
Bit 14 | 置1表示文件被设计成不能运行于多处理器系统中。 |
Bit 15 | 置1表示大尾方式,表示文件的字节顺序如果不是机器所期望的,那么在读出之前要进行交换。在可执行文件中它们是不可信的(操作系统期望按正确的字节顺序执行程序)。 |
5.PE文件的执行顺序
有以下四个步骤
(1)当一个 PE 文件被执行时,PE装载器首先检查DOS header里的PE header的偏移量。如果找到,则直接跳转到PE header的位置。
(2)当PE装载器跳转到PE header后,第二步要做的就是检查PE header是否有效。如果该PE header有效,就跳转到PE header的尾部。
(3)紧跟PE header尾部的是节表。PE装载器执行完第二步后开始读取节表中的节段信息,并采用文件映射(在执行一个PE文件的时候,Windows并不在一开始就将整个文件读入内存,而是采用与内存映射的机制,也就是说,Windows装载器在装载的时候仅仅建立好虚拟地址和PE文件之间的映射关系,只有真正执行到某个内存页中的指令或者访问某一页中的数据时,这个页面才会被从磁盘提交到物理内存,这种机制使文件装入的速度和文件大小没有太大的关系)的方法将这些节段映射到内存,同时附上节表里指定节段的读写属性。
(4)PE文件映射入内存后,PE装载器将继续处理PE文件中类似import table(输入表)的逻辑部分。