PE文件介绍 (2)-DOS头,DOS存根,NT头
PE头
PE头由许多结构体组成,现在开始逐一学习各结构体
0X00 DOS头
微软创建PE文件格式时,人们正广泛使用DOS文件,所以微软充分考虑了PE文件对DOS文件的兼容性。其结果是在PE头的最前面添加一个 IMAGE_DOS_HEADER 结构体用来扩展DOSEXE头
IMAGE_DOS_HEADER
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic; //DOS签名 4D5A
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew; //指向NT头所在的位置
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
IMAGE_DOS_HEADER 结构体的大小位64字节,一个WORD类型两个字节时一个字,一个LONG类型是四个字节两个字,所以该结构体为 30个WORD类型+ 1个LONG类型 为 64字节。
在该结构体中必须知道2个重要的成员:e_magic 与 e_lfanew
- e_magic: DOS签名(4D5A => ASCLL值 “MZ”)
- e_lfanew: 指示NT头的偏移(不同的文件该值不一样)
0X01 使用Hxd在电脑中查看PE格式
把炉石传说的客户端放入Hxd软件中查看

从图中可以看出标黄的是DOS签名4D5A为MZ,整个红框为 DOS头64个字节,最底下绿色框标出来的为NT文件头所在位置 0X00000120 Intel系列CPU以逆序存储数据,这称为小端序标识法。这些是值被修改后将不能够运行(根据PE规范,它以不再是PE文件)。
0X02 DOS存根
DOS存根在DOS头下面,是个可选项,且大小不固定(即使没有DOS存根,文件也能正常运行)DOS存根由代码与数据混合而成下图为炉石传说的客户端的DOS存根

DOS存根的大小不固定,从0x40开始到NT头截至。图中文件偏移40-4D区域为16位汇编指令。32位windows OS中直接忽略该命令。
0X03 NT头
下面介绍NT头 IMAGE_NT_HEADERS
代码:IMAGE_NT_HEADERS
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //PE签名 504500 => ("PE"00)
IMAGE_FILE_HEADER FileHeader; //文件头
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //可选文件头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
IMAGE_NT_HEADERS 结构体由三个成员组成,第一个成员为签名(Signature)结构体,其值为50450000h("PE"00)。另外两个成员分别为文件头与可选头。
在hxd中查看NT头

从图上可以看出DOS头的最后一个结构是指向NT头的0X0120,0X0120的前4个字节存储的是签名。
IMAGE_NT_HEADERS结构体的大小为F8,相当大。下面分别说明文件头和可选头结构体。
0X030 NT头:文件头
文件头是NT头第二个结构,文件头是表现文件大致属性的 IMAGE_FILE_HEADER
代码:IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
IMAGE_FILE_HEADER 结构体中有一下四种重要成员(若它们设置不正确,将导致文件无法运行)。
(1) Machine
每个CPU都拥有唯一的Machine码,兼容32位Intel x86芯片的Machine码为14C.
是定义在winnt.h文件中的Machine码。
(2) NumberOfSections
PE文件把代码,数据,资源等依据属性分类到各节区中存储。NumberOfSections用来指出文件中存在的节区数量。该值一定要大于0,且当定义的节区数量和实际节区不同时,将发生运行错误。
(3) SizeOfOptionalHeader
IMAGE_NT_HEADERS 结构体的最后一个成员为 IMAGE_OPTIONAL_HEADER32 结构体。SizeOfOptionalHeader 成员用来指出IMAGE_OPTIONAL_HEADER32 结构体的长度。IMAGE_OPTIONAL_HEADER32 结构体由C语言编写而成,故其大小已经确定。但是windows的PE装载器需要查看 IMAGE_NT_HEADERS 的SizeOfOptionalHeader值,从而识别出IMAGE_OPTIONAL_HEADER32 结构体的大小。
PE32+格式的文件中使用的是IMAGE_OPTIONAL_HEADER64 结构体,而不是IMAGE_OPTIONAL_HEADER32 结构体。2个结构体尺寸是不同的,所以需要在SizeOfOptionalHeader 成员中指明结构体的大小。
(4) Characteristics
该字段用于标识文件的属性,文件是否是可运行的形态,是否为DLL文件等信息,以二进制位的方式进行组合。
以下是定义在winnt.h文件中的Characteristics值
| Macro | Value | Meaning |
|---|---|---|
| IMAGE_FILE_RELOCS_STRIPPED | 0x0001 | Relocation information was stripped from the file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error. |
| IMAGE_FILE_EXECUTABLE_IMAGE | 0x0002 | The file is executable (there are no unresolved external references). |
| IMAGE_FILE_LINE_NUMS_STRIPPED | 0x0004 | COFF line numbers were stripped from the file. |
| IMAGE_FILE_LOCAL_SYMS_STRIPPED | 0x0008 | COFF symbol table entries were stripped from file. |
| IMAGE_FILE_AGGRESIVE_WS_TRIM | 0x0010 | Aggressively trim the working set. This value is obsolete. |
| IMAGE_FILE_LARGE_ADDRESS_AWARE | 0x0020 | The application can handle addresses larger than 2 GB. |
| IMAGE_FILE_BYTES_REVERSED_LO | 0x0080 | The bytes of the word are reversed. This flag is obsolete. |
| IMAGE_FILE_32BIT_MACHINE | 0x0100 | The computer supports 32-bit words. |
| IMAGE_FILE_DEBUG_STRIPPED | 0x0200 | Debugging information was removed and stored separately in another file. |
| IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP | 0x0400 | If the image is on removable media, copy it to and run it from the swap file. |
| IMAGE_FILE_NET_RUN_FROM_SWAP | 0x0800 | If the image is on the network, copy it to and run it from the swap file. |
| IMAGE_FILE_SYSTEM | 0x1000 | The image is a system file. |
| IMAGE_FILE_DLL | 0x2000 | The image is a DLL file. While it is an executable file, it cannot be run directly. |
| IMAGE_FILE_UP_SYSTEM_ONLY | 0x4000 | The file should be run only on a uniprocessor computer. |
| IMAGE_FILE_BYTES_REVERSED_HI | 0x8000 | The bytes of the word are reversed. This flag is obsolete. |
另外,PE文件中Characteristics的值有可能不是002h吗(不可执行)?也是有可能的,比如类似*.obj的object文件及resource DLL文件等。
(5) TimeDateStamp
该成员的值不影响文件运行,用来记录编译器创建此文件的时间。有些开发工具(VB,VC++)提供了设置该值的工具。而有些开发工具(Delphi)未提供。
0X031 NT头:使用hxd查看炉石传说客户端文件头

文件头有 四个 WORD 型和三个DWORD型组成 42+34=20 一共占了20个字节
从图上可以看出:
| 名称 | 位置(偏移量) | 数据值 | 含义 |
|---|---|---|---|
| machine码 | 0x0124 | 014C | Interl 386 |
| NumberOfSections | 0x0126 | 0005 | 存在5个节区 |
| TimeDateStamp | 0x0128 | 5B89C5B2 | 2018/08/31 22:48:18 |
| SizeOfOptionalHeader | 0x0134 | 00E0 | IMAGE_OPTIONAL_HEADER32的大小为E0 |
| Characteristics | 0X0136 | 0x0102 | 是32位的文件 and 是可执行文件 |
最后一个数值 0x0102 可以看作是 0x100 | 0x002 为 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE
PE文件介绍 (2)-DOS头,DOS存根,NT头的更多相关文章
- PE文件介绍 (1)
PE文件介绍 PE文件主要是windows操作系统下使用的可执行文件格式,PE文件是指32位的可执行文件也叫做PE32,64位可执行文件叫做PE+或者PE32+ PE文件格式 种类 主扩展名 可执行类 ...
- PE 学习之路 —— DOS 头、NT 头
1. 前述 可执行文件的格式是操作系统本身执行机制的反映,理解它有助于对操作系统的深刻理解,掌握可执行文件的数据结构及其一些机理,是研究软件安全的必修课.`PE(Portable Executable ...
- PE文件格式详解,第二讲,NT头文件格式,以及文件头格式
PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) PS:本篇博客 ...
- 第二讲,NT头文件格式,以及文件头格式
今天详解NT 头格式,以及文件头格式,以及作用, 关于DOS头文件格式,以及DOSStub昨天的博客已经写过了.主要是分散讲解.便于理解. 一丶最小PE的生成,以及标准PE的生成 ps: (如果直接学 ...
- PE文件学习系列二 DOS头分析
合肥程序员群:49313181. 合肥实名程序员群 :128131462 (不愿透露姓名和信息者勿加入)Q Q:408365330 E-Mail:egojit@qq.com PE文件结 ...
- PE文件格式详解,第一讲,DOS头文件格式
PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...
- PE文件学习(1)DOS和NT
大致结构 DOS头和NT头之间通常还有个DOS Stub DOS头 DOS头的作用是兼容MS-DOS操作系统中的可执行文件 一般没啥用 记录着PE头的位置 DOS头定义部分 typedef struc ...
- PE文件学习系列三-PE头详解
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com 最近比较忙 ...
- C/C++ 介绍的PE文件遍历工具
在前面的笔记中,我总结了Pe结构的一些结构含义,并手动编写了几段PE结构遍历代码,这里我直接把之前的C语言代码进行了封装,形成了一个命令行版的PE文件查看工具,该工具只有20kb,但却可以遍历出大部分 ...
随机推荐
- 高版本Jenkins关闭跨站请求伪造保护(CSRF)
前言 根据官网描述,Jenkins版本自2.204.6以来的重大变更有:删除禁用 CSRF 保护的功能. 从较旧版本的 Jenkins 升级的实例将启用 CSRF 保护和设置默认的发行者,如果之前被禁 ...
- Poj 2109 k^n = p.
Poj2109(1)和Poj2109(2)这两种解答都是有漏洞的,就是解不一定存在. 当然这种漏洞的存在取决于出题人是否假设输入的n,p必须默认有kn = p这样的关系存在. 这道题可以详细看http ...
- MySQL创建用户,并设置指定访问数据库
一.创建用户并授权 1. 登录mysql mysql -u root -q输入密码2. 创建数据库(已有数据库就不需要建立) create database newDB;//以创建newDB为例3. ...
- Jumpserver-跳板机的搭建
Jumpserver堡垒机 一.Jumpserver堡垒机概述-部署Jumpserver运行环境 01 跳板机概述 跳板机就是一台服务器,开发或运维人员在维护过程中首先要统一登录到这台服务器,然后再登 ...
- SOFA入门
简介 scalable open financial architecture stack , 可扩展开放的金融架构栈: github: https://github.com/sofastack/so ...
- WebStorm 2019.3.1 破解 永久使用 亲测100%成功
声明:本教程 WebStorm 破解补丁.激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除. 前言 今天问公司前端的美眉,你的激活码哪里来的,她说淘宝买的,我说给我用一下,当时 ...
- PreparedStatement实现针对不同表的通用查询操作
PreparedStatement实现针对不同表的通用查询操作:查询一样和多行 PreparedStatementQueryTest package com.aff.PreparedStatement ...
- 【JVM】堆体系结构及其内存调优
堆体系结构 一个JVM实例只存在一个堆内存,堆内存的大小是可调节的.类加载器读取类文件后,需要把类.方法.常量.变量放在堆内存中,保存所有引用类型的真实信息,以方便执行器指向,堆内存分为三个部分:年轻 ...
- Vue中控制更新的方式
一. 强制更新的实例方法 vm.$forceUpdate() 迫使 Vue 实例重新渲染.注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件. 在没有留意到数组或对象的变更检测注意事 ...
- Rocket - debug - Example: Accessing Registers Using Abstract Command
https://mp.weixin.qq.com/s/RdJzE06mMkh2x__vVj_fEA 介绍riscv debug接口的使用实例:使用抽象命令读取寄存器. 1. Read s0 using ...