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,但却可以遍历出大部分 ...
随机推荐
- 给DataTable添加行的几种方式
最近做项目的时候遇到向已有Table中添加另外一个Table中的某一行数据.我是采用这样思路做的: DataTable dtSource = xxxx;//获得的数据源 DataTable dtTar ...
- J2EE项目分类管理中,提交表单数据是二进制形式时,对数据的修改失败。category赋值失败。
原因: 在条件判断时,对字符串的比较进行了错误比较. 解决方法: A==B,比较的是两个字符串是否是同一个对象. A.equal(B),比较的是两个字符串内容是否相同. 出现错误是用了第一种比较,应该 ...
- .net core HttpClient 使用之消息管道解析(二)
一.前言 前面分享了 .net core HttpClient 使用之掉坑解析(一),今天来分享自定义消息处理HttpMessageHandler和PrimaryHttpMessageHandler ...
- [CSharp]传一个包含多个属性的对象,只改变其中个别属性值的方法
需求 假如有这么一个需求,一个对象Person内的属性设置外包给了另外一个类Options, 而要设这个Person对象的属性,就必须传一个Options实例, 但又不能每个属性重新设一遍,只设要修改 ...
- 【PyTorch】深度学习与PyTorch资料链接整理
欢迎来到我的博客! 以下链接均是日常学习,偶然得之,并加以收集整理,感兴趣的朋友可以多多访问和学习.如果以下内容对你有所帮助,不妨转载和分享.(Update on 5,November,2019) 1 ...
- [自动化-脚本]001.自动领淘金币:Anyweb模拟操作
通过模拟手工操作的方法领取淘金币.该方法万能且通用,有能力的还可以自行修改脚本. 工具 软件下载 anywebscript.com 方法/步骤 1.安装软件如图所示 2.设置脚本: (1)进入网站:[ ...
- python pexpect总结
基本使用流程 pexpect 的使用说来说去,就是围绕3个关键命令做操作: 首先用 spawn 来执行一个程序 然后用 expect 来等待指定的关键字,这个关键字是被执行的程序打印到标准输出上面的 ...
- 基于S7-PLCSIM Advanced搭建S7通信仿真环境
写在前面: 之前有专门讲过一期如何搭建西门子PLC的S7通信仿真环境,感兴趣的可以点击查看:戳↓ 1.基于TIA搭建西门子PLC仿真环境及通信方案-联合出品 2.手把手教你搭建西门子PLC仿真环境 那 ...
- WebServer远程部署
通过远程部署获取webshell并不属于代码层次的漏洞,而是属于配置性错误漏洞. 1.Tomcat tomcat是一个jsp/Servlet容器 端口号:8080 攻击方法: 默认口令.弱口令,爆破, ...
- flex布局以及常用属性。
(1)flex布局排列 会消除块状属性,所有与块状相关的属性将失效,比如块状元素会独占一行,如图2,设置flex后会在一行排列