解析资源表

本文介绍了PE文件中复杂的资源表,解析过程中涉及的结构体及其属性,包括IMAGE_RESOURCE_DIRECTORY、IMAGE_RESOURCE_DIRECTORY_ENTRY等。资源表结构类似树形,通过高低位判断属性含义,如资源类型、偏移和字符串表示。通过代码解析并验证了资源表的正确性,提供了一个理解资源表的实例。
摘要由CSDN通过智能技术生成

一、资源表简介

资源表是PE所有表里边最复杂的表,造成资源表复杂是有历史原因的,简单说就是微软设计PE的时候错误的以为只要定义16中资源类型就够了,后来发现远远不够,但是PE结构已经定下来了,只能在原有基础上修改,因此就造成了资源表这块比较不好理解。

所谓的不好理解,就是它里边用到的结构,其中的属性会出现位段/位域的用法,同一个4字节,要根据高位判断它到底是一个整数还是一个偏移;然后偏移并不是RVA,而是相对于资源表的偏移。

但是这些并不能难倒我,我花了一天,把解析程序写出来了。
推荐一本书叫《WINDOWS+PE权威指南》,里面详细说明了资源表的结构,我是看着这本书把程序写出来的。

二、资源表结构的分析

资源表的结构有点像树,长这样:
在这里插入图片描述
解析资源表,会涉及到4个结构体,上图包含其中两个,它们分别是:


资源目录 IMAGE_RESOURCE_DIRECTORY

typedef struct _IMAGE_RESOURCE_DIRECTORY {
   
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    WORD    NumberOfNamedEntries;
    WORD    NumberOfIdEntries;
//  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

该结构的 NumberOfNamedEntries 和 NumberOfIdEntries 求和就是紧挨着的资源目录项的数量,其他属性不用管。


资源目录项 IMAGE_RESOURCE_DIRECTORY_ENTRY

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
   
    union {
   
        struct {
   
            DWORD NameOffset:31;
            DWORD NameIsString:1;
        };
        DWORD   Name;
        WORD    Id;
    };
    union {
   
        DWORD   OffsetToData;
        struct {
   
            DWORD   OffsetToDirectory:31;
            DWORD   DataIsDirectory:1;
        };
    };
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

该结构有两个4字节属性,第一个4字节,当高位为1时,低31位存储的是一个偏移,加上资源表的基址,就指向了一个 IMAGE_RESOURCE_DIR_STRING_U 结构,该结构存储了一个Unicode字符串,在第一层,字符串表示资源的名称;在第二层表示资源的非标准命名;在第三层表示非标准代码页。当高位为0时,在第一层低16位表示是16种标准资源类型之一,如ICON;在第二层低16位表示标准命名(预定义的类型);在第三层低16位表示标准代码页,如2052表示简体中文。

第二个4字节属性,在前两层,高位一定是1,在第三层,高位一定是0.
在第一层,低31位表示一个偏移,加上资源表基址就指向了第二层的资源目录 IMAGE_RESOURCE_DIRECTORY;
在第二层,和第一层同理,低31位加上资源表基址指向了第三层的资源目录 IMAGE_RESOURCE_DIRECTORY;
在第三层,低31位是一个偏移,加上资源表基址就指向了一个资源数据项结构 IMAGE_RESOURCE_DATA_ENTRY,该结构存储的是资源的RVA和大小。


Unicode字符串结构体 IMAGE_RESOURCE_DIR_STRING_U

typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
   
    WORD    Length;
    WCHAR   NameString[ 1 ];
} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;

该结构体存储的是一个Unicode字符串的起始地址,和这个字符串的长度,该结构定义的字符串不以0结尾。


资源数据项 IMAGE_RESOURCE_DATA_ENTRY

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
   
    DWORD   OffsetToData;
    DWORD   Size;
    DWORD   CodePage;
    DWORD   Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

存储了资源的RVA和大小。


三、代码

上面的文字说明写得太烂了,还是用代码说明吧?代码写得也烂,但是至少用LordPE验证过解析结果是对的。

// 打印资源表
VOID PrintResourceTable
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值