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文件的重要信息。为以后的操作奠定基础。