PE 结构

PE的结构如下图所示:

262cca318a6067afa9018ef5

1.开始以DOS MZ开头,在0000003CH的位置找到对应的值计算真正地址--PE的头地址

PE文件中的DOS部分由MZ格式的文件头和可执行代码部分组成,可执行代码被称为“DOS块”(DOS stub)。一般来说,DOS部分的执行代码只是简单地显示一个“This program cannot be run in DOS mode.”就退出了,这段简单的代码是编译器自动生成的。

 1:  typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
 2:      +0h  WORD   e_magic;                     // Magic number
 3:      +2h  WORD   e_cblp;                      // Bytes on last page of file
 4:      +4h  WORD   e_cp;                        // Pages in file
 5:      +6h  WORD   e_crlc;                      // Relocations
 6:      +8h  WORD   e_cparhdr;                   // Size of header in paragraphs
 7:      +0ah WORD   e_minalloc;                  // Minimum extra paragraphs needed
 8:      +0ch WORD   e_maxalloc;                  // Maximum extra paragraphs needed
 9:      +0eh WORD   e_ss;                        // Initial (relative) SS value        DOS代码的初始化堆栈SS 
10:      +10h WORD   e_sp;                        // Initial SP value                    DOS代码的初始化堆栈指针SP
11:      +12h WORD   e_csum;                      // Checksum
12:      +14h WORD   e_ip;                        // Initial IP value                    DOS代码的初始化指令入口[指针IP]
13:      +16h WORD   e_cs;                        // Initial (relative) CS value        DOS代码的初始堆栈入口
14:      +18h WORD   e_lfarlc;                    // File address of relocation table
15:      +1ah WORD   e_ovno;                      // Overlay number
16:      +1ch WORD   e_res[4];                    // Reserved words
17:      +24h WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
18:      +26h WORD   e_oeminfo;                   // OEM information; e_oemid specific
19:      +29h WORD   e_res2[10];                  // Reserved words
20:      +3ch LONG   e_lfanew;                    // File address of new exe header    指向PE文件头        
21:    } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

在PE头地址开始,又是一个结构体

1:  typedef struct _IMAGE_NT_HEADERS {
2:    +0h  DWORD Signature;        //签名
3:    +4h  IMAGE_FILE_HEADER FileHeader;    //文件信息见下面展开
4:    +18h  IMAGE_OPTIONAL_HEADER32 OptionalHeader;    //可选部分
5:  } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
1:  typedef struct _IMAGE_FILE_HEADER {
2:     +4h  WORD    Machine;                    //运行平台
3:     +6h  WORD    NumberOfSections;           //文件的区块数目
4:     +8h  DWORD   TimeDateStamp;              //文件创建日期和时间
5:     +0ch DWORD   PointerToSymbolTable;       //指向符号表(主要用于调试)
6:     +10h DWORD   NumberOfSymbols;            //符号表中符号个数(同上)
7:     +14h WORD    SizeOfOptionalHeader;       //IMAGE_OPTIONAL_HEADER32结构大小
8:     +16h WORD    Characteristics;            //文件属性
9:  } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

image

1.如何计算节,表

节,表,在OptionalHeader之后,所以先要计算OptionalHeader的地址加上OptionalHeader长度之后就是节表的位置

OptionalHeader是在PE结构偏移18H位置, OptionalHeader=00000118H+18H=00000130H

计算SizeOfOptionalHeaeder

SizeOfOptionalHeaeder =PE+14H(20) =00000118H+14H=0000012CH(地址对应的值,00E0)

所以节表的位置在00000130H+00E0=00000210H

 1:  #define IMAGE_SIZEOF_SHORT_NAME              8
 2:  
 3:  typedef struct _IMAGE_SECTION_HEADER {
 4:      BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];    //节表名称,如".text"
 5:      union {
 6:              DWORD   PhysicalAddress;        //物理地址
 7:              DWORD   VirtualSize;            //真实长度,这两个值是一个联合结构,可以使用任何一个,一般取后一个
 8:      } Misc;
 9:      DWORD   VirtualAddress;                    //节区的RVA地址
10:      DWORD   SizeOfRawData;                    //在文件中对齐后的尺寸
11:      DWORD   PointerToRawData;                //在文件中的偏移量
12:      DWORD   PointerToRelocations;            //在OBJ文件中使用,重定位的偏移
13:      DWORD   PointerToLinenumbers;            //行号表的偏移,提供调试使用
14:      WORD    NumberOfRelocations;            //在OBJ文件中使用,重定位项目数目
15:      WORD    NumberOfLinenumbers;            //行号表中行号的数目
16:      DWORD   Characteristics;                //节属性如可读,可写,可执行等
17:  } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

每个区块表的结构占40个字节 sizeof(IMAGE_SECTION_HEADER)

Name:区块名:由一个8位的ASCII码名,用来定义区块的名称,多数区块名字以"."作为开头(例如: .text)这个"."不是必须的,如果区块名超过8个字节,则没有最后的终止符"NULL"字节,并且欠扁带有一个"$"的区块名会从连接器哪里得到特殊待遇,前边带有"$"的相同名字的区块在载入的时候会被合并,在合并之后的区块中,他们按照"$"后边的字符字母顺序进行合并.

每个区块名称都是唯一的,不能有同名的两个区块,事实上节名不代表任何意义,他的存在仅仅是为了正规统一编程的时候方便程序员查看方便而设置的一个标记而已.所以将包含代码的区块命名为".Data"或者讲包含数据的区块命名为".Code"都是合法的

RVA 相对虚拟地址(Relative Virtual Address)缩写

原文地址:https://www.cnblogs.com/fjchenqian/p/2826445.html