前几节,我们已经掌握了DOS头、NT头的内容,我们通过NT头IMAGE_OPTIONAL_HEADER结构的第30字段了解该可执行文件的数据目录表的项目,也了解了该结构的相关字段。接下来我们主要是了解区块表与区块。
区块表紧跟着NT结构,它是一个IMAGE_SECTION_HEADER结构数组。每个结构包含它所关联区块的信息。
typedef struct _IMAGE_SECTION_HEADER
区块表紧跟着NT结构,它是一个IMAGE_SECTION_HEADER结构数组。每个结构包含它所关联区块的信息。
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;
以上是区块表结构的各字段。
从箭头开始的地方就是区块表开始的位置,前面是数据目录表,区块表之后就是各区块的内容了。
关于区块表结构的各字段在上面已经简单的标明,下面解释几个比较重要的字段。
(1)Name:块名,这是一个8位ASCII码名,用来定义块名。前面有个“.”,这是微软的习惯我们不管,实际上这个点并没有什么卵用;
(2)VirtualSize:实际、被使用的区块大小,是区块在没有对齐处理前的实际大小;
(3) VIrtualAddress:该块被装载到内存中的RAV,这个地址是按页对齐的;
(4) SizeOfRawData:该块在磁盘文件中所占的大小;
(5)Characteristics:块属性,主要有以下属性:
IMAGE_SCN_CNT_CODE
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
以上是区块表结构的各字段。
从箭头开始的地方就是区块表开始的位置,前面是数据目录表,区块表之后就是各区块的内容了。
关于区块表结构的各字段在上面已经简单的标明,下面解释几个比较重要的字段。
(1)Name:块名,这是一个8位ASCII码名,用来定义块名。前面有个“.”,这是微软的习惯我们不管,实际上这个点并没有什么卵用;
(2)VirtualSize:实际、被使用的区块大小,是区块在没有对齐处理前的实际大小;
(3) VIrtualAddress:该块被装载到内存中的RAV,这个地址是按页对齐的;
(4) SizeOfRawData:该块在磁盘文件中所占的大小;
(5)Characteristics:块属性,主要有以下属性:
IMAGE_SCN_CNT_CODE
0x00000020
包含代码,常与 0x10000000一起设置。
IMAGE_SCN_CNT_INITIALIZED_DATA
0x00000040
该区块包含以初始化的数据。
IMAGE_SCN_CNT_UNINITIALIZED_DATA
0x00000080
该区块包含未初始化的数据。
IMAGE_SCN_MEM_DISCARDABLE
0x02000000
该区块可被丢弃,因为当它一旦被装入后,进程就不在需要它了,典型的如重定位区块。
IMAGE_SCN_MEM_SHARED
0x10000000
该区块为共享区块。
IMAGE_SCN_MEM_EXECUTE
0x20000000
该区块可以执行。通常当0x00000020被设置时候,该标志也被设置。
IMAGE_SCN_MEM_READ
0x40000000
该区块可读,可执行文件中的区块总是设置该标志。
IMAGE_SCN_MEM_WRITE
0x80000000
该区块可写。
可以通过“|”异或运算,包含更多块属性,例如:E0000020H = 20000000H | 40000000H | 80000000H | 00000020H 表示该块包含执行代码,可读、可写并可执行。
可以通过“|”异或运算,包含更多块属性,例如:E0000020H = 20000000H | 40000000H | 80000000H | 00000020H 表示该块包含执行代码,可读、可写并可执行。