PE文件主要涉及的数据结构:
MS-DOS头占据PE文件的头64(0x40)个字节。反映它的内容的一个结构如下所述:
WINNT.H
typedef struct _IMAGE_DOS_HEADER { // DOS下的.EXE文件头
USHORT e_magic; // 魔数
USHORT e_cblp; // 文件最后一页的字节数
USHORT e_cp; // 文件的页数
USHORT e_crlc; // 重定位
USHORT e_cparhdr; // 段中头的大小
USHORT e_minalloc; // 需要的最少额外段
USHORT e_maxalloc; // 需要的最多额外段
USHORT e_ss; // 初始的(相对的)SS寄存器值
USHORT e_sp; // 初始的SP寄存器值
USHORT e_csum; // 校验和
USHORT e_ip; // 初始的IP寄存器值
USHORT e_cs; // 初始的(相对的)CS寄存器值
USHORT e_lfarlc; // 重定位表在文件中的地址
USHORT e_ovno; // 交叠数
USHORT e_res[4]; // 保留字
USHORT e_oemid; // OEM识别符(用于e_oeminfo成员)
USHORT e_oeminfo; // OEM信息; e_oemid中指定的
USHORT e_res2[10]; // 保留字
LONG e_lfanew; // 新exe头在文件中的地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
其中最后一个e_lfanew最为重要,它指出了IMAGE_NT_HEADER的文件内偏移,帮助我们读取IMAGE_NT_HEADER.
下来就是PE头了:
PE header 实际就是一个 IMAGE_NT_HEADERS 结构。定义如下:
IMAGE_NT_HEADERS STRUCT
Signature dd ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS
typedef struct _IMAGE_FILE_HEADER {
USHORT Machine; //机器
USHORT NumberOfSections; //节数
ULONG TimeDateStamp; //时间日期戳
ULONG PointerToSymbolTable; //符号表指针
ULONG NumberOfSymbols; //符号数
USHORT SizeOfOptionalHeader; //可选头的大小
USHORT Characteristics; //特性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
//
//标准域
//
USHORT Magic; //魔数
UCHAR MajorLinkerVersion; //链接器主版本号
UCHAR MinorLinkerVersion; //链接器小版本号
ULONG SizeOfCode; //代码大小
ULONG SizeOfInitializedData; //已初始化数据大小
ULONG SizeOfUninitializedData; //未初始化数据大小
ULONG AddressOfEntryPoint; //入口点地址
ULONG BaseOfCode; //代码基址
ULONG BaseOfData; //数据基址
//
//NT增加的域
//
ULONG ImageBase; //映像文件基址
ULONG SectionAlignment; //节对齐
ULONG FileAlignment; //文件对齐
USHORT MajorOperatingSystemVersion;//操作系统主版本号
USHORT MinorOperatingSystemVersion;//操作系统小版本号
USHORT MajorImageVersion; //映像文件主版本号
USHORT MinorImageVersion; //映像文件小版本号
USHORT MajorSubsystemVersion; //子系统主版本号
USHORT MinorSubsystemVersion; //子系统小版本号
ULONG Reserved1; //保留项1
ULONG SizeOfImage; //映像文件大小
ULONG SizeOfHeaders; //所有头的大小
ULONG CheckSum; //校验和
USHORT Subsystem; //子系统
USHORT DllCharacteristics; //DLL特性
ULONG SizeOfStackReserve; //保留栈的大小
ULONG SizeOfStackCommit; //指定栈的大小
ULONG SizeOfHeapReserve; //保留堆的大小
ULONG SizeOfHeapCommit; //指定堆的大小
ULONG LoaderFlags; //加载器标志
ULONG NumberOfRvaAndSizes; //RVA的数量和大小
IMAGE_DATA_DIRECTORY DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //数据目录数组
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
每个节的数据结构:
typedef struct _IMAGE_SECTION_HEADER {
UCHAR Name[IMAGE_SIZEOF_SHORT_NAME]; //名字数组
union { //共用体标志
ULONG PhysicalAddress; //物理地址
ULONG VirtualSize; //虚拟大小
} Misc;
ULONG VirtualAddress; //虚拟地址
ULONG SizeOfRawData; //原始数据的大小
ULONG PointerToRawData; //原始数据指针
ULONG PointerToRelocations; //重定位指针
ULONG PointerToLinenumbers; //行数指针
USHORT NumberOfRelocations; //重定位数目
USHORT NumberOfLinenumbers; //行数数目
ULONG Characteristics; //特征
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
这样就可以读取PE文件的重要信息。为以后的操作奠定基础。