PE结构详解---区块表和区块

转自:http://blog.fishc.com/1569.html

让编程改变世界

Change the world by program

 

这一讲我们结合实例来谈谈区块表的定义以及各个属性的含义。

首先,我们先用之前学过的一点知识在二进制文件中手动翻找区块表,这样做的好处是可以使你很快的对PE结构牢记于心。

学来的东西就是能用的东西,不能用的理论是空谈,是瞎扯。

 

这里我们经过千辛万苦终于找到了我们的区块表了(当然将来我会教大家写一个自己的工具,让工具去找,现在让大家自己动手是为了增强感觉!),现在我们联系上一章节提到的区块表的结构对各个成员进行详细的分析:

 

.

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;


Name:

 

区块名。这是一个由8位的ASCII 码名,用来定义区块的名称。

多数区块名都习惯性以一个“.”作为开头(例如:.text),这个“.” 实际上是不是必须的。

值得我们注意的是,如果区块名超过 8 个字节,则没有最后的终止标志“NULL” 字节。

并且前边带有一个“$” 的区块名字会从连接器那里得到特殊的待遇,前边带有“$” 的相同名字的区块在载入时候将会被合并,在合并之后的区块中,他们是按照“$” 后边的字符的字母顺序进行合并的。

 

另外小甲鱼童鞋要跟大家啰嗦一下的是:每个区块的名称都是唯一的,不能有同名的两个区块。

但事实上节的名称不代表任何含义,他的存在仅仅是为了正规统一编程的时候方便程序员查看方便而设置的一个标记而已。

所以将包含代码的区块命名为“.Data” 或者说将包含数据的区块命名为“.Code” 都是合法的。

因此,小甲鱼建议大家:当我们要从PE 文件中读取需要的区块时候,不能以区块的名称作为定位的标准和依据。

正确的方法是按照 IMAGE_OPTIONAL_HEADER32 结构中的数据目录字段结合进行定位。

 

Virtual Size:

对表对应的区块的大小,这是区块的数据在没有进行对齐处理前的实际大小。

 

Virtual Address:

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

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

 

SizeOfRawData:

该区块在磁盘中所占的大小。在可执行文件中,该字段是已经被FileAlignment 潜规则处理过的长度。

 

PointerToRawData:

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

 

PointerToRelocations:

这哥们在EXE文件中没有意义,在OBJ 文件中,表示本区块重定位信息的偏移值。

(在OBJ 文件中如果不是零,它会指向一个IMAGE_RELOCATION 结构的数组)

 

PointerToLinenumbers:

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

 

NumberOfRelocations:

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

 

NumberOfLinenumbers:

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

 

Characteristics:

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

 

小甲鱼以下给大家列举出最常用的一些属性值:

具体内容可以参考MSDN在线文档:传送门


小甲鱼以下给大家列举出最常用的一些属性值:
具体内容可以参考MSDN在线文档:http://msdn.microsoft.com/en-us/library/ms680341%28v=vs.85%29.aspx

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. 该区块可写。

相关文章

文章浏览阅读903次。文章主要介绍了收益聚合器Beefy协议在币...
文章浏览阅读952次。比特币的主要思路是,构建一个无中心、去...
文章浏览阅读2.5k次。虚拟人从最初的不温不火,到现在步入“...
文章浏览阅读1.3k次,点赞25次,收藏13次。通过调查和分析用...
文章浏览阅读1.7k次。这个智能合约安全系列提供了一个广泛的...
文章浏览阅读1.3k次。本文描述了比特币核心的编译与交互方法...