PE文件结构-DOS头部&DOS stub

admin 2024年12月3日12:54:48评论1 views字数 4823阅读16分4秒阅读模式

    PE文件格式(Portable Executable File)是Windows操作系统下可执行文件使用的一种文件格式,广泛用于存储可执行程序(EXE文件)、动态链接库(DLL文件)、驱动程序(SYS文件)以及其他类型的程序代码,它是Windows应用程序的基本运行单元。PE文件结构是经过精心设计的,以支持程序在不同版本的Windows操作系统上能够移植、执行,并能与操作系统的加载机制和动态链接功能兼容。

事实上,在Windows上,文件的拓展名并不直接决定文件是否是PE(Portable Executable)文件;PE文件的识别主要是通过其文件头(特别是DOS头和PE头)来确定,而不是文件的拓展名。拓展名只是用来帮助用户和操作系统识别文件类型的,并不能确定文件的内部格式。

PE 文件作为 Windows 操作系统下的标准可执行文件格式,它在逆向工程、安全研究、免杀技术和病毒分析中扮演着至关重要的角色,理解 PE 文件结构对于逆向分析、恶意软件分析、漏洞研究以及开发反病毒技术具有重要意义。

PE文件结构

PE文件格式包含多个部分,主要包括:

DOS头部 (DOS Header)、PE头部 (PE Header):文件头 (File Header)、可选头 (Optional Header)、节区表 (Section Table)、节区数据 (Section Data):各个节区的内容,如代码、数据、资源等、资源部分 (Resources)、重定位表 (Relocation Table)、导入表 (Import Table)、导出表 (Export Table)、TLS表 (Thread Local Storage)、调试信息 (Debug Information)、符号表 (Symbol Table)、异常处理表 (Exception Handling Table)

本篇文章主要针对PE文件结构中的DOS头部进行介绍。首先我们写一个简单程序,以供我们后续进行PE文件结构学习过程中使用。

#include <iostream>
#include <windows.h>

#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) // 设置入口地址;隐藏程序黑窗口
int main() {
    MessageBox(NULL, "Hello Wolven", "Hey", MB_HELP);
    return 0;
}
代码解释
#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) // 设置入口地址

这行代码是一个 编译器指令,用于在 Windows 平台上设置程序的 子系统类型入口点。具体来说,这行代码使用 #pragma comment 来传递链接器指令,从而影响编译过程中的链接设置。

#pragma comment(linker, ...):这是一个编译器指令,它向链接器传递命令。在这里,linker 表示这条命令将传递给链接器,而不是编译器。链接器是负责将目标文件(.obj 文件)合并并生成最终可执行文件(.exe)的工具。/subsystem:"windows":这部分告诉链接器,生成的程序是一个 Windows GUI 应用程序,而不是一个 控制台应用程序。这样,程序不会显示控制台窗口(黑窗口)。/entry:"mainCRTStartup":该部分告诉链接器使用 mainCRTStartup 作为程序的入口点。mainCRTStartup 是 C 运行时(CRTC Runtime)库的入口点,用于初始化程序(包括设置堆栈、初始化 C 库等)。

MessageBox 是一个用于在 Windows 操作系统中显示消息框的函数。其原型如下:

int MessageBox(
 HWND hWnd,       // 父窗口句柄
 LPCSTR lpText,   // 消息框中显示的文本内容
 LPCSTR lpCaption,// 消息框的标题栏文本
 UINT uType       // 消息框的样式
);

接着右击项目,生成程序;

PE文件结构-DOS头部&DOS stub

并在同一个菜单中,选择在文件资源管理器中打开文件夹;找到生成的程序,可以看到最后程序执行的结果如下:

PE文件结构-DOS头部&DOS stub

DOS 头部

PE文件中的DOS头部(DOS Header)是PE文件的最前端部分,虽然它在现代Windows操作系统中已经基本没有实际用途,但它仍然保留在文件格式中,以保持向后兼容性;DOS头部位于PE文件的开头,通常为 64 字节。Windows 95及之前的版本中,该部分是DOS程序的入口点,为了兼容性,DOS头部仍然保留至今。

在Visual Studio中查看DOS头部结构

打开Visual Studio,打开任意可以编写代码的文件,写入结构体类型:_IMAGE_DOS_HEADER

PE文件结构-DOS头部&DOS stub

接着按下ctrl的同时点击该结构体进行结构查看:即可看到DOS头部的具体结构。

PE文件结构-DOS头部&DOS stub

完整结构如下:

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
   WORD   e_magic;                     // Magic number
   WORD   e_cblp;                      // Bytes on last page of file
   WORD   e_cp;                        // Pages in file
   WORD   e_crlc;                      // Relocations
   WORD   e_cparhdr;                   // Size of header in paragraphs
   WORD   e_minalloc;                  // Minimum extra paragraphs needed
   WORD   e_maxalloc;                  // Maximum extra paragraphs needed
   WORD   e_ss;                        // Initial (relative) SS value
   WORD   e_sp;                        // Initial SP value
   WORD   e_csum;                      // Checksum
   WORD   e_ip;                        // Initial IP value
   WORD   e_cs;                        // Initial (relative) CS value
   WORD   e_lfarlc;                    // File address of relocation table
   WORD   e_ovno;                      // Overlay number
   WORD   e_res[4];                    // Reserved words
   WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
   WORD   e_oeminfo;                   // OEM information; e_oemid specific
   WORD   e_res2[10];                  // Reserved words
   LONG   e_lfanew;                    // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

DOS头部中两个比较重要的成员:e_magic(Magic number)e_lfanew(File address of new exe header)

e_magic(Magic Number)
DOS头部的Magic number 0x5A4D(ASCII字符M和Z)是PE文件格式的一部分,它作为历史遗留的标识符,表示该文件最初为一个可执行的DOS程序;这使得早期的操作系统能够识别文件类型并正确加载。但在现代的Windows系统中,它并不再代表DOS文件本身,而是作为PE文件格式的一部分来保持兼容性。
e_lfanew(File address of new exe header)
在DOS头中,e_lfanew字段的大小是4个字节,存储了一个文件偏移地址,指示PE头在文件中的位置。在PE文件中,DOS头的主要作用是提供一些基本的历史兼容性信息,尤其是对老旧的DOS程序的支持。在现代的PE文件中,DOS头的主要作用是作为一个指向PE头部的引导,e_lfanew字段就起到了这一作用。

在现代操作系统中,DOS头部的作用主要是为了向后兼容,当Windows试图加载一个PE文件时,如果该文件是一个有效的PE文件,它会首先检测DOS头部;操作系统会检查 e_magic 字段是否为 MZ,如果是,操作系统就会继续检查 e_lfanew 字段,它指向的是实际的PE头部。除了e_magice_lfanew之外 DOS头部的其他字段大多数已经不再被使用,但它们依然保留在PE文件格式中,主要是为了向后兼容早期的DOS操作系统。

那么这个时候如果我们修改这些字段会怎么样呢?这个时候我们可以将刚刚生成的程序拖入010 Editor中进行查看。(关于010 Editor的注册/破解请转到文章末尾)

010 Editor 是一款功能强大的十六进制编辑器和二进制文件分析工具,广泛应用于数据分析、逆向工程、调试、文件格式分析等领域、010 Editor 提供了高效的十六进制查看和编辑功能,可以直接编辑二进制文件的每个字节。支持多种文件类型的二进制内容显示,适用于分析各种文件格式。

PE文件结构-DOS头部&DOS stub

接着我们就可以根据上述代码中各个字段的大小去识别010 Editor中的PE文件结构中DOS头部的内容,如:e_magic字段类型为WORD(两个字节),那么我们就可以知道4D 5A(小端序)就是标识e_magic字段:

PE文件结构-DOS头部&DOS stub

e_magic字段后的17个大多数已经不再被使用的字段,在17个不再使用的字段中包含了两个数组e_res[4]e_res2[10]所以这个时候不用的字段总大小则为:

15*word + 4*word + 10*word = 29*word

这个时候我们实际上可以全部用CC字符进行修改以及填充:

PE文件结构-DOS头部&DOS stub

修改后我们可以再次尝试运行程序;发现程序运行成果,因而发现程序运行并不会被这些字段影响。

PE文件结构-DOS头部&DOS stub

最后则是DOS头部的最后一个字段也就是指向PE头部的e_lfanew字段,它的大小为4字节(LONG类型):

LONG   e_lfanew;

010 Editor中查看到其位置以及值如下图所示:

PE文件结构-DOS头部&DOS stub

这边需要注意,在Windows中,字段的值是以小端序形式进行存储的,所以显示的值为00 01 00 00实际则是00 00 01 00

那么关于这个正在使用的字段,我们可以尝试修改它的值,并观察程序在该字段被修改后还能否正常运行:这边我们将该字段的值全部以CC进行填充。

PE文件结构-DOS头部&DOS stub

接着运行程序后发现,此时程序无法正常运行;由此可知这个字段是不可以随意修改的。

PE文件结构-DOS头部&DOS stub

到此DOS头部就基本上讲述完毕,那么这边存在一个问题,也就是在DOS头部和PE头部之间存在着一段间隙:

PE文件结构-DOS头部&DOS stub

在中文中,这段位于 DOS头部 和 PE头部 之间的代码间隙通常被称为 DOS存根或DOS Stub,有时也称为 MZ存根

DOS Stub 是一个简单的程序,在现代操作系统下通常没有实际作用,但它用于在 DOS 环境中尝试运行 PE 文件时提供提示信息。其目的是告诉用户该程序不能在 DOS 环境下运行。包含了一段小的代码,通常会显示像 "This program cannot be run in DOS mode" 这样的消息。

PE文件结构-DOS头部&DOS stub

同样的,我们对DOS stub中的值进行随意修改,此处还是以CC进行填充:

PE文件结构-DOS头部&DOS stub

接着运行程序,发现程序依旧能够正常运行。

PE文件结构-DOS头部&DOS stub

这也直接说明了在现代操作系统中,这段 DOS Stub通常没有实际作用,只是一个为了兼容早期DOS系统而保留的部分。

【注】关注公众号,回复[010]获取破解版010 Editor。

原文始发于微信公众号(风铃Sec):PE文件结构-DOS头部&DOS stub

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月3日12:54:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PE文件结构-DOS头部&DOS stubhttps://cn-sec.com/archives/3453936.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息