pe文件系统中的dos头,pe头

简单来说:

  1. DOS 头是历史的产物,它的唯一使命是引导系统找到 PE 头

  2. PE 头是文件的总说明书和目录,它告诉操作系统:

    • 这个文件是给什么 CPU 的(文件头)。

    • 它有多少个部分(文件头)。

    • 从哪里开始执行(可选头)。

    • 它想被加载到内存的哪个位置(可选头)。

    • 它依赖哪些外部函数(可选头中的导入表)。

    • 它的图标、界面等资源在哪里(可选头中的资源表)。

理解这两个头是分析、调试、逆向或开发 Windows 程序的基础。

1. DOS头 (DOS Stub / DOS Header)

这是PE文件最起始的部分,主要是为了向后兼容古老的MS-DOS操作系统。

  • 历史原因:当你在MS-DOS系统中运行一个Windows程序时,DOS需要能识别它,并显示一句提示信息(如“此程序不能在DOS模式下运行”),而不是直接崩溃。DOS头就是为此而设。

  • 结构:它是一个标准的IMAGE_DOS_HEADER结构体,长度固定为64字节

  • 关键字段

    • e_magic (WORD): DOS签名,固定为0x5A4D,即 ASCII 字符 MZ(Mark Zbikowski,早期DOS开发者)。这是识别文件是否为有效PE文件的第一个标志。

    • e_lfanew (DWORD): 这是整个DOS头中最关键的字段。它存储了一个偏移量(从文件开头算起),指向真正的PE文件头(即IMAGE_NT_HEADERS)的位置。通过这个值,程序可以跳过DOS Stub,直接定位到PE核心内容。

  • DOS Stub:紧跟在IMAGE_DOS_HEADER后面的是一小段可执行的DOS代码和一段提示字符串。在现代操作系统中,这段代码不会被执行(除非你在DOS下运行)。它的存在就是为了兼容性。

作用总结:DOS头是一个“兼容性桥梁”,e_lfanew是这座桥上指向PE核心区域的路标


2. PE头 (PE Header / IMAGE_NT_HEADERS)

这是PE文件的核心元数据区,包含了让Windows加载器正确加载和执行该文件的所有关键信息。它位于由e_lfanew指向的位置。

PE头本身是一个大结构体IMAGE_NT_HEADERS,它又包含三个部分:

a) PE签名 (Signature)
  • Signature (DWORD): PE文件标识,固定为0x00004550,即 ASCII 字符 PE\0\0。这是识别PE文件的第二个、也是最重要的标志。加载器会检查此处是否为“PE”。

b) 文件头 (File Header - IMAGE_FILE_HEADER)

这是一个固定长度的结构体,描述了文件的基本属性。

  • Machine (WORD): 目标CPU架构。例如,0x014C 代表 Intel i386(32位),0x8664 代表 x64,0xAA64 代表 ARM64。

  • NumberOfSections (WORD): 区段的数量。指明了后面紧跟着的“区段表”中有多少个条目(例如.text, .data, .rdata等)。这是解析文件的关键。

  • TimeDateStamp (DWORD): 文件创建的时间戳。

  • PointerToSymbolTable, NumberOfSymbols: 调试信息相关,现代工具链已较少使用。

  • SizeOfOptionalHeader (WORD): 可选头的大小。非常重要,因为它指明了接下来的IMAGE_OPTIONAL_HEADER结构有多大。

  • Characteristics (WORD): 文件属性标志位。例如,是DLL还是EXE,是否是可执行的,是否支持32位机等。

c) 可选头 (Optional Header - IMAGE_OPTIONAL_HEADER32/64)

虽然叫“可选”,但对于可执行文件(EXE/DLL)来说它是必须存在的。它包含了加载和运行程序所需的大部分关键信息。其结构分为32位和64位版本。

  • 关键字段

    • Magic (WORD): 标识可选头类型。0x10B 代表 PE32(32位),0x20B 代表 PE32+(64位)。

    • AddressOfEntryPoint (DWORD): 程序入口点(RVA)。这是加载器完成所有准备工作后,开始执行代码的地址(相对于加载基址的偏移)。

    • ImageBase (DWORD/DWORD64): 优先加载基址。EXE/DLL希望被加载到的内存地址。对于DLL,如果此地址被占用,则需进行“重定位”。

    • SectionAlignment, FileAlignment: 内存对齐文件对齐粒度。例如,内存对齐通常为0x1000(4KB),文件对齐可能为0x200(512字节)。

    • SizeOfImage (DWORD): 加载到内存后整个映像的大小。是所有区段按内存对齐后的大小总和。

    • SizeOfHeaders (DWORD): 所有头(DOS头+PE头+区段表)的总大小,通常也是文件中第一个区段起始位置的偏移量。

    • Subsystem (WORD): 子系统类型。例如,1 为Native驱动,2 为GUI图形界面,3 为CUI控制台。

    • NumberOfRvaAndSizes, DataDirectory (数组): 数据目录表。这是极其重要的部分。它是一个有16个元素的数组,每个元素是一个IMAGE_DATA_DIRECTORY结构(包含虚拟地址和大小),指向各种关键数据结构的RVA。例如:

      • 导出表

      • 导入表

      • 资源表

      • 重定位表

      • 基址重定位表

      • TLS表

      • 等...


总结与关系图

plaintext

文件起始 (0x0)
├── **IMAGE_DOS_HEADER (64字节)**
│    ├── e_magic: "MZ" (0x5A4D) // DOS签名
│    └── e_lfanew: 0x000000E0   // **指向PE头的偏移**
│
├── **DOS Stub** (一小段DOS代码和提示信息)
│
└── **IMAGE_NT_HEADERS** (起始于 e_lfanew 指向的位置)
     ├── Signature: "PE\0\0" (0x00004550) // **PE签名**
     ├── **IMAGE_FILE_HEADER** (文件头)
     │    ├── Machine: 0x014C
     │    ├── NumberOfSections: 0x0005
     │    └── SizeOfOptionalHeader: 0x00E0
     │
     └── **IMAGE_OPTIONAL_HEADER** (可选头 - 核心)
          ├── Magic: 0x010B
          ├── AddressOfEntryPoint: 0x00001234
          ├── ImageBase: 0x00400000
          ├── ...
          └── **DataDirectory[16]** // **数据目录,定位各种表**
               ├── [0] 导出表 RVA & Size
               ├── [1] 导入表 RVA & Size  <- **加载器找DLL函数的关键**
               └── ...
​
紧跟PE头之后的就是 **区段表 (Section Table)**,然后是实际的 **区段数据**(如 .text, .data)。

把PE文件想象成一栋大楼(后面有简化版)

1. DOS头 - 大楼的老式门牌(为了照顾老居民)

想象这栋楼建于80年代,当时街道编号还是旧系统。现在楼门口还保留着:

  • 门口有个牌子写着"MZ"

    • 就像老式门牌号,告诉老DOS系统:“这里确实有栋楼”

  • 牌子上最关键的一句话: “真正的地址簿在楼内第188步的位置

    • 这就是e_lfanew!它是个指针,告诉你怎么找到大楼真正的重要信息

  • 门口还有个老式信箱

    • 里面是DOS Stub,一段古老的文字:“本大楼需要Windows系统才能进入”

    • 纯粹为了历史兼容性,现在基本用不上

一句话记DOS头:它就是个“指路牌”,主要作用是告诉你PE头在哪里。


2. PE头 - 大楼的总控制室

跟着DOS头指的路,你来到了大楼的总控室。这里有三样核心文件:

a) 身份认证(PE签名)
  • 墙上挂着金色大字:“PE”

  • 这是大楼的身份证明:“没错,我就是PE大楼”

b) 大楼基本信息卡(文件头)

像大楼的房产证:

text

[ 大楼基本信息 ]
建筑类型:32位/64位  ✓
楼层数(区段数):5层  ✓
大楼设计图纸大小:224页  ✓
特点:可执行、支持调试、非DLL  ✓

关键数字NumberOfSections(楼层数)告诉你有多少层(区段),决定了后面要看几张楼层图纸。

c) 大楼使用手册(可选头)

这是最重要的文件!告诉你怎么使用这栋楼:

text

=== 大楼核心信息 ===
1. 大楼首层入口:0x1234号房间  
   (AddressOfEntryPoint - 程序开始执行的地方)
​
2. 理想地基地址:0x400000  
   (ImageBase - 大楼希望建在内存的这个位置)
​
3. 大楼内存占地面积:0x28000平方米  
   (SizeOfImage - 加载到内存后占多大)
​
4. 各楼层对齐方式:
   文件里:每512字节对齐
   内存中:每4096字节对齐
​
5. 大楼类型:带图形界面  
   (Subsystem - GUI还是控制台)

d) 大楼功能索引表(数据目录)

这是手册中最有用的部分!像大楼的“各部门电话簿”:

text

[ 快速联系表 ]
1. 出口部(导出表):负责对外服务
2. 进口部(导入表):需要哪些外部DLL帮助  
3. 资源部(资源表):图标、图片、文字等
4. 搬家部(重定位表):如果地基被占,如何调整
5. 安全部(安全证书):数字签名
...
(共16个重要部门)

这个索引表是加载器的导航地图!比如要找DLL函数(进口部),就查第2项。

简化版例子

整个PE文件 = 一栋智能大楼

  1. DOS头 = 门口的老式信箱和指路牌

    • 主要是为了照顾还能用DOS的老人

    • 关键信息:“去大楼总控室怎么走”(e_lfanew

  2. PE头 = 大楼总控室

    • 门口挂牌:“PE大楼”(PE签名)

    • 房产证:几层楼、什么结构(文件头)

    • 使用手册:入口在哪、占多大地方(可选头)

    • 电话簿:各部门联系表(数据目录)

  3. 之后的内容 = 大楼各楼层

    • .text层 = 代码层(员工办公区)

    • .data层 = 数据层(仓库)

    • .rsrc层 = 资源层(装修材料库)

加载器如何看这栋楼

Windows加载器就像大楼管理员:

  1. 走到门口:看到“MZ”牌子,知道这是栋楼

  2. 看指路牌:按e_lfanew找到总控室

  3. 进总控室

    • 看到“PE”招牌,确认是PE大楼

    • 翻房产证:哦,有5层楼

    • 看使用手册:入口在0x1234,希望建在0x400000

    • 查电话簿:需要找哪些外部DLL(进口部)

  4. 开始搬楼:按手册把各楼层放进内存合适位置

  5. 按门铃:走到入口地址0x1234,敲门:“程序,开始运行吧!”

这个是完整源码 python实现 Flask,Vue 【python毕业设计】基于Python的Flask+Vue物业管理系统 源码+论文+sql脚本 完整版 数据库是mysql 本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发展随后依照传统的软件开发流程,最先为系统挑选适用的言语和软件开发平台,依据需求分析开展控制模块制做和数据库查询构造设计,随后依据系统整体功能模块的设计,制作系统的功能模块图、E-R图。随后,设计框架,依据设计的框架撰写编码,完成系统的每个功能模块。最终,对基本系统开展了检测,包含软件性能测试、单元测试和性能指标。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。本文首先实现了基于Python的Flask+Vue物业管理系统技术的发
源码地址: https://pan.quark.cn/s/a4b39357ea24 # SerialAssistant串口助手 下载地址: 本仓库release文件夹 在线下载:http://mculover666.cn/SerialAssistant.zip 功能说明 本项目是使用C# + WinForm框架编写的串口助手。 目前版本为2.0.0版本,拥有以下功能: 未打开串口时,自动扫描可用端口 接收数据支持文本或者HEX方式显示 支持接收数据加入时间戳 支持将当前接收数据保存为文件 支持发送文本数据或HEX数据 支持自动定时发送数据 支持从文件中(.txt, .json)加载数据到发送文本框 支持发送数据记录(不重复记录) ……欢迎加入更多功能 环境说明 VS2019 .NET Framework 4.5 教程 C#上位机开发(一)—— 了解上位机 C#上位机开发(二)—— Hello,World C#上位机开发(三)—— 构建SerialAssistant雏形 C#上位机开发(四)—— SerialAssistant功能完善 C#上位机开发(五)——SerialAssistant界面升级(WinForm界面布局进阶) C#上位机开发(六)——SerialAssistant功能优化(串口自动扫描功能、接收数据保存功能、加载发送文件、发送历史记录、打开浏览器功能、定时发送功能) C#上位机开发(七)—— 修改窗口图标和exe文件图标 C#上位机开发(八)—— 美化界面(给按钮添加背景) 更新日志 2018/6/3 完成串口属性设置,打开与关闭异常处理; 字符串发送功能; 字符串接收功能; 2018/6/4 完善串口扩展功能界面部分 2018/6/6 完善...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值