深入学习PE文件结构系列一DOS-Header-DOS-Stub-Rich-Header

admin 2026-02-03 16:53:18 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文系统解析PE文件结构前三部分,以深化攻防基础。文章详述DOSHeader的MZ标识与NT头定位、DOSStub的兼容机制及逆向分析,并介绍非标准RichHeader结构及其在恶意软件伪装与载荷隐藏中的利用价值,为后续开发PE解析器奠定基础。 综合评分: 90 文章分类: 二进制安全,逆向分析,恶意软件,安全开发


cover_image

深入学习PE文件结构系列一DOS-Header-DOS-Stub-Rich-Header

原创

ybdt ybdt

卡卡罗特取西经

2026年2月3日 12:39 吉林

0x1 前言

Windows终端攻防越深入学习,越发现基础的重要性,之前只是零散的学习Windows PE知识,趁着现在工作之余还有时间精力,准备系统的学习下Windows PE,本篇文章开始进入PE文件结构深度学习系列,文章中也会带有一些好玩的逆向,最后会用这些知识实现一个PE Parser,如果你也能跟着这个系列学完,我相信你回头再看PE Loader、PE Packer、PE Injection、Process Hollowing、RDI等等,会有不一样的视角

0x2 PE结构概览

PE全称Portable Executable,是Windows中的可执行文件格式,它基于COFF文件格式(Common Object File Format)修改而来,准确的说PE文件格式是对COFF文件格式的扩展,其中PE File Header部分就是标准的COFF文件格式(后面会提到)

PE文件不只是EXE文件,还有DLL(动态链接库)、SRV(内核模块)、CPL(控制面板项)、等等

一个PE文件需要包含特定的内容,Windows PE Loader才能正确解析它,并将它载入内存,通常的PE文件结构如下图

image

我们用PE-bear打开一个实际的PE文件,可以看到结构如下

image

上图所示,一个PE文件的主要部分包括:DOS Header、DOS Stub、NT Headers、Section Table(我更习惯称之为Section Headers,后面多使用Section Headers)、Section

DOS Header

每个PE文件都以一个64字节大小的结构体开始,这个64字节大小的结构体称之为DOS Header(DOS头),因为它的存在,PE文件也叫MS-DOS可执行文件

DOS Stub

DOS Header之后就是DOS Stub(DOS存根),它从第65个字节开始,是一个兼容MS-DOS 2.0的可执行文件,它的作用就是,当被运行在DOS模式下,输出一个消息”This program cannot be run in DOS mode”,然后退出

NT Headers

NT Headers(NT头)包含3部分:

  1. 1. Image File Signature(镜像文件签名,我更习惯称之为PE File Signature,PE文件签名,后面多使用PE File Signature):一个4字节的内容,标识这是一个PE文件
  2. 2. Image File Header(镜像文件头,我更习惯称之为PE File Header,PE文件头,后面多使用PE File Header):是标准的COFF格式,本质是一个结构体,里面包含PE文件相关信息
  3. 3. Image Optional Header(镜像可选头,我更习惯称之为PE Optional Header,PE可选头,后面多使用PE Optional Header):这部分叫PE可选头是因为像Object File这样的对象文件没有这部分,但像EXE这样的可执行文件必须得有这部分,它可以说是PE文件结构中最重要的部分

Section Table

紧随PE Optional Header之后就是Section Table(节表,我更习惯称之为Section Headers,节头,后面多使用Section Headers),它是一个结构体数组,每个结构体装有特定数据的相关信息,特定数据比如导出表、导入表、重定位表等等

Sections

节是PE文件实际存储数据的地方,包括代码、数据、资源等等

DOS Header

DOS Header是从PE文件起始位置开始的一个64字节大小的结构体,,在Windows中,它的存在只是为了向后兼容,由于它和DOS Stub的存在,使得PE文件也是一个MS-DOS下可执行文件,当它运行在MS-DOS下时,DOS Stub被执行,输出一条消息并退出(PE文件中的其他部分不会被执行),没有它们的话,PE文件在MS-DOS下执行将会报错

DOS Header的结构体定义位于winnt.h中,定义如下

typedef struct _IMAGE_DOS_HEADER {
    WORD   e_magic;
    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;
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

多数字段我们不用关注,只需要关注其中2个字段就可以了

  1. 1. e_magic:DOS头的第一个成员,类型为WORD表示大小是2字节,它有一个固定值0x5A4D,对应的ASCII是”MZ”,它的作用可以理解为MS-DOS下可执行文件标识
  2. 2. e_lfanew:DOS头的最后一个成员,位于DOS Header偏移0x3C处,它中的值是NT Headers的起始地址,PE Loader也是通过它获取真正PE部分的起始地址

下图展示了一个实际PE文件中的DOS Header部分

image

可以看到第一个成员Magic Number的值为0x5A4D,最后一个成员位于DOS Header偏移0x3C处,它中的值0x78正是真正PE部分的起始地址

DOS Stub

DOS Stub本质是一段MS-DOS可执行程序,用来输出一个错误消息并退出,当PE文件运行在DOS模式下,会输出默认消息”This program cannot be run in DOS mode”,提示这个PE文件不能运行在DOS模式下,需要注意,这个消息的内容是可以修改的

DOS Stub不需要了解太多,我们来做点好玩的,试着逆向它

将它从PE-bear中拷贝出来,然后粘贴到010 editor中,并创建一个新的文件,使用IDA打开后可以看到程序的汇编代码

image

如果你学习过Windows16位汇编,你会发现代码并不复杂

push cs
pop ds
  • • 代码段寄存器cs中的值入栈,再将栈顶的值(代码段寄存器cs的值)赋给数据段寄存器ds,也就是说让数据段寄存器的起始地址等于代码段寄存器的起始地址
mov dx, 0eh
mov ah, 9
int 21h
  • • int 21h是DOS下的中断处理(就类似于Windows下的API调用),具体执行哪种类型的中断处理(API调用)取决于ah中的值,这里给ah赋值的9表示执行输出到屏幕功能,而输出的内容就是dx中的值,将0eh赋值给dx就是将那个字符串的地址赋值给dx
mov ax, 4c01h
int 21h
  • • 这两个语句也同理,0x4c表示的含义是退出函数,放在ax的高16位ah中,0x01表示函数退出代码,放在ax的低16位al中,所以ax的值是0x4c01,结合到一起,执行退出函数的中断处理,并返回值1

完整的DOS API调用参考可以查看这里:https://en.wikipedia.org/wiki/DOS_API

Rich Header

在DOS Stub和NT Headers之间,其实还有一段数据,叫Rich Header(富有头),通常使用微软Visual Studio构建的exe才会有这个头,里面的数据用于表示VS的名字、类型、版本等等

很多讲述PE文件结构的文章都没有提到这个头,其实Rich Header并不是PE文件的标准内容,就是说,将这部分完全填充为0也不会影响PE文件,说到这里有没有想到什么?我们可以将PE文件内嵌的内容除了放到资源节,还可以放到这里,其实已经有恶意软件这么做了

在2018年冬奥会期间有一款名为Olympic Destroyer的恶意软件,这款恶意软件以伪造其他恶意软件而闻名,比如在Rich Header中伪造Lazarus threat group组织的特征,具体分析可参考:https://securelist.com/the-devils-in-the-rich-header/84348/

Rich Header中首先是一系列异或加密的数据,然后是Rich Header签名,最后是一个校验值,这个校验值也是异或加密的密钥

下图中可以看到Rich Header中主要是微软VS编译工具的相关信息

image


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:卡卡罗特取西经 ybdt ybdt《深入学习PE文件结构系列一DOS-Header-DOS-Stub-Rich-Header》

网安新年专属祝福图直取 网络安全文章

网安新年专属祝福图直取

文章总结: 本文主要分享网络安全领域的新年专属祝福图片,内容多为展示性质。文末附带了往期文章链接及二维码,旨在邀请读者加入吃瓜交流群进行互动与交流。整体属于社群
评论:0   参与:  0