书上没讲 PE 结构,只能从网上找资料看,但是习惯了看纸质书学习,网上只看小说、新闻啥的,所以学习进度很慢!总算初步搞明白 PE 结构了,先还是用熟悉的 C 语言练练手:把 exe 文件的 PE 文件的头部结构显示出来。
我没有按惯例把 IMAGE_DATA_DIRECTORY 放到 IMAGE_OPTIONAL_HEADER 里面,而是放到了 IMAGE_NT_HEADER 里面,让 IMAGE_DATA_DIRECTORY 和 IMAGE_OPTIONAL_HEADER 处于平等地位,因为我觉得这样比较顺眼!但是这会导致 IMAGE_FILE_HEADER 中的 SizeOfOptionalHeader 字段数值不准,需要进行换算。
/* PE.h PE 文件格式 四彩 2015-11-30 */ /* PE 文件的总体结构:(内存地址有低到高) IMAGE_DOS_HEADER(DOS 头) DOS stub "PE00"(PE 标志) IMAGE_FILE_HEADER(文件头) IMAGE_OPTIONAL_HEADER(可选头) IMAGE_DATA_DIRECTORY(数据块目录) IMAGE_SECTION_HEADER(节表) .text节区 .data节区 其它节区 不能被映射的其他数据 */ /* 虚拟地址:Virtual Address(VA),保护模式下访问内存所使用的逻辑地址。 装载基址:Image Base,文件装入内存的基址。 默认情况下,EXE 文件的基址为 0x00400000,DLL 文件的基址为 0x10000000。 相对虚拟地址:Relative Virtual Address(RVA),在内存中相对于装载基址的偏移量。 文件偏移地址:File Offset Address(FOA),文件在磁盘上存放时相对于文件开头的偏移量。 文件偏移地址从文件的第一个字节开始计数,起始值为 0。 无论是在内存中还是在磁盘文件中,节都是按基址排列的,而且都要对齐,但对齐值一般不同。 映射到内存后,所有头和节表的偏移位置与大小均没有变化,而各节基址的偏移位置发生了变化。 不管节是在文件中还是被加载到内存中,节中数据的位置相对该节的基址是不变的。 在内存中:数据相对节的起始位置的偏移h = 数据的RVA - 节的RVA 在文件中:数据相对节的起始位置的偏移h = 数据的FOA – 节的FOA 一个节中的数据只是属性相同,并不一定是同一种用途的内容,因此仅依靠节表是无法确定和定位 的,而要由数据目录表来定位。 */ /* IMAGE_DATA_DIRECTORY 直接定义在 IMAGE_NT_HEADER 里面,而不在 IMAGE_OPTIONAL_HEADER 里, 这导致 IMAGE_FILE_HEADER 中的 SizeOfOptionalHeader 字段数值失效。 */ #ifndef _PE_H #define _PE_H #include "Typedef.h" // *************************************************************************************** // DOS 头结构:文件偏移基址 0 // // e_magic 字段预定义值 #define IMAGE_DOS_SIGNATURE 0x5A4D // 即字符 "MZ" typedef struct tag_IMAE_DOS_HEADER { // 偏移 说明 WORD e_magic; // 0x00 DOS 可执行文件标识符(= "MZ") WORD e_cblp; // 0x02 Bytes on last page of file WORD e_cp; // 0x04 Pages in file WORD e_crlc; // 0x06 Relocations WORD e_cparhdr; // 0x08 Size of header in paragraphs WORD e_minalloc; // 0x0A Minimum extra paragraphs needed WORD e_maxalloc; // 0x0C Maximum extra paragraphs needed WORD e_ss; // 0x0E Initial (relative) SS value WORD e_sp; // 0x10 Initial SP value WORD e_csum; // 0x12 Checksum WORD e_ip; // 0x14 Initial IP value WORD e_cs; // 0x16 Initial (relative) CS value WORD e_lfarlc; // 0x18 File address of relocation table WORD e_ovno; // 0x1A Overlay number WORD e_res[4]; // 0x1C Reserved words WORD e_oemid; // 0x24 OEM identifier (for e_oeminfo) WORD e_oeminfo; // 0x26 OEM information; e_oemid specific WORD e_res2[10]; // 0x28 Reserved words DWORD e_lfanew; // 0x3C PE 签名的文件偏移地址 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; // ======================================================================================= // *************************************************************************************** // NT 头结构:文件偏移地址 = IMAGE_DOS_HEADER.e_lfanew // // NT 头结构 —— File 头结构 // // Machine 字段预定义值: Value Meaning #define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // x86 #define IMAGE_FILE_MACHINE_AMD64 0x8664 // x64 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel Itanium /* Characteristics 是一个标志的集合 位 预定义值 含义 0 IMAGE_FILE_RELOCS_STRIPPED 文件中没有重定向信息。在可执行文件中没有使用。 可执行文件用基址重定向目录表来表示重定向信息。 1 IMAGE_FILE_EXECUTABLE_IMAGE 可执行文件。 2 IMAGE_FILE_LINE_NUMS_STRIPPED 没有行数信息。在可执行文件中没有使用。 3 IMAGE_FILE_LOCAL_SYMS_STRIPPED 没有局部符号信息。在可执行文件中没有使用。 4 IMAGE_FILE_AGGRESIVE_WS_TRIM 已无效。 5 IMAGE_FILE_LARGE_ADDRESS_AWARE 应用程序可以处理超过 2 GB 的地址。 6 未使用 7 IMAGE_FILE_BYTES_REVERSED_LO 已无效。 8 IMAGE_FILE_32BIT_MACHINE 希望机器为32位机。这个值永远为 1。 9 IMAGE_FILE_DEBUG_STRIPPED 没有调试信息。在可执行文件中没有使用。 10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 该程序不能运行于可移动介质中(如软驱或CD)。 11 IMAGE_FILE_NET_RUN_FROM_SWAP 程序不能在网上运行。(必须拷贝到内存中执行) 12 IMAGE_FILE_SYSTEM 系统文件,如驱动程序。在可执行文件中没有使用。 13 IMAGE_FILE_DLL 动态链接库(DLL)。 14 IMAGE_FILE_UP_SYSTEM_ONLY 不能运行于多处理器系统中。 15 IMAGE_FILE_BYTES_REVERSED_HI 已无效。 */ // Characteristics 字段预定义值 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 #define IMAGE_FILE_32BIT_MACHINE 0x0100 #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 #define IMAGE_FILE_SYSTEM 0x1000 #define IMAGE_FILE_DLL 0x2000 #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 typedef struct tag_IMAGE_FILE_HEADER { WORD Machine; // 0x04 运行所要求的 CPU 类型。 WORD NumberOfSections; // 0x06 节数。 DWORD TimeDateStamp; // 0x08 文件创建日期和时间 DWORD PointerToSymbolTable; // 0x0C 指向符号表(用于调试) DWORD NumberOfSymbols; // 0x10 符号表中符号个数(用于调试) WORD SizeOfOptionalHeader; // 0x14 IMAGE_OPTIONAL_HEADER 结构大小(无效) WORD Characteristics; // 0x16 属性 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; // --------------------------------------------------------------------------------------- // NT 头结构 —— NT 可选头结构 // /* 数据目录表各项的含义 索引 预定义值 对应的数据块 0 IMAGE_DIRECTORY_ENTRY_EXPORT 导出函数表,主要用于 DLL 中的导出函数 1 IMAGE_DIRECTORY_ENTRY_IMPORT 导入函数表,使用外部函数的数据表 2 IMAGE_DIRECTORY_ENTRY_RESOURCE 资源数据表 3 IMAGE_DIRECTORY_ENTRY_EXCEPTION 异常处理表(具体资料不详) 4 IMAGE_DIRECTORY_ENTRY_SECURITY 安全处理数据表(具体资料不详) 5 IMAGE_DIRECTORY_ENTRY_BASERELOC 重定位信息表,一般和 DLL 相关 6 IMAGE_DIRECTORY_ENTRY_DEBUG 调试信息表 7 IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 版权信息表 8 IMAGE_DIRECTORY_ENTRY_GLOBALPTR 机器值(MIPS GP)(具体资料不详) 9 IMAGE_DIRECTORY_ENTRY_TLS 线程信息本地存储表 10 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 装配信息表(具体资料不详) 11 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 输入函数绑定信息表(具体资料不详) 12 IMAGE_DIRECTORY_ENTRY_IAT 导入函数地址表(与 ImportTable 对应, 由 Loader 填写的输入函数地址) 13 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 延迟装入的函数信息表(具体资料不详) 14 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 公用组件信息表(具体资料不详) 15 未使用 */ typedef struct tag_IMAGE_OPTIONAL_HEADER { // 偏移 说明 // Standard fields. WORD Magic; // 0x18 标志字(Win32 下总是 0x010B) BYTE MajorLinkerVersion; // 0x1A 链接程序的主版本号 BYTE MinorLinkerVersion; // 0x1B 链接程序的次版本号 DWORD SizeOfCode; // 0x1C 所有含代码的节的总大小 DWORD SizeOfInitializedData; // 0x20 所有含已初始化数据的节的总大小 DWORD SizeOfUninitializedData; // 0x24 所有含未初始化数据的节的大小 DWORD AddressOfEntryPoint; // 0x28 程序执行入口地址(RVA) DWORD BaseOfCode; // 0x2C 代码的区块的起始地址(RVA) DWORD BaseOfData; // 0x30 数据的区块的起始地址(RVA) // NT additional fields. DWORD ImageBase; // 0x34 首选装载基址 DWORD SectionAlignment; // 0x38 内存中节的对齐单位(32 位下为 4K) DWORD FileAlignment; // 0x3C 磁盘文件中节的对齐单位(一个扇区大小) WORD MajorOperatingSystemVersion; // 0x40 要求操作系统最低版本号的主版本号 WORD MinorOperatingSystemVersion; // 0x42 要求操作系统最低版本号的副版本号 WORD MajorImageVersion; // 0x44 可运行于操作系统的主版本号 WORD MinorImageVersion; // 0x46 可运行于操作系统的次版本号 WORD MajorSubsystemVersion; // 0x48 要求最低子系统版本的主版本号 WORD MinorSubsystemVersion; // 0x4A 要求最低子系统版本的次版本号 DWORD Win32VersionValue; // 0x4C 不明。一般为 0 。 DWORD SizeOfImage; // 0x50 装入内存后的总大小 DWORD SizeOfHeaders; // 0x54 所有头 + 节表的总大小 DWORD CheckSum; // 0x58 校检和 WORD Subsystem; // 0x5C 可执行文件期望的界面子系统 WORD DllCharacteristics; // 0x5E DllMain() 函数何时被调用,默认为 0 DWORD SizeOfStackReserve; // 0x60 初始化时的栈大小 DWORD SizeOfStackCommit; // 0x64 初始化时实际提交的栈大小 DWORD SizeOfHeapReserve; // 0x68 初始化时保留的堆大小 DWORD SizeOfHeapCommit; // 0x6C 初始化时实际提交的堆大小 DWORD LoaderFlags; // 0x70 与调试有关,默认为 0 DWORD NumberOfRvaAndSizes; // 0x74 数据目录表的项数 } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; // --------------------------------------------------------------------------------------- // NT 头结构 —— 数据目录结构 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 // 数据目录表的项数一直是 16 typedef struct tag_IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; // 数据的基址(RVA) DWORD Size; // 数据的长度 } IMAGE_DATA_DIRECTORY; // --------------------------------------------------------------------------------------- // NT 头结构 // // Signature 字段预定义值 #define IMAGE_NT_SIGNATURE 0x00004550 // 即字符"PE00" typedef struct tag_IMAGE_NT_HEADERS { // 偏移 说明 DWORD Signature; // 0x00 PE 文件签名(= "PE00") IMAGE_FILE_HEADER FileHeader; // 0x04 文件头结构 IMAGE_OPTIONAL_HEADER OptionalHeader; // 0x18 可选 NT 头结构 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 0x78 数据目录表 } IMAGE_NT_HEADER, *PIMAGE_NT_HEADER; // ======================================================================================= // *************************************************************************************** // 节表:文件偏移地址 = IMAGE_DOS_HEADER.e_lfanew + sizeof(IMAGE_NT_HEADER) // 项数由 IMAGE_NT_HEADER 中的 FileHeader.NumberOfSections 指定 // // 节(区块)头结构 #define IMAGE_SIZEOF_SHORT_NAME 8 // Name 字段最长 8 字节 // Characteristics 字段预定义值 #define IMAGE_SCN_CNT_CODE 0x20 // 包含代码 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 // 包含已初始化数据 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 // 包含未初始化数据 #define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 // 数据在进程开始后将被丢弃 #define IMAGE_SCN_MEM_NOT_CACHED 0x4000000 // 数据不经过缓存 #define IMAGE_SCN_MEM_NOT_PAGED 0x8000000 // 数据不被交换出内存 #define IMAGE_SCN_MEM_SHARED 0x10000000 // 数据可共享 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 // 可执行 #define IMAGE_SCN_MEM_READ 0x40000000 // 可读 #define IMAGE_SCN_MEM_WRITE 0x80000000 // 可写 typedef struct tag_IMAGE_SECTION_HEADER { // 偏移 说明 BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 0x00 节表名称(仅供编程参考) union // 0x08 一般是取后一个,即节的真实长度 { DWORD PhysicalAddress; // 物理地址 DWORD VirtualSize; // 真实长度(没有进行对齐处理前的实际大小) } Misc; DWORD VirtualAddress; // 0x0C 装载到内存的基址(内存对齐后的 RVA) DWORD SizeOfRawData; // 0x10 在文件中的大小(在磁盘中对齐后的大小) DWORD PointerToRawData; // 0x14 在文件中的偏移量(从文件头开始算起) DWORD PointerToRelocations; // 0x18 重定位的偏移(在 OBJ 文件中供调试用) DWORD PointerToLinenumbers; // 0x1C 行号表的偏移(同上) WORD NumberOfRelocations; // 0x20 重定位项的数目(同上) WORD NumberOfLinenumbers; // 0x22 行号表中行号的数目(同上) DWORD Characteristics; // 0x24 节的属性(如可读、可写、可执行等) } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; // ======================================================================================= #endif
/* PEF.c 显示 PE 文件格式信息 四彩 2015-11-30 */ #include <stdio.h> #include <stdlib.h> #include "PE.h" // 显示 IMAGE_DOS_HEADER 信息 void PrintDosHeader(IMAGE_DOS_HEADER DosHeader) { int i; printf("e_magic : %c%c\n", LByteOfW(DosHeader.e_magic), HByteOfW(DosHeader.e_magic)); printf("e_cblp : 0x%04X\n", DosHeader.e_cblp); printf("e_cp : 0x%04X\n", DosHeader.e_cp); printf("e_crlc : 0x%04X\n", DosHeader.e_crlc); printf("e_cparhdr : 0x%04X\n", DosHeader.e_cparhdr); printf("e_minalloc : 0x%04X\n", DosHeader.e_minalloc); printf("e_maxalloc : 0x%04X\n", DosHeader.e_maxalloc); printf("e_ss : 0x%04X\n", DosHeader.e_ss); printf("e_sp : 0x%04X\n", DosHeader.e_sp); printf("e_csum : 0x%04X\n", DosHeader.e_csum); printf("e_ip : 0x%04X\n", DosHeader.e_ip); printf("e_cs : 0x%04X\n", DosHeader.e_cs); printf("e_lfarlc : 0x%04X\n", DosHeader.e_lfarlc); printf("e_ovno : 0x%04X\n", DosHeader.e_ovno); printf("e_res : "); for(i = 0; i < 4; i++) printf("0x%X, ", DosHeader.e_res[i]); printf("\ne_oemid : 0x%04X\n", DosHeader.e_oemid); printf("e_oeminfo : 0x%04X\n", DosHeader.e_oeminfo); printf("e_res2 : "); for(i = 0; i < 10; i++) printf("0x%X, ", DosHeader.e_res2[i]); printf("\ne_lfanew : 0x%04X\n", DosHeader.e_lfanew); } // 显示 IMAGE_FILE_HEADER 信息 void PrintFileHeader(IMAGE_FILE_HEADER FileHeader) { printf("Machine : 0x%04X\n", FileHeader.Machine); printf("NumberOfSections : 0x%04X\n", FileHeader.NumberOfSections); printf("TimeDateStamp : 0x%08X\n", FileHeader.TimeDateStamp); printf("PointerToSymbolTable : 0x%08X\n", FileHeader.PointerToSymbolTable); printf("NumberOfSymbols : 0x%08X\n", FileHeader.NumberOfSymbols); printf("SizeOfOptionalHeader : 0x%04X\n", FileHeader.SizeOfOptionalHeader); printf("Characteristics : 0x%04X\n", FileHeader.Characteristics); } // 显示 IMAGE_OPTIONAL_HEADER 信息 void PrintOptionalHeader(IMAGE_OPTIONAL_HEADER OptHeader) { // Standard fields. printf("Magic : 0x%04X\n", OptHeader.Magic); printf("MajorLinkerVersion : 0x%02X\n", OptHeader.MajorLinkerVersion); printf("MinorLinkerVersion : 0x%02X\n", OptHeader.MinorLinkerVersion); printf("SizeOfCode : 0x%08X\n", OptHeader.SizeOfCode); printf("SizeOfInitializedData : 0x%08X\n", OptHeader.SizeOfInitializedData); printf("SizeOfUninitializedData : 0x%08X\n", OptHeader.SizeOfUninitializedData); printf("AddressOfEntryPoint : 0x%08X\n", OptHeader.AddressOfEntryPoint); printf("BaseOfCode : 0x%08X\n", OptHeader.BaseOfCode); printf("BaseOfData : 0x%08X\n", OptHeader.BaseOfData); // NT additional fields. printf("ImageBase : 0x%08X\n", OptHeader.ImageBase); printf("SectionAlignment : 0x%08X\n", OptHeader.SectionAlignment); printf("FileAlignmen : 0x%08X\n", OptHeader.FileAlignment); printf("MajorOperatingSystemVersion : 0x%04X\n", OptHeader.MajorOperatingSystemVersion); printf("MinorOperatingSystemVersion : 0x%04X\n", OptHeader.MinorOperatingSystemVersion); printf("MajorImageVersion : 0x%04X\n", OptHeader.MajorImageVersion); printf("MinorImageVersion : 0x%04X\n", OptHeader.MinorImageVersion); printf("MajorSubsystemVersion : 0x%04X\n", OptHeader.MajorSubsystemVersion); printf("MinorSubsystemVersion : 0x%04X\n", OptHeader.MinorSubsystemVersion); printf("Win32VersionValue : 0x%08X\n", OptHeader.Win32VersionValue); printf("SizeOfImage : 0x%08X\n", OptHeader.SizeOfImage); printf("SizeOfHeaders : 0x%08X\n", OptHeader.SizeOfHeaders); printf("CheckSum : 0x%08X\n", OptHeader.CheckSum); printf("Subsystem : 0x%04X\n", OptHeader.Subsystem); printf("DllCharacteristics : 0x%04X\n", OptHeader.DllCharacteristics); printf("SizeOfStackReserve : 0x%08X\n", OptHeader.SizeOfStackReserve); printf("SizeOfStackCommit : 0x%08X\n", OptHeader.SizeOfStackCommit); printf("SizeOfHeapReserve : 0x%08X\n", OptHeader.SizeOfHeapCommit); printf("SizeOfHeapCommit : 0x%08X\n", OptHeader.SizeOfHeapCommit); printf("LoaderFlags : 0x%08X\n", OptHeader.LoaderFlags); printf("NumberOfRvaAndSizes : 0x%08X\n", OptHeader.NumberOfRvaAndSizes); } // 显示 IMAGE_DATA_DIRECTORY 信息 void PrintDataDircrory(IMAGE_DATA_DIRECTORY DataDirectory) { printf(" 0x%08X 0x%08X", DataDirectory.VirtualAddress, DataDirectory.Size); } // 显示 IMAGE_SECTION_HEADER 信息 void PrintSectionHeader(IMAGE_SECTION_HEADER SectionHeader) { printf("Name : %s\n", SectionHeader.Name); printf("Misc.VirtualSize : 0x%08X\n", SectionHeader.Misc.VirtualSize); printf("VirtualAddress : 0x%08X\n", SectionHeader.VirtualAddress); printf("SizeOfRawData : 0x%08X\n", SectionHeader.SizeOfRawData); printf("PointerToRawData : 0x%08X\n", SectionHeader.PointerToRawData); printf("PointerToRelocations : 0x%08X\n", SectionHeader.PointerToRelocations); printf("PointerToLinenumbers : 0x%08X\n", SectionHeader.PointerToLinenumbers); printf("NumberOfRelocations : 0x%04X\n", SectionHeader.NumberOfRelocations); printf("NumberOfLinenumbers : 0x%04X\n", SectionHeader.NumberOfLinenumbers); printf("Characteristics : 0x%08X\n", SectionHeader.Characteristics); } int main(int argc, char **argv) { int i; FILE *fp; IMAGE_DOS_HEADER DosHeader; IMAGE_NT_HEADER NtHeader; IMAGE_SECTION_HEADER SectionHeader; if(argc != 2) { printf("Usage : %s exeFileName\n", argv[0]); return 0; } fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Error : open file\n"); return -1; } // 显示 IMAGE_DOS_HEADER 信息 fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, fp); if(DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { printf("Error : NOT DOS file\n"); fclose(fp); return -1; } printf("IMAGE_DOS_HEADER :\n"); PrintDosHeader(DosHeader); // 显示 IMAGE_NT_HEADER 信息 fseek(fp, DosHeader.e_lfanew, SEEK_SET); fread(&NtHeader, sizeof(IMAGE_NT_HEADER), 1, fp); if(NtHeader.Signature != IMAGE_NT_SIGNATURE) { printf("Error : NOT PE file\n"); fclose(fp); return 0; } printf("\nIMAGE_NT_HEADER :\n"); // Signature printf("Signature : %c%c%d%d\n", // 低低高高 LByteOfW(LWordOfDW(NtHeader.Signature)), HByteOfW(LWordOfDW(NtHeader.Signature)), LByteOfW(HWordOfDW(NtHeader.Signature)), HByteOfW(HWordOfDW(NtHeader.Signature))); printf("\nIMAGE_FILE_HEADER :\n"); // IMAGE_FILE_HEADER PrintFileHeader(NtHeader.FileHeader); printf("\nIMAGE_OPTIONAL_HEADER :\n"); // IMAGE_OPTIONAL_HEADER PrintOptionalHeader(NtHeader.OptionalHeader); printf("\nIMAGE_DATA_DIRECTORY : "); // 遍历全部 IMAGE_DATA_DIRECTORY printf("\n NO. VirtualAddress Size"); for(i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { if(NtHeader.DataDirectory[i].Size != 0) { printf("\n %2d", i); PrintDataDircrory(NtHeader.DataDirectory[i]); } } // 遍历显示全部 IMAGE_SECTION_HEADER 信息 printf("\n\nIMAGE_SECTION_HEADER :"); for(i = 0; i < NtHeader.FileHeader.NumberOfSections; i++) { printf("\nSECTION_HEADER : NO.%02d\n", i); fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, fp); PrintSectionHeader(SectionHeader); } fclose(fp); return 0; }
本程序的显示结果:
IMAGE_DOS_HEADER : e_magic : MZ e_cblp : 0x0090 e_cp : 0x0003 e_crlc : 0x0000 e_cparhdr : 0x0004 e_minalloc : 0x0000 e_maxalloc : 0xFFFF e_ss : 0x0000 e_sp : 0x00B8 e_csum : 0x0000 e_ip : 0x0000 e_cs : 0x0000 e_lfarlc : 0x0040 e_ovno : 0x0000 e_res : 0x0, 0x0, 0x0, 0x0, e_oemid : 0x0000 e_oeminfo : 0x0000 e_res2 : 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, e_lfanew : 0x0080 IMAGE_NT_HEADERS : Signature : PE00 IMAGE_FILE_HEADER : Machine : 0x014C NumberOfSections : 0x000D TimeDateStamp : 0x565C3D10 PointerToSymbolTable : 0x00006A00 NumberOfSymbols : 0x0000047D SizeOfOptionalHeader : 0x00E0 Characteristics : 0x0107 IMAGE_OPTIONAL_HEADER : Magic : 0x010B MajorLinkerVersion : 0x02 MinorLinkerVersion : 0x19 SizeOfCode : 0x00002400 SizeOfInitializedData : 0x00005000 SizeOfUninitializedData : 0x00000600 AddressOfEntryPoint : 0x000014E0 BaseOfCode : 0x00001000 BaseOfData : 0x00004000 ImageBase : 0x00400000 SectionAlignment : 0x00001000 FileAlignmen : 0x00000200 MajorOperatingSystemVersion : 0x0004 MinorOperatingSystemVersion : 0x0000 MajorImageVersion : 0x0001 MinorImageVersion : 0x0000 MajorSubsystemVersion : 0x0004 MinorSubsystemVersion : 0x0000 Win32VersionValue : 0x00000000 SizeOfImage : 0x00011000 SizeOfHeaders : 0x00000400 CheckSum : 0x0001C911 Subsystem : 0x0003 DllCharacteristics : 0x0000 SizeOfStackReserve : 0x00200000 SizeOfStackCommit : 0x00001000 SizeOfHeapReserve : 0x00001000 SizeOfHeapCommit : 0x00001000 LoaderFlags : 0x00000000 NumberOfRvaAndSizes : 0x00000010 IMAGE_DATA_DIRECTORY : NO. VirtualAddress Size 1 0x00009000 0x00000640 9 0x0000B004 0x00000018 12 0x00009124 0x000000E8 IMAGE_SECTION_HEADER : SECTION_HEADER : NO.00 Name : .text Misc.VirtualSize : 0x00002274 VirtualAddress : 0x00001000 SizeOfRawData : 0x00002400 PointerToRawData : 0x00000400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x60500060 SECTION_HEADER : NO.01 Name : .data Misc.VirtualSize : 0x00000038 VirtualAddress : 0x00004000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00002800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.02 Name : .rdata Misc.VirtualSize : 0x0000138C VirtualAddress : 0x00005000 SizeOfRawData : 0x00001400 PointerToRawData : 0x00002A00 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x40300040 SECTION_HEADER : NO.03 Name : /4 Misc.VirtualSize : 0x00000970 VirtualAddress : 0x00007000 SizeOfRawData : 0x00000A00 PointerToRawData : 0x00003E00 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x40300040 SECTION_HEADER : NO.04 Name : .bss Misc.VirtualSize : 0x00000444 VirtualAddress : 0x00008000 SizeOfRawData : 0x00000000 PointerToRawData : 0x00000000 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0700080 SECTION_HEADER : NO.05 Name : .idata Misc.VirtualSize : 0x00000640 VirtualAddress : 0x00009000 SizeOfRawData : 0x00000800 PointerToRawData : 0x00004800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.06 Name : .CRT Misc.VirtualSize : 0x00000034 VirtualAddress : 0x0000A000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005000 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.07 Name : .tls Misc.VirtualSize : 0x00000020 VirtualAddress : 0x0000B000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005200 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0xC0300040 SECTION_HEADER : NO.08 Name : /14 Misc.VirtualSize : 0x00000038 VirtualAddress : 0x0000C000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00005400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42400040 SECTION_HEADER : NO.09 Name : /29 Misc.VirtualSize : 0x00000DE7 VirtualAddress : 0x0000D000 SizeOfRawData : 0x00000E00 PointerToRawData : 0x00005600 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.10 Name : /41 Misc.VirtualSize : 0x00000089 VirtualAddress : 0x0000E000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006400 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.11 Name : /55 Misc.VirtualSize : 0x00000129 VirtualAddress : 0x0000F000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006600 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42100040 SECTION_HEADER : NO.12 Name : /67 Misc.VirtualSize : 0x00000038 VirtualAddress : 0x00010000 SizeOfRawData : 0x00000200 PointerToRawData : 0x00006800 PointerToRelocations : 0x00000000 PointerToLinenumbers : 0x00000000 NumberOfRelocations : 0x0000 NumberOfLinenumbers : 0x0000 Characteristics : 0x42300040
现在就是有个疑问:数据目录结构(IMAGE_DATA_DIRECTORY)到底干什么用的?和节表(IMAGE_SECTION_HEADER)有什么联系?
答:一个节中的数据只是属性相同,并不一定是同一种用途的内容,因此仅依靠节表是无法确定和定位
的,而要由数据目录表来定位。