PE文件格式学习(五):资源表_adoqa66822的博客-程序员秘密

1.概述

程序内部和外部的界面等元素的二进制数据统称为资源,程序把它们放在一个特定的表中,符合数据和程序分离的设计原则。

Windows程序中的资源大致分为六类:菜单、对话框、位图、光标、图标、自定义资源

资源表是数据目录表中的第三个元素,排在导入表的后面。

2.资源表解析

资源表的解析比较复杂,可能是所有数据目录表中最复杂的一个。我将结合例子说明,这样会比较好理解。

我们的文件在十六进制工具010editor的帮助下,将PE中的结构全部标记了出来。资源表是数据目录表的第三个,查找到它的RVA是0x4000,转换成offset还是0x4000,找到它的位置如下图所示:

1240

从0x4000开始就是资源表的结构体了,这个结构体叫IMAGE_RESOURCE_DIRECTORY,有如下字段:

struct IMAGE_RESOURCE_DIRECTORY
{
    DWORD Characteristics;
    DWORD  TimeDateStamp;
    WORD MajorVersion;
    WORD  MinorVersion;
    WORD  NumberOfNamedEntries;
    WORD  NumberOfIdEntries;
}

Characteristics:属性,一般为0,对应上图中的0x00000000

TimeDateStamp:时间戳,一般为0(前面说过文件头也有这个字段,导出表、导入表都有这个字段,都有值,在这里很多时间为0),对应上图中的0x00000000

MajorVersion:资源的版本,一般为0,对应上图中的0x0000

MinorVersion:一般为0,对应上图中的0x0000

NumberOfNamedEntries:以字符串命名的资源数量,对应上图中的0x0000

NumberOfIdEntries:以整型数字命名的资源数量,对应上图中的0x0003

上图中NumberOfNamedEntries和NumberOfIdEntries的和是0x3,表明这个程序有3个资源项目,也就是说紧跟着IMAGE_RESOURCE_DIRECTORY结构体的有3个IMAGE_RESOURCE_DIRECTORY_ENTRY结构,这里展示一下IMAGE_RESOURCE_DIRECTORY_ENTRY结构体:

struct IMAGE_RESOURCE_DIRECTORY_ENTRY
{
     DWORD Name;
     DWORD OffsetToData;
}

Name:对应上图中的0x00000003(第一个IMAGE_RESOURCE_DIRECTORY_ENTRY),当它的最高位是1的时候,表示低位作为一个指针使用,指向IMAGE_RESOURCE_DIR_STRING_U结构;当它的最高位是0的时候,分为三种情况:当结构用于第1层目录时定义的是资源类型,用于第2层目录时定义的是资源ID,用于第3层目录时定义的是资源语言类型(0x409表示是英语)。第1层-第3层是什么意思呢?简单的理解就是,资源表的解析分为三层,每一层都是IMAGE_RESOURCE_DIRECTORY+IMAGE_RESOURCE_DIRECTORY_ENTRY的形式,第二个字段OffsetToData的最高位是1的时候就会指向下一层,每一层都是一样的IMAGE_RESOURCE_DIRECTORY和IMAGE_RESOURCE_DIRECTORY_ENTRY的结构,大概是这个样子,后面会更详细的介绍,现在有个印象就好。IMAGE_RESOURCE_DIR_STRING_U的结构体如下:

struct IMAGE_RESOURCE_DIR_STRING_U
{
    WORD Length;
    WCHAR NameString;
}

这个资源的Name是0x00000003,最高位是0,并且它在第一层,也就是说0x00000003代表的是资源类型,那么资源类型又有哪些呢?下表列出了一些类型,所以这个资源是图标。

1240

offsetToData:对应上图的0x80000028,当它的最高位是1的时候,低位数据指向下一层的IMAGE_RESOURCE_DIRECTORY的起始地址,当它的最高位是0的时候,指针指向IMAGE_RESOURCE_DATA_ENTRY结构,这个结构后面会说,它是真正的资源数据的地址,一般情况下,分析到第三层的时候,offsetToData的最高位会是0。值得注意的是offsetToData作为指针的时候(0x80000028),28是从资源块最开始的地方开始计算偏移的,它不是RVA。IMAGE_RESOURCE_DATA_ENTRY的结构体是:

IMAGE_RESOURCE_DATA_ENTRY STRUCT

    OffsetToData DWORD ? ; 资源数据的RVA
    Size1 DWORD ? ; 资源数据的长度
    CodePage DWORD ? ; 代码页, 一般为0
    Reserved DWORD ? ; 保留字段

IMAGE_RESOURCE_DATA_ENTRY ENDS

这个结构体,暂时先不用管它,等分析到第三层的时候再回来看。

先总结一下,我已经分析了第一层的IMAGE_RESOURCE_DIRECTORY,它从0x4000开始,占据16个字节,它的NumberOfNameEntries和NumberOfNameIds的总和是0x3,因此从0x4010开始有3个IMAGE_RESOURCE_DIRECTORY_ENTRY结构体,也就是3个资源,每个结构体占8个字节,所以从0x4010-0x4027是它的内容,这三个结构体的Name字段的最高位都是0,所以它们代表的是类型,分别是0x03图标、0x04菜单、0x0E图标组,它们的OffsetToData字段的最高位是1,所以指向的位置是下一层。

接下来我们找到位置开始分析第二层的内容。

根据第一个资源的OffsetToData的低位字节0x28,我们从0x4000往后数0x28个字节,找到如下图的内容,我们知道OffsetToData这时指向的是第二层的IMAGE_RESOURCE_DIRECTORY结构体。所以它同样是16个字节。

1240

最后的NumberOfIdEntries为0x01,所以它的后面紧跟着一个IMAGE_RESOURCE_DIRECTORY_ENTRY,也就是如下图中所示:

1240

Name字段的最高位是0,我们知道最高位是0,并且Name在第二层代表的是资源ID,所以这个资源的ID是0x01,OffsetToData最高位是1,所以它的最低位指向的是最后一层,也就是第三层。通过0x4000+0x70,我们找到0x4070,这里就是第三层的IMAGE_RESOURCE_DIRECTORY。如下图

1240

我们看到NumberOfIdEntries为0x01,所以第三层也只有一个IMAGE_RESOURCE_DIRECTORY_ENTRY。如下图:

1240

这时我们看到它的第一个元素Name的最高位是0,在第三层Name最高位为0就代表资源语言类型,这时表示的资源语言类型就是0x804,OffsetToData的最高位是0,所以0xB8+0x4000处就是IMAGE_RESOURCE_DATA_ENTRY,如下图:

1240

我们再来回顾一下这个结构体:

IMAGE_RESOURCE_DATA_ENTRY STRUCT

    OffsetToData DWORD ? ; 资源数据的RVA
    Size1 DWORD ? ; 资源数据的长度
    CodePage DWORD ? ; 代码页, 一般为0
    Reserved DWORD ? ; 保留字段

IMAGE_RESOURCE_DATA_ENTRY ENDS

所以资源的RVA是0x4100,转为offset仍然是0x4100,这个资源的起始位置就是这个0x4100,长度是0x2e8。

3.总结

我们还没有碰到IMAGE_RESOURCE_DIRECTORY_ENTRY里面的Name为1的情况,以后可能会补充。资源表的理论说起来很复杂,其实没那么复杂,只要写一遍PE分析工具,在代码中可以更好地理解资源表。

转载于:https://www.cnblogs.com/tutucoo/p/9927334.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/adoqa66822/article/details/102138780

智能推荐

Magento 2.4 迁移导致后台登录出错 Notice: Undefined offset: 2 invendor\magento\Encryptor.php on line 591_CyrusZhou的博客-程序员秘密

问题:Magento 2.4 迁移导致后台登录出错问题Exception #0 (Exception): Notice: Undefined offset: 2 invendor\magento\Encryptor.php on line 591解决方法:进数据库修改管理员密码:命令如下UPDATE admin_user SET password = CONCAT(SHA2('74c7b1dd740c8bbe82fbg8e3f8ce1bc4新密码', 256), ':74c7b1dd74...

Linux下更改MySQL数据库存储路径(实践常用)_廖俊才的博客-程序员秘密

第1步:使用第三方软件SSH或xshell成功登录到centos系统。第2步:home目录下建立data目录,data目录下建立mysql目录第3步:首先停止掉mysql服务,在终端中执行"/etc/init.d/mysql stop" 或者执行"service mysqld stop"并回车确定。第4步: 把/var/lib/mysql整个目录移到/home/data/下...

虚拟机mysql磁盘扩容_虚拟机里的linux主分区扩容_weixin_39622521的博客-程序员秘密

[[email protected] ~]# vgdisplay--- Volume group ---VG Name VolGroupSystem IDFormat lvm2Metadata Areas 1Metadata Sequence No 3VG Access read/writeVG Sta...

用Python实现BT种子转化为磁力链接_Python编程KK的博客-程序员秘密

经常看电影的朋友肯定对BT种子并不陌生,但是BT种子文件相对磁力链来说存储不方便,而且在网站上存放BT文件容易引起版权纠纷,而磁力链相对来说则风险小一些。将BT种子转换为占用空间更小,分享更方便的磁力链还是有挺大好处的。今天咱们来看下如何将种子转换成磁力链接,方案是:利用python的bencode模块,用起来比较简单首先要安装这个模块,安装命令:pip install bencode...

电商项目——商城业务-检索服务——第六章——中篇_福建选手阿俊的博客-程序员秘密

文章目录1:搭建页面环境2:调整页面跳转3:检索查询参数模型分析抽取4:检索返回结果模型分析抽取5:检索DSL测试-查询部分6:检索DSL测试-聚合部分7:SearchRequest构建-检索8:SearchRequest构建-排序,分页,高亮&测试9:SearchRequest构建-聚合10:SearchResponse分析&封装11:验证结果封装正确性12:页面基本数据渲染13:页面筛选条件渲染14:页面分页数据渲染15:页面排序功能16:页面排序字段回显17:页面价格区间搜索18:面包

两步完成利用procdump64+mimikatz获取win用户密码_weixin_33888907的博客-程序员秘密

使用procdump64+mimikatz可实现从内存中获取明文密码工具链接:https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密码:fc38首先得先获取到内存文件lsass.exe进程,它用于本地安全和登陆策略,一般在进程管理器中能看到, 比如这样1.导出lsass.exeprocdump64.exe -acce...

随便推点

Android休眠唤醒驱动流程分析(四)_android休眠唤醒机制分析 四_dadizhiying1215的博客-程序员秘密

关于wake_lock在上文中,已经介绍了wakelock机制,下面从代码的角度进行介绍。wakelock有2种类型,常用为WAKE_LOCK_SUSPEND,作用是防止系统进入睡眠。WAKE_LOCK_IDLE这种锁不会影响到系统进入休眠,但是如果这种锁被持有,那么系统将无法进入idle空闲模式。enum {WAKE_LOCK_SUSPEND, W

【机器学习】(周志华--西瓜书) 真正例率(TPR)、假正例率(FPR)与查准率(P)、查全率(R)_大隐隐于市Ww的博客-程序员秘密

Q:试述真正例率(TPR)、假正例率(FPR)与查准率(P)、查全率(R)之间的联系。查全率: 真实正例被预测为正例的比例真正例率: 真实正例被预测为正例的比例显然查全率与真正例率是相等的。查准率:预测为正例的实例中真实正例的比例假正例率: 真实反例被预测为正例的比例两者并没有直接的数值关系。敏感度,召回率,命中率或真实阳性率(TPR)特异性,选择性或真阴...

第一次运行UVM_记录自己的第一个uvm_xiaomayi1994的博客-程序员秘密

最近在学uvm, 想先试着搭建一个UVM并运行来。记录一下步骤吧我看的书是《UVM实战》并下载了对应的example的源码example_and_uvm_source_code.tar.gz解压之后里面还有两个压缩文件puvm.tar.gz(例程源码)以及uvm-1.1d.tar.gz(UVM库)解压之后进入puvm文件夹,在该路径下有setup.xxx(xxx表示使用的仿真器),我使用的是vcs所以修改setup.vcs脚本。setenv VCS_HOME /opt/vcs/E-201

二、网络安全等级保护制度的前世今生_国际上公认最早提出等级保护的是_vickie2019的博客-程序员秘密

一、开展网络安全等级保护工作的法律依据1994年《计算机信息系统安全保护条例》(第147号)第九条明确规定,“计算机信息系统实行安全等级保护,安全等级的划分标准和安全等级保护的具体办法,由公安部会同有关部门规定”。该条明确了三方面的内容:一是确立等级保护是计算机信息系统安全保护的一项制度;二是出台配套规章和标准;三是明确公安部在等级保护工作中的牵头地位。2017年《网络安全法》第二十一条 国家实行网络安全等级保护制度。网络运营者应当按照网络安全等级保护制度的要求,履行下列安全保护义务,保障网络免受干扰、

c++控制台应用每一列数据如何对齐_懂Excel就能轻松入门Python数据分析包pandas(十六):合并数据..._weixin_39883079的博客-程序员秘密

此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd 转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的)经常听别人说 Python 在数据领域有多厉害,结果学了很长时间,连数据处理都麻烦得要死。后来才发现,原来不是 Python 数据处理厉害,而是他有数据分析神器—— pandas前言本系列上一节说了拆分数据的案例,这次自然是说下怎么合并...

postman接口测试实践_postman项目实践_程序员吾非同的博客-程序员秘密

postman简介Postman是谷歌开发的一款接口测试工具,能够发送任何类型的http请求,支持GET/PUT/POST/DELETE等方法。Postman非常简单易用,可以直接填写URL,header,body等就可以发送一个请求,用来测试api接口非常方便。以前只支持chrome插件现在已经有独立的应用了。postman的优势使用Postman,可以快速构建请求、保存以供以后使用,并分析AP...

推荐文章

热门文章

相关标签