IMAGE_NT_HEADERS的结构如下:
IMAGE_NT_HEADERS STRUCT
{
DWORD //PE标志 0x00
IMAGE_FILE_HEADER //文件头 0x04
IMAGE_OPTIONAL_HEADER32 //扩展头 0x18
} IMAGE_NT_HEADERS
其中包含两个子结构体,和一个标志。
1、是以PE00起始位置,是WindowsNT内核下判断可执行文件的唯一有效结构。
2、Signature字段是PE文件头的标识,可以看到他是一个DWORD类型,因此占4个
字节,它是PE开始的标记,对Windows程序这个值始终为0x50450000 (PE00),它对应一个宏为IMAGE_NT_SIGNATURE 。 也就是DOS头的第19个参数 e_lfanew的值所在的位置。
IMAGE_FILE_HEADER 的结构如下:
typedef struct _IMAGE_FILE_HEADER
{
WORD Machine; // 运行平台 <span style="font-family: Arial;"> </span>
WORD NumberOfSections; // 文件的区块数目
DWORD TimeDateStamp; // 文件创建日期和时间
DWORD PointerToSymbolTable; // 指向符号表(主要用于调试)
DWORD NumberOfSymbols; // 符号表中符号个数(同上)
WORD SizeOfOptionalHeader; // IMAGE_OPTIONAL_HEADER32 结构大小
WORD Characteristics; // 文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
NumberOfSection 代表区块的数目,区块表紧跟在IMAGE_NT_HEADERS后面,区块表大概是一个链表结构,链表长度由NumberOfSection的数值决定。
TimeDataStamp 表明文件的创建时间
SizeOfOptionalHeader 是IMAGE_NT_HEADERS的另一个子结构IMAGE_OPTIONAL_HEADER的大小,32位的PE文件这个值一般是00E0,64位的PE文件一般是00F0
Characteristics 代表文件的属性EXE文件一般是0100h DLL文件一般是210Eh,多种属性可以用或运算同时拥有。
IMAGE_OPTIONAL_HEADER结构是对IMAGE_FILE_HEADER的一个补充,如下:
typedef struct _IMAGE_OPTIONAL_HEADER
{
//
// Standard fields.
//
WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
BYTE MajorLinkerVersion; // 链接程序的主版本号
BYTE MinorLinkerVersion; // 链接程序的次版本号
DWORD SizeOfCode; // 所有含代码的节的总大小
DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小
DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小
DWORD AddressOfEntryPoint; // 程序执行入口RVA
DWORD BaseOfCode; // 代码的区块的起始RVA
DWORD BaseOfData; // 数据的区块的起始RVA
//
// NT additional fields. 以下是属于NT结构增加的领域。
//
DWORD ImageBase; // 程序的首选装载地址
DWORD SectionAlignment; // 内存中的区块的对齐大小
DWORD FileAlignment; // 文件中的区块的对齐大小
WORD MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号
WORD MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号
WORD MajorImageVersion; // 可运行于操作系统的主版本号
WORD MinorImageVersion; // 可运行于操作系统的次版本号
WORD MajorSubsystemVersion; // 要求最低子系统版本的主版本号
WORD MinorSubsystemVersion; // 要求最低子系统版本的次版本号
DWORD Win32VersionValue; // 莫须有字段,不被病毒利用的话一般为0
DWORD SizeOfImage; // 映像装入内存后的总尺寸
DWORD SizeOfHeaders; // 所有头+ 区块表的尺寸大小
DWORD CheckSum; // 映像的校检和
WORD Subsystem; // 可执行文件期望的子系统
WORD DllCharacteristics; // DllMain()函数何时被调用,默认为0
DWORD SizeOfStackReserve; // 初始化时的栈大小
DWORD SizeOfStackCommit; // 初始化时实际提交的栈大小
DWORD SizeOfHeapReserve; // 初始化时保留的堆大小
DWORD SizeOfHeapCommit; // 初始化时实际提交的堆大小
DWORD LoaderFlags; // 与调试有关,默认为0
DWORD NumberOfRvaAndSizes; // 下边数据目录的项数,这个字段自Windows NT 发布以来 // 一直是16
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
// 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
ImageBase 指向文件的优先装入地址,一般情况EXE文件不需要重定位,DLL文件可能需要重定位。
SectionAlignment 和FileAlignment 确定了内存中的节对齐单位和在磁盘中的节对齐单位。
DataDirectory 成员是一个比较牛逼的成员,它由16个IMAGE_DATA_DIRCTORY结构组成,用来定义多种不通用处的数据块。这个结构体的内容很简单,只有相对虚拟地址和大小两个成员:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; //相对虚拟地址
DWORD Size; //大小
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
data directory数据目录在WINNT.H中定义为
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 导出表
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 导入表
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 资源目录
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 异常目录
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 安全目录
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 重定位基本表
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 调试目录
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 描术字串
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 机器值
#define IMAGE_DIRECTORY_ENTRY_TLS 9 TLS目录
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 载入配值目录
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 绑定输入表
#define IMAGE_DIRECTORY_ENTRY_IAT 12 导入地址表
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 延迟载入描述
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 COM信息