结构体源代码如下:

IMAGE_SECTION_HEADER 的源代码如下:

资源表是一个树形结构,可以设置成2的31次方的层数,Windows 使用了3级:

typedef struct _IMAGE_OPTIONAL_HEADER 
{
    //
    // Standard fields.  
    //
+18h    WORD    Magic;                   // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
+1Ah    BYTE    MajorLinkerVersion;      // 链接程序的主版本号
+1Bh    BYTE    MinorLinkerVersion;      // 链接程序的次版本号
+1Ch    DWORD   SizeOfCode;              // 所有含代码的节的总大小
+20h    DWORD   SizeOfInitializedData;   // 所有含已初始化数据的节的总大小
+24h    DWORD   SizeOfUninitializedData; // 所有含未初始化数据的节的大小
+28h    DWORD   AddressOfEntryPoint;     // 程序执行入口RVA ***(必须了解)***
+2Ch    DWORD   BaseOfCode;              // 代码的区块的起始RVA
+30h    DWORD   BaseOfData;              // 数据的区块的起始RVA
    //
    // NT additional fields.    以下是属于NT结构增加的领域。
    //
+34h    DWORD   ImageBase;               // 程序的首选装载地址 ***(必须了解)***
+38h    DWORD   SectionAlignment;        // 内存中的区块的对齐大小 ***(必须了解)***
+3Ch    DWORD   FileAlignment;           // 文件中的区块的对齐大小 ***(必须了解)***
+40h    WORD    MajorOperatingSystemVersion;  // 要求操作系统最低版本号的主版本号
+42h    WORD    MinorOperatingSystemVersion;  // 要求操作系统最低版本号的副版本号
+44h    WORD    MajorImageVersion;       // 可运行于操作系统的主版本号
+46h    WORD    MinorImageVersion;       // 可运行于操作系统的次版本号
+48h    WORD    MajorSubsystemVersion;   // 要求最低子系统版本的主版本号
+4Ah    WORD    MinorSubsystemVersion;   // 要求最低子系统版本的次版本号
+4Ch    DWORD   Win32VersionValue;       // 莫须有字段,不被病毒利用的话一般为0
+50h    DWORD   SizeOfImage;             // 映像装入内存后的总尺寸
+54h    DWORD   SizeOfHeaders;           // 所有头 + 区块表的尺寸大小
+58h    DWORD   CheckSum;                // 映像的校检和
+5Ch    WORD    Subsystem;               // 可执行文件期望的子系统 ***(必须了解)***
+5Eh    WORD    DllCharacteristics;      // DllMain()函数何时被调用,默认为 0
+60h    DWORD   SizeOfStackReserve;      // 初始化时的栈大小
+64h    DWORD   SizeOfStackCommit;       // 初始化时实际提交的栈大小
+68h    DWORD   SizeOfHeapReserve;       // 初始化时保留的堆大小
+6Ch    DWORD   SizeOfHeapCommit;        // 初始化时实际提交的堆大小
+70h    DWORD   LoaderFlags;             // 与调试有关,默认为 0 
+74h    DWORD   NumberOfRvaAndSizes;     // 下边数据目录的项数,这个字段自Windows NT 发布以来一直是16
+78h    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];   
// 数据目录表 ***(必须了解,重点)*** winNT发布到win10,IMAGE_NUMBEROF_DIRECTORY_ENTRIES一直都是16
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_SECTION_HEADER 
{
    BYTE Name[IMAGE_SIZEOF_SHORT_NAME];   // 节表名称,如“.text” 
    //IMAGE_SIZEOF_SHORT_NAME=8
    union
    {

        DWORD PhysicalAddress; // 在文件中的物理地址

DWORD VirtualSize;     // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一般是取后一个

} Misc;
    DWORD VirtualAddress;          // 节区的 RVA 地址

DWORD SizeOfRawData;           // 在文件中对齐后的尺寸

DWORD PointerToRawData;        // 在文件中的偏移量

DWORD PointerToRelocations;    // 在OBJ文件中使用,重定位的偏移

DWORD PointerToLinenumbers;    // 行号表的偏移(供调试使用地)

WORD NumberOfRelocations;      // 在OBJ文件中使用,重定位项数目

WORD NumberOfLinenumbers;      // 行号表中行号的数目

DWORD Characteristics;         // 节属性如可读,可写,可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

类型->名称->语言

AddressOfEntryPoint  ***(必须了解)***

每个区块表长度占40个字节。

图片 1

程序开始执行的地址,这是一个RVA(相对虚拟地址)。对于exe文件,这里是启动代码;对于dll文件,这里是libMain()的地址。如果在一个可执行文件上附加了一段代码并想让这段代码首先被执行,那么只需要将这个入口地址指向附加的代码就可以了。在脱壳时第一件事就是找入口点,指的就是这个值。

*
表示需要注意的字段,最有用的是 SizeOfRawData 、**
 PointerToRawData
和Characteristics
字段。**

 

ImageBase  ***(必须了解)***

Name *

此字段时区块名。(一句话:名字而已,没什么用

要求:

  1. 占8个字节的utf8字符串,如果区块名超过 8
    个字节,则没有最后的终止标志“NULL”。

  2. 每个区块的名称都是唯一的,不能有同名的两个区块。

3.
另外,如果名字过长,可以那么使用斜杠(/)加上ASCII字符表示一个10进制地址,这个地址表示真正的区块名在在字符串表中的地址。

含义:但事实上节的名称不代表任何含义,仅仅是为了便查看方便(所以将包含代码的区块命名为“.Data”
或者说将包含数据的区块命名为“.Code” 都是合法的。)。当我们要从PE
文件中读取需要的区块时候,不能以区块的名称作为定位的标准和依据。正确的做法是按照
IMAGE_OPTIONAL_HEADER32 结构中的数据目录字段结合进行定位。

其他说明:多数区块名都习惯性以一个“.”作为开头(例如:.text),这个“.”
不是必须的。并且前边带有一个“$”
的区块名字会从连接器那里得到特殊的待遇,前边带有“$”
的相同名字的区块在载入时候将会被合并,在合并之后的区块中,他们是按照“$”
后边的字符的字母顺序进行合并的。

其中涉及到四个结构:

PE文件的优先装入地址。也就是说,当文件被执行时,如果可能的话(当前地址没有被使用),Windows优先将文件装入到由ImageBase字段指定的地址中。

Misc *

共用体:

PhysicalAddress 在文件中的地址。
Virtual Size 此节在读取到内存中的总大小,单位是字节。如果此值大于 SizeOfRawData 成员的话,此节将被0填充。此值仅当可执行镜像且object文件必须被设置为0时有效。

 

对于EXE文件来说,由于每个文件总是使用独立的虚拟地址空间,优先装入地址不可能被**模块占据,所以EXE总是能够按照这个地址装入

 

Data

Description

Resource Directory Tables (and Resource Directory Entries)

A series of tables, one for each group of nodes in the tree. All top-level (Type) nodes are listed in the first table. Entries in this table point to second-level tables. Each second-level tree has the same Type ID but different Name IDs. Third-level trees have the same Type and Name IDs but different Language IDs.

Each individual table is immediately followed by directory entries, in which each entry has a name or numeric identifier and a pointer to a data description or a table at the next lower level.

Resource Directory Strings

Two-byte-aligned Unicode strings, which serve as string data that is pointed to by directory entries.

Resource Data Description

An array of records, pointed to by tables, that describe the actual size and location of the resource data. These records are the leaves in the resource-description tree.

Resource Data

Raw data of the resource section. The size and location information in the Resource Data Descriptions field delimit the individual regions of resource data.

这也意味着EXE文件不再需要重定位信息。

Virtual Address *

该区块装载到内存中的RVA
地址。这个地址是按照内存页来对齐的,因此它的数值总是 SectionAlignment
的值的整数倍。

在Microsoft 工具中,第一个快的默认 RVA 总为1000h。在OBJ
中,该字段没有意义地,并被设为0。

 

对于DLL文件来说,由于多个DLL文件全部使用宿主EXE文件的地址空间,不能保证优先装入地址没有被**的DLL使用,所以DLL文件中必须包含重定位信息以防万一。

SizeOfRawData ***

该区块在磁盘中所占的大小(单位是字节),必须是IMAGE_OPTIONAL_HEADERFileAlignment成员的整数倍。如果此值小于Virtual
Size
,那么剩下的字节以0填充。如果此节仅包含未初始化的数据,那么成员为0。

 

因此,在前面介绍的 IMAGE_FILE_HEADER 结构的 Characteristics
字段中,DLL 文件对应的 IMAGE_FILE_RELOCS_STRIPPED
位总是为0,而EXE文件的这个标志位总是为1。

PointerToRawData ***

该区块在磁盘中的偏移。这个数值是从文件头开始算起的偏移量哦。

 

如果没有指定的话,dll文件默认为0x10000000;exe文件默认为0x00400000,但是在Windows
CE平台上是0x00010000。此值必须是64K bytes的倍数!

PointerToRelocations

这哥们在EXE文件中没有意义,在OBJ
文件中,表示本区块重定位信息的偏移值
。(在OBJ
文件中如果不是零,它会指向一个IMAGE_RELOCATION 结构的数组)

 

SectionAlignment ***(必须了解)***

PointerToLinenumbers

行号表在文件中的偏移值,文件的调试信息,于我们没用,鸡肋。

Resource Directory Table

Each resource directory
table has the following format. This data structure should be considered
the heading of a table because the table actually consists of directory
entries (described in section 6.9.2, “Resource Directory Entries”) and
this structure:

Offset Size Field Description
0 4 Characteristics Resource flags. This field is reserved for future use. It is currently set to zero.
4 4 Time/Date Stamp The time that the resource data was created by the resource compiler.
8 2 Major Version The major version number, set by the user.
10 2 Minor Version The minor version number, set by the user.
12 2 Number of Name Entries The number of directory entries immediately following the table that use strings to identify Type, Name, or Language entries (depending on the level of the table).
14 2 Number of ID Entries The number of directory entries immediately following the Name entries that use numeric IDs for Type, Name, or Language entries.

 

内存中区块的对齐单位。区块总是对齐到这个值的整数倍。此字段必须大于或等于
FileAlignment ,默认值是系统页面的大小。32位cpu通常值为
0x1000(十六进制),即4096,即4KB。64位cpu通常为 8kB
FileAlignment ***(必须了解)*****

NumberOfRelocations

这哥们在EXE文件中也没有意义,在OBJ
文件中,是本区块在重定位表中的重定位数目
来着。

Resource Directory Entries

The directory entries
make up the rows of a table. Each resource directory entry has the
following format. Whether the entry is a Name or ID entry is indicated
by the resource directory table, which indicates how many Name and ID
entries follow it (remember that all the Name entries precede all the ID
entries for the table). All entries for the table are sorted in
ascending order: the Name entries by case-sensitive string and the ID
entries by numeric value.  Offsets are relative to the address in the
IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory.

Offset

Size

Field

Description

0

4

Name Offset

The offset of a string that gives the Type, Name, or Language ID entry, depending on level of table.

0

4

Integer ID

A 32-bit integer that identifies the Type, Name, or Language ID entry.

4

4

Data Entry Offset

High bit 0. Address of a Resource Data entry (a leaf).

4

4

Subdirectory Offset

High bit 1. The lower 31 bits are the address of another resource directory table (the next level down).

pe文件中区块的对齐单位,以bytes(字节)为单位。此值必须是2的次方倍,但是必须在512和64K区间之间(闭区间[521,
64*1024=65536]),如果SectionAlignment小于系统页面的大小,那么SectionAlignment的大小就和FileAlignment相同。pe文件中默认值为
521 字节(0.5KB) 即 0x200(十六进制)。

NumberOfLinenumbers

该区块在行号表中的行号数目,鸡肋。

 

Subsystem ***(必须了解)***

Characteristics ***

该区块的属性。该字段是按位来指出区块的属性(如代码/数据/可读/可写等)的标志。

在 winnt.h 中定义如下:

//
// Section characteristics.
//
//      IMAGE_SCN_TYPE_REG                   0x00000000  // Reserved.
//      IMAGE_SCN_TYPE_DSECT                 0x00000001  // Reserved.
//      IMAGE_SCN_TYPE_NOLOAD                0x00000002  // Reserved.
//      IMAGE_SCN_TYPE_GROUP                 0x00000004  // Reserved.
#define IMAGE_SCN_TYPE_NO_PAD                0x00000008  // Reserved.
//      IMAGE_SCN_TYPE_COPY                  0x00000010  // Reserved.

#define IMAGE_SCN_CNT_CODE                   0x00000020  // Section contains code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA       0x00000040  // Section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA     0x00000080  // Section contains uninitialized data.

#define IMAGE_SCN_LNK_OTHER                  0x00000100  // Reserved.
#define IMAGE_SCN_LNK_INFO                   0x00000200  // Section contains comments or some other type of information.
//      IMAGE_SCN_TYPE_OVER                  0x00000400  // Reserved.
#define IMAGE_SCN_LNK_REMOVE                 0x00000800  // Section contents will not become part of image.
#define IMAGE_SCN_LNK_COMDAT                 0x00001000  // Section contents comdat.
//                                           0x00002000  // Reserved.
//      IMAGE_SCN_MEM_PROTECTED - Obsolete   0x00004000
#define IMAGE_SCN_NO_DEFER_SPEC_EXC          0x00004000  // Reset speculative exceptions handling bits in the TLB entries for this section.
#define IMAGE_SCN_GPREL                      0x00008000  // Section content can be accessed relative to GP
#define IMAGE_SCN_MEM_FARDATA                0x00008000
//      IMAGE_SCN_MEM_SYSHEAP  - Obsolete    0x00010000
#define IMAGE_SCN_MEM_PURGEABLE              0x00020000
#define IMAGE_SCN_MEM_16BIT                  0x00020000
#define IMAGE_SCN_MEM_LOCKED                 0x00040000
#define IMAGE_SCN_MEM_PRELOAD                0x00080000

#define IMAGE_SCN_ALIGN_1BYTES               0x00100000  //
#define IMAGE_SCN_ALIGN_2BYTES               0x00200000  //
#define IMAGE_SCN_ALIGN_4BYTES               0x00300000  //
#define IMAGE_SCN_ALIGN_8BYTES               0x00400000  //
#define IMAGE_SCN_ALIGN_16BYTES              0x00500000  // Default alignment if no others are specified.
#define IMAGE_SCN_ALIGN_32BYTES              0x00600000  //
#define IMAGE_SCN_ALIGN_64BYTES              0x00700000  //
#define IMAGE_SCN_ALIGN_128BYTES             0x00800000  //
#define IMAGE_SCN_ALIGN_256BYTES             0x00900000  //
#define IMAGE_SCN_ALIGN_512BYTES             0x00A00000  //
#define IMAGE_SCN_ALIGN_1024BYTES            0x00B00000  //
#define IMAGE_SCN_ALIGN_2048BYTES            0x00C00000  //
#define IMAGE_SCN_ALIGN_4096BYTES            0x00D00000  //
#define IMAGE_SCN_ALIGN_8192BYTES            0x00E00000  //
// Unused                                    0x00F00000
#define IMAGE_SCN_ALIGN_MASK                 0x00F00000

#define IMAGE_SCN_LNK_NRELOC_OVFL            0x01000000  // Section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE            0x02000000  // Section can be discarded.
#define IMAGE_SCN_MEM_NOT_CACHED             0x04000000  // Section is not cachable.
#define IMAGE_SCN_MEM_NOT_PAGED              0x08000000  // Section is not pageable.
#define IMAGE_SCN_MEM_SHARED                 0x10000000  // Section is shareable.
#define IMAGE_SCN_MEM_EXECUTE                0x20000000  // Section is executable.
#define IMAGE_SCN_MEM_READ                   0x40000000  // Section is readable.
#define IMAGE_SCN_MEM_WRITE                  0x80000000  // Section is writeable.

//
// TLS Characteristic Flags
//
#define IMAGE_SCN_SCALE_INDEX                0x00000001  // Tls index is scaled

常用的值的翻译:

数值

含义

IMAGE_SCN_CNT_CODE
0x00000020

The section contains executable code.

包含代码,常与 0x10000000一起设置。

IMAGE_SCN_CNT_INITIALIZED_DATA
0x00000040

The section contains initialized data.

该区块包含以初始化的数据。

IMAGE_SCN_CNT_UNINITIALIZED_DATA
0x00000080

The section contains uninitialized data.

该区块包含未初始化的数据。

IMAGE_SCN_MEM_DISCARDABLE
0x02000000

The section can be discarded as needed.
该区块可被丢弃,因为当它一旦被装入后,
进程就不在需要它了,典型的如重定位区块。

IMAGE_SCN_MEM_SHARED
0x10000000

The section can be shared in memory.
该区块为共享区块。

IMAGE_SCN_MEM_EXECUTE
0x20000000

The section can be executed as code.
该区块可以执行。通常当0x00000020被设置
时候,该标志也被设置。

IMAGE_SCN_MEM_READ
0x40000000

The section can be read.
该区块可读,可执行文件中的区块总是设置该
标志。

IMAGE_SCN_MEM_WRITE
0x80000000

The section can be written to.
该区块可写。

更多资料请参考官方文档:

例子:

图片 2

Resource Directory String

The resource directory
string area consists of Unicode strings, which are word-aligned. These
strings are stored together after the last Resource Directory entry and
before the first Resource Data entry. This minimizes the impact of these
variable-length strings on the alignment of the fixed-size directory
entries. Each resource directory string has the following format:

Offset

Size

Field

Description

0

2

Length

The size of the string, not including length field itself.

2

variable

Unicode String

The variable-length Unicode string data, word-aligned.

pe文件的用户界面使用的子系统类型。定义如下:

 

#define IMAGE_SUBSYSTEM_UNKNOWN              0   // 未知子系统
#define IMAGE_SUBSYSTEM_NATIVE               1   // 不需要子系统(如驱动程序)
#define IMAGE_SUBSYSTEM_WINDOWS_GUI          2   // Windows GUI 子系统
#define IMAGE_SUBSYSTEM_WINDOWS_CUI          3   // Windows 控制台子系统
#define IMAGE_SUBSYSTEM_OS2_CUI              5   // OS/2 控制台子系统
#define IMAGE_SUBSYSTEM_POSIX_CUI            7   // Posix 控制台子系统
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS       8   // 镜像是原生 Win9x 驱动程序
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI       9   // Windows CE 图形界面

Resource Data Entry

Each Resource Data
entry describes an actual unit of raw data in the Resource Data area. A
Resource Data entry has the following format:

Offset

Size

Field

Description

  0

4

Data RVA

The address of a unit
of resource data in the Resource Data area.

  4

4

Size

The size, in bytes, of
the resource data that is pointed to by the Data RVA field.

  8

4

Codepage

The code page that is
used to decode code point values within the resource data. Typically,
the code page would be the Unicode code page.

12

4

Reserved, must be
0.

例如,Visual Studio 2015中编译程序时可以在图形界面设置链接选项:

图片 3

更多请查看:

微软官方文档:https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx.aspx)

DataDirectory ***(必须了解,重要)***

这个字段可以说是最重要的字段之一,它由16个相同的IMAGE_DATA_DIRECTORY结构组成。其结构如下:

typedef struct _IMAGE_DATA_DIRECTORY {

   DWORD   VirtualAddress; // 相对虚拟地址 

   DWORD   Size;           // 数据块的大小

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

也就是定义了某块的位置和大小。

虽然PE文件中的数据是按照装入内存后的页属性归类而被放在不同的节中的,但是这些处于各个节中的数据按照用途可以被分为导出表、导入表、资源、重定位表等数据块,这16个IMAGE_DATA_DIRECTORY结构就是用来定义多种不同用途的数据块的(如下表所示)。IMAGE_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

给出说明:

Offset

(PE/PE32+)

Size

Field

Description

  96/112

8

Export
Table

The export table
address and size. For more information see section 6.3, “The .edata
Section (Image Only).”

104/120

8

Import
Table

The import table
address and size. For more information, see section 6.4, “The .idata
Section.”

112/128

8

Resource
Table

The resource table
address and size. For more information, see section 6.9, “The .rsrc
Section.”

120/136

8

Exception
Table

The exception table
address and size. For more information, see section 6.5, “The .pdata
Section.”

128/144

8

Certificate
Table

The attribute
certificate table address and size. For more information, see section
5.7, “The Attribute Certificate Table (Image Only).”

136/152

8

Base Relocation
Table

The base relocation
table address and size. For more information, see section 6.6, “The
.reloc Section (Image
Only).”

144/160

8

Debug

The debug data starting
address and size. For more information, see section 6.1, “The .debug
Section.”

152/168

8

Architecture

Reserved, must be
0

160/176

8

Global Ptr

The RVA of the value to
be stored in the global pointer register. The size member of this
structure must be set to zero.

168/184

8

TLS Table

The thread local
storage (TLS) table address and size. For more information, see section
6.7, “The .tls Section.”

176/192

8

Load Config
Table

The load configuration
table address and size. For more information, see section 6.8, “The Load
Configuration Structure (Image Only).”

184/200

8

Bound
Import

The bound import table
address and size.

192/208

8

IAT

The import address
table address and size. For more information, see section 6.4.4, “Import
Address Table.”

200/216

8

Delay Import
Descriptor

The delay import
descriptor address and size. For more information, see section 5.8,
“Delay-Load Import Tables (Image Only).”

208/224

8

CLR Runtime
Header

The CLR runtime header
address and size. For more information, see section 6.10, “The .cormeta
Section (Object Only).”

216/232

8

Reserved, must be
zero

 

具体资料见:www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
中的pecoff.docx文档

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图