很多朋友都想通过自己动手修改一些游戏的资源、工具的界面、或者一些软件的图标等,都知道要改资源部分。但纯粹一进去就像走进了迷宫……出不来……

虽然说是迷雾重重,但是本节的学习确意义非凡,例如我们可以对游戏进行汉化!怎么样?刺激吧?给力吧?我们可以自己汉化我们喜欢的**游戏哦!

资源结构

资源是PE文件中非常重要的部分,几乎所有的PE文件中都包含着资源,与导入表和导出表相比,资源的组织方式要复杂很多,其实我们只要看下图就好了:

从图中可以看到,PE文件中的资源是按照:
资源类型->资源ID->资源代码页
的3层树型目录结构来组织资源的,通过层层索引才能够进入相应的子目录找到正确的资源

资源目录结构

资源在PE中是以目录的形式存在的,一般有3层:资源类型,目标资源ID与资源代码页都是以IMAGE_RESOURCE_DIRECTORY结构为头部的,并且后面跟着一个IMAGE_RESOURCE_DIRECTORY_ENTRY结构数组。

IMAGE_RESOURCE_DIRECTORY,负责指出后面数组中的成员个数
IMAGE_RESOURCE_DIRECTORY_ENTRY,数组成员分别指向下一层目录结构

请看下图:
一般为三层 :第一层资源类型,第二层是资源名,第三层是资源代码页

IMAGE_RESOURCE_DIRECTORY结构

该结构长度为167字节,共6个字段,定义如下:

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

其实在这里面我们唯一要注意的就是NumberOfNamedEntriesNumberOfIdEntries,它们说明了本目录中目录项的数量。两者加起来就是本目录中的目录项总和。也就是后边跟着的_IMAGE_RESOURCE_DIRECTORY_ENTRY

资源目录入口结构(_IMAGE_RESOURCE_DIRECTORY_ENTRY)

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结构 (结构体一)

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 结构。

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

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

资源数据入口

经 过三层 IAMGE_RESOURCE_DIRECTORY_ENTRY (一般是3层。第一层资源类型第二层资源名第三层是资源的 Language),第三层目录结构中的 OffsetOfData 指向 IMAGE_RESOURCE_DATA_ENTRY 结构。该结构描述了资源数据的位置和大小,定义如下
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 结构就是真正的资源数据了。结构中的OffsetTodata指向资源数据的指针,其为 RVA 值



例子:
软件:QQ,PEinfo.exe, UltraEdit.exe, eXeScope.exe

1:PEinfo.exe打开QQ

上图中rva=4000
落在了rsrc区块中

计算硬盘的物理地址为:4000-4000+1e00=1e00

2:UltraEdit打开QQ
搜索1e00的地址

————————————————第一层:—————————————————————-

IMAGE_RESOURCE_DIRECTORY STRUCT (1e00起点)
{
+00 h DWORD Characteristics         0000 0000       理论上为资源的属性,不过事实上总是0
+04 h DWORD TimeDateStamp           0000 0000       资源的产生时刻
+08 h WORD MajorVersion             0004            理论上为资源的版本,不过事实上总是0
+0A h WORD MinorVersion             0000
+0C h WORD NumberOfNamedEntries     0000            以名称(字符串)命名的入口数量(重要)
+0E h WORD NumberOfIdEntries        0008(有8个跟班)             以ID(整型数字)命名的入口数量(重要)
}IMAGE_RESOURCE_DIRECTORY ENDS

一.1.–>有下一层

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1e10)
{
+10 h DWORD Name           0000 0003(图标)  目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData   8000 0050        目录项指针,高位为1时指向子结构体二(8的二进制是1000H,1e00+50=1e50)(有下一层)
};IMAGE_RE

一.2.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
+10 h DWORD Name 0000 0004(菜单) ; 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 00a0 ; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.3.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1e20)
{
+10 h DWORD Name 0000 0005(对话框) ; 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 00b8 ; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.4.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
+10 h DWORD Name 0000 0006(字符串) ; 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 00d0 ; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.5.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1e30)
{
+10 h DWORD Name 0000 0009(加速键); 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 00e8; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.6.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
+10 h DWORD Name 0000 000e(版本信息); 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 0100; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.7.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1e40)
{
+10 h DWORD Name 0000 0010(自定义); 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 0118; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

一.8.–>有下一层
IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
+10 h DWORD Name 0000 0018(自定义); 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 0130; 目录项指针,高位为1时指向子结构体二
};IMAGE_RE

————————————————第二层:—————————————————————-
(第一层的第1个)

(一.1.二.)->第一层的第1个的第二层–>有下一层
IMAGE_RESOURCE_DIRECTORY STRUCT (1e50起点)
{
+00 h DWORD Characteristics 0000 0000 理论上为资源的属性,不过事实上总是0
+04 h DWORD TimeDateStamp 0000 0000 资源的产生时刻
+08 h WORD MajorVersion 0004 理论上为资源的版本,不过事实上总是0
+0A h WORD MinorVersion 0000
+0C h WORD NumberOfNamedEntries 0000 以名称(字符串)命名的入口数量(重要)
+0E h WORD NumberOfIdEntries 0008(有8个图标!!好多) 以ID(整型数字)命名的入口数量(重要)
}IMAGE_RESOURCE_DIRECTORY ENDS

(一.1.二.1) ->第一层的第1个的第二层的第1个–>有下一层

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1e60)
{
+10 h DWORD Name           0000 0001(光标)  目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData   8000 0148        目录项指针,高位为1时指向子结构体二(8的二进制是1000H,1e00+148=1f48)(有下一层)
};IMAGE_RE

(一.1.二.2) ->第一层的第1个的第二层的第2个–>有下一层
**IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
{
+10 h DWORD Name 0000 0002(位图) 目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData 8000 0160 目录项指针,高位为1时指向子结构体二(8的二进制是1000H,1e00+168=1f68)(有下一层)
};IMAGE_RE**

(一.1.二.3) ->第一层的第1个的第二层的第3个(1e70)–>有下一层
(一.1.二.4) ->第一层的第1个的第二层的第4个–>有下一层
….省略其它的…

(一.1.二.5) ->第一层的第1个的第二层的第5个(1e80)–>有下一层
(一.1.二.6) ->第一层的第1个的第二层的第6个–>有下一层
….省略其它的…

(一.1.二.7) ->第一层的第1个的第二层的第7个(1e90)–>有下一层
(一.1.二.8) ->第一层的第1个的第二层的第8个–>有下一层
….省略其它的…

————————————————第三层:—————————————————————-
(第二层的第1个)
(一.1.二.1.三)->第一层的第1个的第二层的第1个的第三层

IMAGE_RESOURCE_DIRECTORY STRUCT (1f48起点)
{
+00 h DWORD Characteristics         0000 0000       理论上为资源的属性,不过事实上总是0
+04 h DWORD TimeDateStamp           0000 0000       资源的产生时刻
+08 h WORD MajorVersion             0004            理论上为资源的版本,不过事实上总是0
+0A h WORD MinorVersion             0000
+0C h WORD NumberOfNamedEntries     0000            以名称(字符串)命名的入口数量(重要)
+0E h WORD NumberOfIdEntries        0001(有1个跟班)             以ID(整型数字)命名的入口数量(重要)
}IMAGE_RESOURCE_DIRECTORY ENDS

一.1.二.1.三.1 ->第一层的第1个的第二层的第1个的第三层的第1个->没有下一层了~

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT(1f58)
{
+10 h DWORD Name           0000 0409(光标)  目录项的名称字符串指针或ID,高位为1时指向子结构体
+14 h DWORD OffsetToData   0000 02b0        目录项指针,高位为1时指向子结构体二(没有下一层了~~指向了一个地址(1e00+2b0=20b0))
};IMAGE_RE

最终:
一.1.二.1.三.1 所指向的资源:

IMAGE_RESOURCE_DATA_ENTRY STRUCT(20b0)
{
+00 h DWORD OffsetToData    0000 43a0       ; 资源数据的RVA(重要)
+04 h DWORD Size            0000 0128       ; 资源数据的长度(重要)
+08 h DWORD CodePage        0000 04e4       ; 代码页, 一般为0
+0C h DWORD Reserved        0000 0000       ; 保留字段
};IMAGE_RESOURCE_DATA_ENTRY ENDS

因为SectionAlignment是00001000H
FileAlignment 是00000200H 两者不一样,
所以最终的 rva=43a0-4000+1E00=21A0
查找0x21A0之后的128个字节,就是第一个资源 21A0+128=22c8
结论:从21A022c8之间的数据就是第一个资源的二进制代码(就是一个图标)

找到的结果请看下图:

最后再用工具验证一下:
使用eXeScope打开QQ:

所有工具下载地址:点此下载

PE结构-【资源表】Resources Table相关推荐

  1. PE结构延迟加载导入表

    PE体系 PE结构&整体叙述 PE结构&导入表 PE结构&导出表 PE结构&基址重定位表 PE结构&绑定导入实现 PE结构&延迟加载导入表 简介 延迟加 ...

  2. PE结构基址重定位表

    PE体系 PE结构&整体叙述 PE结构&导入表 PE结构&导出表 PE结构&基址重定位表 PE结构&绑定导入实现 PE结构&延迟加载导入表 重定位表定位 ...

  3. 手写PE结构解析工具

    PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如 ...

  4. WindowsPE 第七章 资源表

    资源表 在程序设计中,总会设计一些数据.这些数据可能是源代码内部需要用到的常量,菜单选项.界面描述等:也可能是源代码外部的,比如程序的图标文件.北京音乐文件.配置文件等,以上这些数据统称为资源.按照程 ...

  5. PE结构绑定导入实现

    PE体系 PE结构&整体叙述 PE结构&导入表 PE结构&导出表 PE结构&基址重定位表 PE结构&绑定导入实现 PE结构&延迟加载导入表 简介 作用 ...

  6. 23. PE结构-PE详解之输出表(导出表)

    为每一个程序写一个相同的函数看起来似乎有点浪费空间,因此Windows就整出了动态链接库的概念,将一些常用的函数封装成动态链接库,等到需要的时候通过直接加载动态链接库,将需要的函数整合到自身中,这样就 ...

  7. Windows PE资源表编程(枚举资源树)

    资源枚举 写一个例子,枚举一个PE文件的资源表.首先说下资源相关的作为铺垫. 1.资源类型也是PE可选头中数据目录的一种.位于第三个类型. 2.资源目录分为三层.第四层是描述文件相关的.这些结构是按照 ...

  8. 25. PE结构-PE详解之资源

    资源结构 资源是PE 文件中非常重要的部分,几乎所有的PE 文件中都包含着资源,与导入表和导出表相比,资源的组织方式要复杂很多,其实我们只要看下图就知道俺所言不虚. 分3级:1 资源类型 ,2 资源I ...

  9. 【Android 安装包优化】资源混淆 ( resources.arsc 资源映射表文件格式 | 头文件 数据格式 | 全局字符串池 数据格式 | 包数据 数据格式 | 包头 数据格式 )

    文章目录 一.resources.arsc 资源映射表文件格式 二.头文件 数据格式 三.全局字符串池 数据格式 四.包数据 数据格式 1.包头 数据格式 2.资源类型字符串池 数据格式 3.资源名称 ...

最新文章

  1. python3爬虫基础学习
  2. 苹果xr如何截屏_苹果手机自带的三种截屏技巧,你知道几个?现在知道还不迟...
  3. JFrog Container Registry 搭建Docker镜像仓库 (docker 版本)
  4. visual studio 代码分析利器 FxCop
  5. 企业级生产环境CICD入门
  6. Java打卡Day4-算术运算符
  7. 板绘萌新拿到数位板之后,不知道先做什么?这些板绘学习小技巧必须要知道
  8. 汽车行业(车厂)常见英文缩写及其中文含义(不断完善中)
  9. 自己退出微信小程序开发者权限
  10. win7文件和文件夹可以重名吗_怎么取消WIN7复制同名文件自动重命名
  11. C++核心编程笔记整理
  12. win10的ie保存html文件夹,win10系统IE缓存文件夹在哪里,详细教您IE缓存文件在哪里...
  13. python 指定值的位置_python数组查找某个值的位置
  14. matlab图上面加箭头,利用matlab如何在图形中绘制箭头
  15. 解决报错:org/springframework/util/backoff/BackOff
  16. 电脑计算机睡眠时间设置为永不熄灭后,电脑仍会熄屏,重新唤醒时出现在登录界面怎么办?
  17. ImportError: /home/yang/anaconda3/envs/sar/bin/../lib/libgio-2.0.so.0: undefined symbol: g_unix_get_
  18. 测绘程序设计——基础篇(1)C#编写方位角计算程序篇1——用户界面的构造
  19. 远程服务器架构,.NET远程处理框架详解
  20. SolidWorks工程图中材料明细表的一些操作

热门文章

  1. 一句话总结—打发无聊的时间
  2. vue——前置路由守卫
  3. 联发科营收复苏,但重回辉煌不容易
  4. linux kernel 配置(部分) 部分内容翻译自内核帮助文档
  5. python 中使用 shutil 实现文件或目录的复制、删除、移动
  6. 例1-反转一个三位整数
  7. 微信小程序 — 长列表组件 recycle-view 详细教学
  8. php入门级基础语法知识
  9. uniCloud发起小票打印,uniapp小票打印实现方案
  10. 黑科技!你知道,小米MIX2如何把听筒塞入一条细缝?