• PE文件详解九:资源结构体


    Windows 将程序的各种界面定义为资源,包括加速键(Accelerator)、位图(Bitmap)、光标(Cursor)、对话框(Dialog Box)、图标(Icon)、菜单(Menu)、串表(String Table)、工具栏(Toolbar)和版本信息(Version Information)等。
    资源有很多种类型,每种类型的资源中可能存在多个资源项,这些资源项用不同的ID 或者名称来区分。但是要将这么多种类型的不同ID 的资源有序地组织起来是一件非常痛苦的事情,因此,我们采取类似于磁盘目录结构的方式保存。
    PE 文件中的资源是按照 资源类型 -> 资源ID -> 资源代码页 的3层树型目录结构来组织资源的,通过层层索引才能够进入相应的子目录找到正确的资源。

    资源目录结构:
    数 据目录表中的 IMAGE_DIRECTORY_ENTRY_RESOURCE 条目(第三项)包含资源的 RVA 和大小。资源目录结构中的每一个节点都是由 IMAGE_RESOURCE_DIRECTORY 结构和紧跟其后的数个IMAGE_RESOURCE_DIRECTORY_ENTRY 结构组成的。
    我们再来看这张图:



    IMAGE_RESOURCE_DIRECTORY STRUCT 【资源表位于数据目录表的第三项,共动态分配字节,其中结构体中的成员指出的RVA偏移量都是对于此结构体的地址作为基地址】
    {
    +00 h DWORD Characteristics ; 理论上为资源的属性,不过事实上总是0
    +04 h DWORD TimeDateStamp ; 资源的产生时刻
    +08 h WORD MajorVersion ; 理论上为资源的版本,不过事实上总是0
    +0A h WORD MinorVersion
    +0C h WORD NumberOfNamedEntries ; 以名称(字符串)命名的入口数量
    +0E h WORD NumberOfIdEntries ; 以ID(整型数字)命名的入口数量
    };IMAGE_RESOURCE_DIRECTORY ENDS

    后面紧接着一个结构体,个数由上个结构指出:

    IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
    {
    +10 h DWORD Name ; 目录项的名称字符串指针或ID,高位为1时指向子结构体一
    +14 h DWORD OffsetToData ; 目录项指针,高位为1时指向子结构体二
    };IMAGE_RESOURCE_DIRECTORY_ENTRY ENDS

    Name 字段完全是个百变精灵,改字段定义的是目录项的名称或ID。

    当结构用于第一层目录时,定义的是资源类型;

    当结构定义于第二层目录时,定义的是资源的名称;

    当结构用于第三层目录时,定义的是代码页编号。
    注意:

    当最高位为 0 的时候,表示字段的值作为 ID 使用;

    而最高位为 1 的时候,字段的低位作为指针使用(资源名称字符串是使用 UNICODE编码),但是这个指针不是直接指向字符串,而是指向一个IMAGE_RESOURCE_DIR_STRING_U 结构的。
    子结构体一:

    IMAGE_RESOURCE_DIR_STRING_U STRUCT
    {
    +00 h DWORD Length ; 字符串的长度
    +04 h DWORD NameString ; UNICODE字符串,由于字符串是不定长的。由Length 制定长度
    };IMAGE_RESOURCE_DIR_STRING_U ENDS

    OffsetOfData 字段是一个指针,

    当最高位为 1 时,低位数据指向下一层目录块的其实地址;

    当最高位为 0 时,指针指向 IMAGE_RESOURCE_DATA_ENTRY 结构。


    注意:将 Name 和 OffsetToData 用做指针时需要注意,该指针是从资源区块开始的地方算起的偏移量(即根目录的起始位置的偏移量),不是我们习惯的 RVA 哦。


    最后,在上图中我们看到,在第一层的时候,IMAGE_RESOURCE_DIRECTORY_ENTRY 的Name 字段作为资源类型使用。
    具体类型匹配见下表:



    经 过三层 IAMGE_RESOURCE_DIRECTORY_ENTRY (一般是3层,偶尔少一些。第一层资源类型,第二层资源名,第三层是资源的 Language),第三层目录结构中的 OffsetOfData 指向 IMAGE_RESOURCE_DATA_ENTRY 结构。该结构描述了资源数据的位置和大小,定义如下:
    子结构体二:

    IMAGE_RESOURCE_DATA_ENTRY STRUCT
    {
    +00 h DWORD OffsetToData ; 资源数据的RVA
    +04 h DWORD Size ; 资源数据的长度
    +08 h DWORD CodePage ; 代码页, 一般为0
    +0C h DWORD Reserved ; 保留字段
    };IMAGE_RESOURCE_DATA_ENTRY ENDS


    此处的 IMAGE_RESOURCE_DATA_ENTRY 结构就是真正的资源数据了。结构中的OffsetOfData 指向资源数据的指针,其为 RVA 值

  • 相关阅读:
    POJ 1511
    POJ 1125
    POJ 2240
    POJ 1459
    POJ 1274
    POJ 1789
    POJ 2485,1258
    POJ 1236
    POJ 1273
    Ruby on Rails 观后感
  • 原文地址:https://www.cnblogs.com/qintangtao/p/2857193.html
Copyright © 2020-2023  润新知