资源表

在程序设计中,总会设计一些数据。这些数据可能是源代码内部需要用到的常量,菜单选项、界面描述等;也可能是源代码外部的,比如程序的图标文件、北京音乐文件、配置文件等,以上这些数据统称为资源。按照程序与数据分离的设计思想,最理想的方案是单独为程序所需要的数据安排一节来存储-PE中的资源就是这么做的。

7.1资源分类

资源数据在PE里是最复杂的一种。其难度主要体现在对资源数据的遍历定位上,以及资源块的不易阅读性。因为即使通过信息定位方法找到了资源块,其内部结构还需要进一步解析。首先来看资源分类的历史。

刚开始资源类型方面,以为16个种类足以了,然而后来发现并不够,这类问题再之前很容易理解。就如千年虫问题...

程序中常用的六类资源包括:

位图资源、光标资源、图标资源、菜单资源、对话框资源、自定义资源。

7.1.1  位图、光标、图标资源

位图、光标和图标是标识程序用途、修饰程序的最简约的符号,一般对应ico、cur、ani和bmp文件内容。这三种资源最终都是基于图片文件。在对资源脚本文件进行定义时,通常使用文件名,最后由资源编译器rc.exe将像素数据读入,在转化为二进制格式存储在PE的资源表指向的位置。位图、光标、图标这三类资源在脚本文件中的定义格式如下:

7.1.2  菜单资源

菜单资源是大部分应用程序都具备的资源。在资源脚本文件中,菜单的定义格式如下所示:

菜单ID MENU [DISCARDABLE]

BEGIN

菜单项定义

......

END

7.1.3  对话框资源

对话框也是大部分程序具备的一种资源。弹出式对话框人性化地排列着文本框、说明文字和按钮等可视化控件,使复杂的计算机操作变得容易。语法如下:

对话框ID DIALOG[DISCARDABLE] x坐标,y坐标,宽度,高度[options]

BEGIN

子窗口控件1

子窗口控件2

......

END

对话框的可可选属性及描述:

7.1.4  自定义资源

通常,当开发者需要在PE文件中附带自定义数据时,可以使用自定义资源。其在资源文件中的定义语法如下:

资源ID    类型ID  [DISCARDABLE]

BEGIN

数据定义

......

END

大部分情况下,都是讲一个磁盘文件当做资源的内容。此时的语法简化为:

资源ID 类型ID [DISCARDABLE] 文件名

类型ID可以是大于255的数值或字符串,如可以定义如下自定义资源:

7.2  PE资源表组织

这节主要说PE文件中资源数据的组织方式,并通过实例介绍针对资源数据定义的数据结构以及在PE中定位资源表的方法。

7.2.1  资源表的组织方式

PE的资源组织方式类似于操作系统的文件管理方式。从根目录开始,下设一级子目录、二级子目录和三级子目录;三级子目录下才是文件。其三级目录结构如下:

一级子目录按照资源类型分类。

二级子目录按照资源ID分类。

三级子目录按照资源代码页分类。

三级子目录后即为节点,也就是所说的文件。这里的文件其实就是包含了资源数据的指针和大小等信息的一个数据结构而已。对于所有资源数据块的访问均可以从这里开始。

由于一、二、三级目录的数据结构是相同的,均是由一个资源目录头加上多个现行跟随着的资源目录项组成,将主干和枝干的节点成为资源目录结构单元。如下图:

从数据结构的角度来看,资源表示一个四层的儿茶排序树结构。其中,第一层为主干,第二、三层为枝干,叶子节点为第四层。主干和枝干的节点即为资源目录结构单元,完整示意图如下:

7.2.2  资源表数据定位

资源表是一张描述资源数据在PE中的分布情况的表。资源表是数据目录中注册的数据类型之一,其描述信息位于数据目录第3个目录项中。

7.2.3  资源目录头IMAGE_RESOURCE_DIRECTORY

资源表数据从第一级资源目录开始。资源的每一级目录都会有一个资源目录头,它标识了该类资源的属性、创建日期和版本等信息,其中也包含了随后的目录项的数量描述信息。

详细结构定义如下:

然后是结构详解:

73.MAGE_RESOURCE_DIRECTORY.Characteristics

+0000h,双字。资源属性,保留为将来使用,必须为0。

74.MAGE_RESOURCE_DIRECTORY.TimeDateStamp

+0004h,双字。时间戳,即创建该资源的时间。

75.MAGE_RESOURCE_DIRECTORY.MajorVersion/MinorVersion;

+0008h,双字。资源版本号。未用,大部分情况为0。

76.MAGE_RESOURCE_DIRECTORY.NumberOfNamedEntries

+000ch,双字。以名称命名的资源个数。

77.MAGE_RESOURCE_DIRECTORY.NumberOfIdEntries

+000eh,双字。以ID命名的资源个数。

以上字段中,最重要的是76和77两个字段。在资源脚本文件中,定义资源时,既可以使用字符串作为名称来标识一个资源,也可以通过ID号来标识资源。资源目录项的数量等于两者之和。

7.2.4资源目录项IMAGE_RESOURCE_DIRECTORY_ENTRY

紧跟在资源目录后的数据结构,就是在资源目录中声明的资源目录项。一个资源目录可能有多个资源目录项(以名称定义的资源目录项或以ID定义的资源目录项,或两者组合),目录项和目录项之间是线性排列的。首先按照字母升序(不区分大小写)排列名称资源目录项,然后再按照ID升序排列资源目录项。下图是资源目录项及目录项之间的关系示意图。

资源目录项数据结构的详细定义如下:

上面有一个union定义,我也是第一次看到这个类型,百度了一下:

78.IMAGE_RESOURCE_DIRECTORY_ENTRY.Namee1

+0000h,双字。第一个union字段,它定义了目录项的名称或者ID。

该双字的高位(即31位)如果为1,则表示低地址部分为一个纸箱Uniconde字符串的指针(注意,这里的字符串不是Ansi字符串,所以另有规定);如果为0,则表示该字段为一个编号。

资源中对字符串的定义全部采用Unicode编码,该指针并不是直接指向一个以“\0”结尾的字符串所在地址,而是指向了结构IMAGE_RESOURCE_DIR_STRING_U。

该结构完善了指针的定义(即不仅包含指针,还包含指针纸箱的块的长度),其详细结构如下:

79.IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData

+0004h,双字。这个字段是一个指针,当它的高位(第31位)为0时,指针指向的是描述资源数据块的指针,通常出现在第三级目录中;当高位为1时,地位数据指向下一级目录快的起始地址。

提示:字段78、79中的地址并不是基于文件起始地址的,它的偏移是基于资源表的起始位置。一定要清楚这一点,否则在定位资源表的时候会出现错误。

7.2.5  资源数据项IMAGE_RESOURCE_DATA_ENTRY

资源数据项其实就是前面所说的目录-文件中的文件。他是通过三次目录定位后找到的一个数据结构,下图显示了资源数据项与三级目录和最终的资源数据块之间的关系。

第三级目录项中的字段IMAGE_RESOURCE_DIREXTORY_ENTRY.OffsetToData指向了资源数据项,而资源数据项中的OffsetToData字段则指向了资源数据块。

资源数据项的详细结构如下:

80.IMAGE_RESOURCE_DATA_ENTRY.OffsetToData

+0000h,双字。该字段是一个纸箱资源数据块的指针,是一个RVA值,在文件中访问时需要注意转换成文件偏移。此处指向的资源数据块还不是赤裸裸的资源信息,而是附加了一些数据结构的资源快。

81.IMAGE_RESOURCE_DATA_ENTRY.Size1

+0004h,双字。资源数据的大小。

82.IMAGE_RESOURCE_DATA_ENTRY.CodePage

+0008h,双字。代码页,未用,大多数情况下为0.

83.IMAGE_RESOURCE_DATA_ENTRY.Reserved

+000ch,双字。保留字段。总是0。

对资源表的大部分编程,只要能解析出该结构中制定资源快所处的地址和资源快的大小,资源表的使命也就算完成了。

7.2.6  三级结构中目录项的区别

由于目录处的级别不同,目录中各字段所表述的内容也不一样;尽管他们具有相同的数据结构和完全相同的字段,在不同级别的目录项中有些数字段的含义是不一样的。

1.IMAGE_RESOURCE_DATA_ENTRY.Name1

(1)字段最高位(即31位)为1

当结构用于第一层目录时,表示这是一个非标准的类型。

当结构用于第二层目录时,表示这是一个非标准的命名。

当结构用于第三层目录时,表示这是一个非标准的语言。

(2)字段31位为0

当结构用于第一层目录时,表示这是一个标准的类型。

当结构用于第二层目录时,表示这是一个标准的命名。

当结构用于第三层目录时,表示这是一个标准的语言。

2.IMAGE_RESOURCE_DATA_ENTRY.OffsetToData

(1)字段第31位为1

当结构用于第一层目录时,下一级目录地址。

当结构用于第二层目录时,下一级目录地址。

当结构用于第三层目录时,第31位不为0。

(2)字段第31位为0

第一层,第二层的这一位都不为0。

  当结构用于第三层目录时,表示该字段指向一个数据项IMAGE_RESOURCE_DATA_ENTRY。

注意:由低31位组成的地址是基于资源起始地址的。

WindowsPE 第七章 资源表的更多相关文章

  1. SQL笔记-第七章,表连接

    SQL中使用JOIN 关键字来使用表连接.表连接有多种不同的类型,被主流数据库系统支持的有交叉连接(CROSS JOIN).内连接(INNER JOIN).外连接(OUTTER JOIN),另外在有的 ...

  2. 第七章 资源在Windows编程中的应用 P157 7-8

    资源在基于SDK的程序设计中的应用实验 一.实验目的 1.掌握各种资源的应用及资源应用的程序设计方法.   二.实验内容及步骤 实验任务 1.熟悉菜单资源的创建过程: 2.熟悉位图资源的创建: 3.熟 ...

  3. 【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

    原文:[原创]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)-托管资源优化-监测CLR性能 构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测C ...

  4. 第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表、课程章节表、课程视频表、课程资源表

    第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表.课程章节表.课程视频表.课程资源表 创建名称为app_courses的 ...

  5. 2017.2.28 activiti实战--第七章--Spring容器集成应用实例(五)普通表单

    学习资料:<Activiti实战> 第七章  Spring容器集成应用实例(五)普通表单 第六章中介绍了动态表单.外置表单.这里讲解第三种表单:普通表单. 普通表单的特点: 把表单内容写在 ...

  6. apue第七章学习总结

    apue第七章学习总结 1.main函数 程序是如何执行有关的c程序的? C程序总是从main函数开始执行.main函数的原型是 int main(int argc,char *argv[]); 其中 ...

  7. 第七章——DMVs和DMFs(3)——用DMV和DMF监控TempDB

    原文:第七章--DMVs和DMFs(3)--用DMV和DMF监控TempDB 前言: 我们都知道TempDB是SQLServer的系统数据库,且SQLServer的日常运作严重依赖这个库.因此,监控T ...

  8. Linux内核分析——第七章 链接

    第七章——链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载到存储器并执行. 2.链接可以执行于编译时,加载时,运行时. 7.1编译器驱动程序 1.大多数编译系 ...

  9. 【黑金原创教程】【TimeQuest】【第七章】供源时钟与其他

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

随机推荐

  1. #String类简述(小白理解,小白编写,欢迎大神指点,小白跪谢)

    @ 目录 一.前言(可忽略) 二.String变量的认知 三.String类的构造方法 四.String类的基本方法 4.1 toString()方法 4.2 equals()方法 4.3 equal ...

  2. 读 Kafka 源码写优雅业务代码:配置类

    这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一剑! 往期文章 Kafka 探险 ...

  3. Java 并发编程之 Condition 接口

    本文部分摘自<Java 并发编程的艺术> 概述 任意一个 Java 对象,都拥有一个监视器方法,主要包括 wait().wait(long timeout).notify() 以及 not ...

  4. idea自制模板代码快捷键

    一:/** 方法描述 /*** 功能描述: * @param: $param$ * @return: $return$ * @auther: $user$ * @date: */二./c** 类描述 ...

  5. Python内置函数作用及解析

    Python内置的函数及其用法.为了方便记忆,已经有很多开发者将这些内置函数进行了如下分类: 数学运算(7个)    类型转换(24个)    序列操作(8个)    对象操作(7个)    反射操作 ...

  6. python之Click的简单应用

    一.介绍 Click是一个Python包,用于以可组合的方式创建漂亮的命令行界面,只需要很少的代码.这是"命令行界面创建工具包".它具有高度可配置性,但具有开箱即用的合理默认值. ...

  7. IaaS, PaaS和SaaS的区别

    从小型企业到全球企业,云都是一个非常热门的话题,它是一个非常广泛的概念,涵盖了很多在线领域. 无论是应用程序还是基础架构部署,当您开始考虑将业务转移到云时,了解各种云服务的差异和优势比以往任何时候都更 ...

  8. 7、MyBatis教程之分页实现

    8.分页实现 1.limit实现分页 思考:为什么需要分页? 在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使 ...

  9. mysql数据库忘记密码时如何修改密码

    方法/步骤  1.进入 mysql 的 bin 目录下,打开 cmd ,在此之前关闭mysql服务,并且结束mysqld.exe进程                                  ...

  10. 「HTML+CSS」--自定义加载动画【009】

    前言 Hello!小伙伴! 首先非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 哈哈 自我介绍一下 昵称:海轰 标签:程序猿一只|C++选手|学生 简介:因C语言结识编程,随后转入计算机 ...