根据PE文件格式我们可以快速找到目录表数组位置,在目录表数组中我们可以找到资源表在哪里
我们看出资源表位置为0x4000,大小为0xb20。
资源表所对应数据结构为IMAGE_RESOURCE_DIRECTORY
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
其中,
5. NumberOfNamedEntries,重要字段,以字符串命名的资源条目的数量;
6. NumberOfIdEntries,重要字段,以整数命名的资源条目的数量;
主要关注最后两个字段:NumberOfNamedEntries与NumberOfIdEntries,两者加起来就是资源表根目录下总的资源条目的数量。
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
DWORD Name;
DWORD OffsetToData;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
该结构体占用8个字节,结构体的成员的介绍如下:
1. Name,这个字段拥有多个不同的含义:当IRDE位于第一层目录时,Name表示资源的类型;当IRDE位于第二层目录时,Name表示资源的名称;当IRDE位于第三层目录时,Name表示代码页的编号。此外,还需要先判断Name的最高位是0还是1,如果是0则表示当做一个值来使用,如果是1,则表示低31位当做指针来使用;
2. OffsetToData,指针;当最高位为1时,表示低位数据指向下一层目录;当最高位为0时,表示没有下一层目录,低位数据指向一个IMAGE_RESOURCE_DATA_ENTRY结构。
注意,当Name和OffsetToData当做指针使用时,其值并不是RVA,而是表示相对于资源区块起始位置的偏移值。
前面提到,当IMAGE_RESOURCE_DIRECTORY_ENTRY位于第一层目录时,它的Name字段表示资源类型,系统预定义的资源类型如下图所示:
IMAGE_RESOURCE_DATA_ENTRY结构体在WinNT.h头文件中的定义如下:
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
IMAGE_RESOURCE_DATA_ENTRY结构体成员的介绍如下:
1. OffsetToData,这是一个RVA,指向真正的资源数据;
2. Size,表示资源的大小;
3. CodePage,代码页,一般为0;
4. Reserved,保留字段,暂时没有意义;
第一层
可以看出第一层有5个IMAGE_RESOURCE_DIRECTORY_ENTRY,我们选取第一个讲解
Name为03,可知为图标资源,OffsetToData高位为1,可知下一层存在,偏移0x38,位于0x4038
可以看出第二层有2个IMAGE_RESOURCE_DIRECTORY_ENTRY,我们依旧选取第一个讲解
Name为01,存在下一层,位于0x40c0
可以看出第三层有1个IMAGE_RESOURCE_DIRECTORY_ENTRY
这里的Name表示代码页的编号,OffsetToData最高位为0,可知没有下一层,且大小为0x168,我们在0x4168处找到IMAGE_RESOURCE_DATA_ENTRY结构体
我们可以在0x41e0处找到该资源,大小为0x2e8