PE知识汇总(一)
PE知识汇总(二)
PE知识汇总(三)
资源用类似于磁盘目录的方式保存,目录通常包含3层。
NumberOfNamedEntries字段是以字符命名的资源数量,NumberOfIdEntries字段是以整型数字命名的资源数量。两者加起来是本目录中的目录项总和,即紧随其后的IMAGE_RESOURCE_DIRECTORY_ENTRY结构的数量。
资源目录入口结构
紧跟资源目录结构的就是资源目录入口(Resource Dir Entries)结构,此结构长度为8字节,包含2个字段。
Name:
当结构用于第一层目录时,定义的是资源类型;当结构用于第二层目录时,定义的是资源的名称;当结构用于第三层目录,定义的是代码页的编号。当最高位为0时,表示字段的值作为ID使用;当最高位为1时,表示字段的低位作为指针使用,这个指针不直接指向字符串,而是指向一个IMAGE_RESOURCE_DIR_STRING_U结构。定义如下
OffsetToData:
指针。当最高位(位31)为1时,低位数据指向下一层目录块的起始地址;当最高位为0时,指针指向IMAGE_RESOURCE_DATA_ENTRY结构。在将Name和OffsetToData 作为指针时需要注意,该指针从资源区块开始处计算偏移量,并非从RVA开始处计算偏移量。(资源区块地址 + 偏移)
资源数据入口
经过三层IMAGE_RESOURCE_DIRECTORY_ENTRY,第三层目录结构中的OffsetToData将指向IMAGE_RESOURCE_DATA_ENTRY结构。该结构描述了资源数据的位置和大小,其定义如下:
多层结构的指向后,获取资源数据的RVA(OffsetToData)
实例:
测试软件:notepad.exe
使用16进制编辑器打开exe,并且跳转到0xBC00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 05 00
NumberOfNameEntries:1
NumberOfIdEntries:5
即一共存在6个资源项,使用工具查看确实满足6个资源
分别是:
第一项.
00 04 00 80 40 00 00 80
第二项.
02 00 00 00 58 00 00 80
第三项.
03 00 00 00 70 00 00 80
第四项.
0E 00 00 00 E8 00 00 80
第五项.
10 00 00 00 00 01 00 80
第六项.
18 00 00 00 18 01 00 80
以第一个资源项为例
第一项:
00 04 00 80
40 00 00 80
Name = 80000400
高位为1,所以是指向IMAGE_RESOURCE_DIR_STRING_U结构。FileOffset = BC00(资源块开始地址) + 0400 = C000
Length = 03
NameString = "MUI"
OffsetToData = 80000040;指向第二层(BC40)
第一项第二层:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
NumberOfNameEntries:1
NumberOfIdEntries:0
只有1项
01 00 00 00
30 01 00 80
ID = 1
OffsetToData = 80000130;指向第三层(BD30)
第一项第二层第一项第三层:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
NumberOfNameEntries:1
NumberOfIdEntries:0
只有1项
09 04 00 00
E0 02 00 00
ID=409
OffsetToData = 2E0;指向IMAGE_RESOURCE_DATA_ENTRY结构(BEE0)
IMAGE_RESOURCE_DATA_ENTRY结构:
70 E0 02 00 OffsetToData = 02E070
F0 00 00 00 Size = F0
00 00 00 00
00 00 00 00
所以指向资源的RVA为2E070,计算得出FileOffset = 2E070-F000+BC00 = 2AC70,资源大小为F0
通过工具查看:
typedef struct _IMAGE_RESOURCE_DIRECTORY
{
DWORD Characteristics;
/
/
理论上为资源的属性,不过事实上总是
0
DWORD TimeDateStamp;
/
/
资源的产生时刻
WORD MajorVersion;
/
/
理论上为资源的版本,不过事实上总是
0
WORD MinorVersion;
WORD NumberOfNamedEntries;
/
/
以名称(字符串)命名的入口数量
WORD NumberOfIdEntries;
/
/
以
ID
(整型数字)命名的入口数量
} IMAGE_RESOURCE_DIRECTORY,
*
PIMAGE_RESOURCE_DIRECTORY;
typedef struct _IMAGE_RESOURCE_DIRECTORY
{
DWORD Characteristics;
/
/
理论上为资源的属性,不过事实上总是
0
DWORD TimeDateStamp;
/
/
资源的产生时刻
WORD MajorVersion;
/
/
理论上为资源的版本,不过事实上总是
0
WORD MinorVersion;
WORD NumberOfNamedEntries;
/
/
以名称(字符串)命名的入口数量
WORD NumberOfIdEntries;
/
/
以
ID
(整型数字)命名的入口数量
} IMAGE_RESOURCE_DIRECTORY,
*
PIMAGE_RESOURCE_DIRECTORY;
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
DWORD Name;
/
/
目录项的名称字符串指针或
ID
DWORD OffsetToData;
/
/
资源数据偏移地址或子目录偏移地址
}
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
DWORD Name;
/
/
目录项的名称字符串指针或
ID
DWORD OffsetToData;
/
/
资源数据偏移地址或子目录偏移地址
}
IMAGE_RESOURCE_DIR_STRING_U
{
WORD Length;
/
/
字符串长度
WCHAR NameString;
/
/
字符串
}
IMAGE_RESOURCE_DIR_STRING_U
{
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!