资源表

在程序设计中,总会设计一些数据。这些数据可能是源代码内部需要用到的常量,菜单选项、界面描述等;也可能是源代码外部的,比如程序的图标文件、北京音乐文件、配置文件等,以上这些数据统称为资源。按照程序与数据分离的设计思想,最理想的方案是单独为程序所需要的数据安排一节来存储-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. 无需编程,通过配置零代码生成CRUD RESTful API

    Hello,crudapi!(你好,增删改查接口!) 本文通过学生对象为例,无需编程,通过配置实现CRUD RESTful API. 概要 CRUD简介 crud是指在做计算处理时的增加(Create ...

  2. 【odoo14】第四章、应用模型

    由于本章有包含很多基础知识,个人不会全部转化为自己的语言.直接机器翻译了(用斜体标注,机器翻译反而一字不落,我会过滤掉冗余的内容),虽然机翻,但会保证意思不会偏. 本章主要章节如下: 定义模型展示及顺 ...

  3. IDEA如何像ecplise一样添加jar包?

    以前使用ecplise开发代码,现在换成IDEA,有很多操作都不习惯,比如添加jar包.网上可以找到IDEA好几种添加jar包的方法,这里主要介绍在用IDEA开发时如何像ecplise一样添加jar包 ...

  4. 在Windows10搭建WebAssembly开发环境

    最近研究WebAssembly技术,准备用WebAssembly编译C/C++代码供前端调用.网上看了很多文章,收获很大,现在就遇到的问题做一个记录. 官网关于windows开发环境搭建基本上几句话, ...

  5. 如何使用Typora写博客

    如何写博客及Typora的使用 Typora Typora是写好博客的一个重要的软件,下面我们来介绍如何安装以及使用它 安装 官网下载Typora 较慢,首先附上Typora安装包: 链接:https ...

  6. 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口

    <C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...

  7. Android Studio之圆形按钮设计

    •效果展示图 •实现方法 点击 app/src/main/res 找到 drawable 文件夹,右击->New->Drawable Resource File. 创建一个 $drawab ...

  8. vue 快速入门 系列

    vue 快速入门(未完结,持续更新中...) 前言 为什么要学习 vue 现在主流的框架 vue.angular 和 react 都是声明式操作 DOM 的框架.所谓声明式,就是我们只需要描述状态与 ...

  9. Redis扩展数据类型详解

    在Redis中有5种基本数据类型,分别是String, List, Hash, Set, Zset.除此之外,Redis中还有一些实用性很高的扩展数据类型,下面来介绍一下这些扩展数据类型以及它们的使用 ...

  10. thinkphp添加excel更新数据表数据(优化篇)

    由于主管说使用saveAll更新数据效率太低,要改用sql语句一次执行现在修改 /** * excel开启上传 * author: panzhide * @return array * Date: 2 ...