NT Optional Header 字段详解

在 PE(Portable Executable)格式中,IMAGE_OPTIONAL_HEADER 扮演着非常重要的角色,它提供了操作系统加载程序时所需的关键信息。

Magic 字段

1
2
3
WORD    Magic;
IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
  • 含义
    Magic 字段用于标识可执行文件是32位还是64位。
    • 对于32位 PE 文件,其值为 0x10bIMAGE_NT_OPTIONAL_HDR32_MAGIC)。
    • 对于64位 PE 文件,其值为 0x20bIMAGE_NT_OPTIONAL_HDR64_MAGIC)。
  • 作用
    加载器通过检测该字段来判断如何解析后续的可选头结构,从而选择正确的数据结构和加载方式。

链接器版本

1
2
3
//链接器的版本  参考使用的VS的版本
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
  • 含义
    这两个字段分别表示链接器的主版本号和次版本号。它们通常反映了编译和链接过程中所使用的 Visual Studio 版本或其他编译工具的版本信息。
  • 作用
    虽然对程序的加载影响不大,但这些版本信息有助于开发者和逆向工程人员了解程序的构建环境,可能在调试和兼容性分析时提供参考。

代码和数据大小字段

1
2
3
DWORD   SizeOfCode;                 //参考,代码总大小
DWORD SizeOfInitializedData; //参考,初始化全局数据区总大小
DWORD SizeOfUninitializedData; //参考,未初始化全局数据区代码总大小
  • SizeOfCode
    • 含义:表示所有代码段(.text节)的总大小。
    • 作用:用于确定在内存中加载代码部分的空间大小。
  • SizeOfInitializedData
    • 含义:表示所有已初始化数据段(如 .data 节)的总大小。
    • 作用:加载器会根据该大小为已初始化的数据分配内存,并将文件中相应的数据复制到内存中。
  • SizeOfUninitializedData
    • 含义:表示所有未初始化数据(通常是 BSS 段)的总大小。
    • 作用:虽然文件中没有存储这部分数据,但加载器会为其分配内存,并通常将其初始化为零。

入口点和代码、数据基地址

1
2
3
4
DWORD   AddressOfEntryPoint;        //重要 EP(Relative Virtual Address)
//Old EntryPoint OEP
DWORD BaseOfCode;
DWORD BaseOfData;
  • AddressOfEntryPoint
    • 含义:指定程序入口点的相对虚拟地址(RVA),即程序开始执行时的入口位置。
    • 作用:加载器在映射可执行文件到内存后,会跳转到这个地址开始执行程序。对于调试、逆向工程以及安全检测来说,该字段至关重要。
  • BaseOfCode
    • 含义:表示代码段在内存中的起始地址(也是一个 RVA)。
    • 作用:帮助加载器确定代码段的内存位置,从而正确加载和执行代码。
  • BaseOfData
    • 含义:表示数据段在内存中的起始地址(RVA),主要适用于32位的 PE 文件(在64位版本中,该字段被省略)。
    • 作用:为已初始化和未初始化数据分配内存时,加载器需要知道数据区的起始位置。

小结

  • Magic 字段:通过 0x10b0x20b 判断 PE 文件的位数,指导加载器使用相应的数据结构。
  • 链接器版本:提供编译环境信息,辅助后续分析和调试。
  • SizeOfCode、SizeOfInitializedData、SizeOfUninitializedData:描述了代码与数据在文件中的大小,为内存分配和文件映射提供依据。
  • AddressOfEntryPoint:指明程序执行入口,是程序启动时最重要的地址信息之一。
  • BaseOfCode 与 BaseOfData:分别标识代码和数据段在内存中的基地址,确保程序在加载时能够正确定位各个部分。