PE文件结构(懒的写博客我直接贴代码还不行么!)
2016-05-14 09:30
323 查看
1.常见PE文件 可执行文件:EXE,SCR,COM 驱动程序:SYS,VSD 库文件:DLL,OCX,CPL,DRV 对象文件:OBJ 2.PE32(32位)、PE32+或者PE+(64位) 3.PE组成: DOS头 DOS存根 NT头 节区头(代码段) 节区头(数据段) 节区头(资源段) 节区(代码段) 节区(数据段) 节区(资源段) 4.VA(virtual address:虚拟地址)&RVA(relative virtual address:相对虚拟地址) VA=RVA+ImageBase(映象基址) 5.DOS头 IMAGE_DOS_HEADER STRUCT { +0h WORD e_magic // Magic DOS signature MZ(4Dh 5Ah) DOS可执行文件标记 +2h WORD e_cblp // Bytes on last page of file 最后一页大小 +4h WORD e_cp // Pages in file 文件页数 +6h WORD e_crlc // Relocations +8h WORD e_cparhdr // Size of header in paragraphs 头的段大小 +0ah WORD e_minalloc // Minimun extra paragraphs needs 最小额外段需求 +0ch WORD e_maxalloc // Maximun extra paragraphs needs 最大额外段需求 +0eh WORD e_ss // intial(relative)SS value DOS代码的初始化堆栈SS +10h WORD e_sp // intial SP value DOS代码的初始化堆栈指针SP +12h WORD e_csum // Checksum 校验和 +14h WORD e_ip // intial IP value DOS代码的初始化指令入口[指针IP] +16h WORD e_cs // intial(relative)CS value DOS代码的初始堆栈入口 +18h WORD e_lfarlc // File Address of relocation table 重定位表的文件地址 +1ah WORD e_ovno // Overlay number +1ch WORD e_res[4] // Reserved words 保留字 +24h WORD e_oemid // OEM identifier(for e_oeminfo) +26h WORD e_oeminfo // OEM information;e_oemid specific +29h WORD e_res2[10] // Reserved words 保留字 +3ch DWORD e_lfanew //Offset to start of PE header NT头地址 } IMAGE_DOS_HEADER ENDS 6.DOS存根 DOS存根是16位的汇编指令,用以在DOS中运行 7.NT头 typedef struct _IMAGE_NT_HEADERS { +00h DWORD Signature; //PE签名 固定为 "PE"00(0X50450000) +04h IMAGE_FILE_HEADER FileHeader; //文件头 大小为0xF8 +18h IMAGE_OPTIONAL_HEADER32 OptionalHeader;//可选头 } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; //文件头 typedef struct _IMAGE_FILE_HEADER { +00h WORD Machine; //CPU机器码,I386对应为0x014c +02h WORD NumberOfSections; //节区数量 +04h DWORD TimeDateStamp; //PE文件的创建时间,一般有连接器填写。 +08h DWORD PointerToSymbolTable; //COFF文件符号表在文件中的偏移。 +0ch DWORD NumberOfSymbols; //符号表的数量。 +10h WORD SizeOfOptionalHeader; //可选头大小 +12h WORD Characteristics; //文件属性标志(用或计算) 常见:0x0002:可执行文件 0x2000:DLL文件 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; //可选头,以32位下可选头为例 typedef struct _IMAGE_OPTIONAL_HEADER { +00h WORD Magic; //可选头类型 +02h BYTE MajorLinkerVersion; //连接器版本号 +03h BYTE MinorLinkerVersion; //连接器版本号 +04h DWORD SizeOfCode; //代码段的长度,如果有多个代码段,则是代码段长度的总和。 +08h DWORD SizeOfInitializedData; //初始化的数据长度。 +0ch DWORD SizeOfUninitializedData; //未初始化的数据长度。 +10h DWORD AddressOfEntryPoint; //程序的EP(RVA表示) +14h DWORD BaseOfCode; //代码段起始地址的RVA。 +18h DWORD BaseOfData; //数据段起始地址的RVA。 +1ch DWORD ImageBase; //映象(加载到内存中的PE文件)的基地址,这个基地址是建议,对于DLL来说,如果无法加载到这个地址,系统会自动为其选择地址。 +20h DWORD SectionAlignment; //节对齐,PE中的节被加载到内存时会按照这个域指定的值来对齐,比如这个值是0x1000,那么每个节的起始地址的低12位都为0。 +24h DWORD FileAlignment;//节在文件中按此值对齐,SectionAlignment必须大于或等于FileAlignment。 +28h WORD MajorOperatingSystemVersion; //操作系统版本号 +2ah WORD MinorOperatingSystemVersion; //操作系统版本号 +2ch WORD MajorImageVersion; //映象的版本号,这个是开发者自己指定的,由连接器填写。 +2eh WORD MinorImageVersion; //映象的版本号,这个是开发者自己指定的,由连接器填写。 +30h WORD MajorSubsystemVersion; //所需子系统版本号。 +32h WORD MinorSubsystemVersion; //所需子系统版本号。 +34h DWORD Win32VersionValue; //保留,必须为0。 +38h DWORD SizeOfImage; //映象的大小,PE文件加载到内存中空间是连续的,这个值指定占用虚拟空间的大小。 +3ch DWORD SizeOfHeaders; //所有文件头(包括节表)的大小,这个值是以FileAlignment对齐的。 +40h DWORD CheckSum; //映象文件的校验和。 +44h WORD Subsystem; //运行该PE文件所需的子系统(1.系统驱动,2.窗口应用程序,3.控制台应用) +46h WORD DllCharacteristics; //DLL的文件属性 +48h DWORD SizeOfStackReserve; //运行时为每个线程栈保留内存的大小。 +4ch DWORD SizeOfStackCommit; //运行时每个线程栈初始占用内存大小。 +50h DWORD SizeOfHeapReserve; //运行时为进程堆保留内存大小。 +54h DWORD SizeOfHeapCommit; //运行时进程堆初始占用内存大小。 +58h DWORD LoaderFlags; //保留,必须为0。 +5eh DWORD NumberOfRvaAndSizes; //数据目录的项数,即下面这个数组的项数 +60h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //数据目录,这是一个数组,第i项含义在下边 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; typedef struct { +00h DWORD VirtualAddress; //RVA +04h DWORD Size; //大小 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor 8.节区头 typedef struct _IMAGE_SECTION_HEADER { +00h BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8个字节的区块名 +08h union { //区块尺寸 DWORD PhysicalAddress; DWORD VirtualSize; } Misc; +0ch DWORD VirtualAddress; //区块的RVA地址 +10h DWORD SizeOfRawData; //文件对齐后的尺寸 +14h DWORD PointerToRawData; //文件偏移 +18h DWORD PointerToRelocations; +1ch DWORD PointerToLinenumbers; +20h WORD NumberOfRelocations; +22h WORD NumberOfLinenumbers; +24h DWORD Characteristics; //区块的属性 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; RVA与RAW换算(内存地址与文件偏移的转换) RAW=RVA-VirtualAddress+PointerToRawData 9.IAT(Import Address Table:导入地址表): INT和IAT是以NULL为结束的长整型数组,保存的是_IMAGE_IMPORT_BY_NAME, IMAGE_THUNK_DATA 的地址 _IMAGE_IMPORT_DESCRIPTOR:结构体中记录着PE文件要导入哪些库文件 typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // DWORD OriginalFirstThunk; // INT地址(RVA) }; DWORD TimeDateStamp; // DWORD ForwarderChain; // DWORD Name; // RVA,指向字符串,是这个可执行文件的名字。例如"ACE.dll" DWORD FirstThunk; // IAT地址(RVA) } IMAGE_IMPORT_DESCRIPTOR; typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; ///该函数的导出序数 BYTE Name[1]; ///该函数的名字 } `, *PIMAGE_IMPORT_BY_NAME; typedef struct _IMAGE_THUNK_DATA32 { union { DWORD ForwarderString; // 一个RVA地址,指向forwarder string DWORD Function; // PDWORD,被导入的函数的入口地址 DWORD Ordinal; // 该函数的序数 DWORD AddressOfData; // 一个RVA地址,指向IMAGE_IMPORT_BY_NAME } u1; } IMAGE_THUNK_DATA32; IMAGE_THUNK_DATA64与IMAGE_THUNK_DATA32的区别,仅仅是把DWORD换成了64位整数。 10.EAT typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; //模块的内部名称,如果DLL文件的名字被用户改了,那么PE加载器会使用这个内部名称 DWORD Base; //序号的起始编号,注意:起始序号可以不为0 DWORD NumberOfFunctions; //导出函数的个数 DWORD NumberOfNames; //导出函数中具名函数个数 DWORD AddressOfFunctions; //导出函数地址表所在地址(大小等于NumberOfNames) DWORD AddressOfNames; //导出函数名称表所在地址(大小等于NumberOfNames) DWORD AddressOfNameOrdinals; //导出函数序数表所在地址(大小等于NumberOfNames) } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
相关文章推荐
- Mono源码阅读--加载文件
- PE文件数据结构汇总
- PE文件结构 - 导入表结构
- PE文件结构详解
- Spring属性占位符PropertyPlaceholderConfigurer
- Java配置文件Properties的读取、写入与更新操作
- Java设计模式之代理设计模式
- Eclipse&STS常用小技巧
- java常用工具类之DES和Base64加密解密类
- java多线程系列四:synchronized
- [C++]内存管理器--谈论如何自定义内存分配机制
- eclipse 优化配置
- 成为C++高手之最终版计算器
- java-Thread
- QT连接mysql
- JDK的安装与环境变量配置
- java第六次作业 抽奖机
- C++中关于set的自定义排序函数的书写
- thinkphp集成系列之rbac的升级版auth权限管理系统demo
- thinkphp集成系列之rbac的升级版auth权限管理系统demo