PE文件之资源表

PE文件之资源表

资源(光标、图标、菜单等)一般写在资源脚本文件中,通过RC编译器进行编译供可执行程序使用。在资源文件中,字符串都以Unicode的形式存储。

在PE文件格式中,这些资源的二进制格式统一放在一个单独的节区中:.rsrc。

如何找到一个程序的资源呢?我们可以通过PE文件可选头中的数据目录的第三项来定位程序资源:

在获取资源块地址的时候,注意不要使用查找".rsrc"节起始地址的方法,虽然在一般情况下资源总是在".rsrc"节中,但这并不是必然的。

得到了资源块的RVA和大小之后,我们就来解析这些字节,看看它们的组织形式。

资源的组织方式

上图很直观地展现了资源的组织方式,三种类型的结构加上资源数据组成了资源块。

资源目录头IMAGE_RESOURCE_DIRECTORY

写过资源脚本文件的都知道,我们可以使用资源名称(字符串)或者资源ID来命名一个资源:

所以IMAGE_RESOURCE_DIRECTORY的最后两项的总和,才是IMAGE_RESOURCE_DIRECTORY下面IMAGE_RESOURCE_DIRECTORY_ENTRY结构的数量。

资源目录项IMAGE_RESOURCE_DIRECTORY_ENTRY

Name1字段

这个字段用于定义资源目录项的名称或者ID,在不同级别的目录中,有着不同的含义:

  1. 一级目录:表示资源的类型
  2. 二级目录:表示资源的名称
  3. 三级目录:表示资源的代码页编号

对于一级目录,该字段作为资源类型的来使用,当资源类型以ID来表示的时候(最高位是0),并且ID的数值在1到16之间,那么这种类型是系统定义的类型,如果ID数值大于16,这是用户自定义的类型:

当字段作为ID使用的时候,是可以放入一个双字的,如果使用字符串定义的时候,一个双字是不够的,这就需要将两种

情况分别对待,区分的方法是使用字段的最高位(位31)。当位31是0的时候,表示字段的值作为ID使用;而位31为1的时候,字段的低位作为指针使用,但由于资源名称字符串是使用UNICODE来编码的,所以这个指针并不直接指向字符串,而是指向一个IMAGE_RESOURCE_DIR_STRING_U结构,这个结构包含UNICODE字符串的长度和字符串本身,其定义如下:

OffsetToData字段

这个字段是一个指针,在不同的级别中也有不同的含义:

  1. 在一二级目录中:当它的最高位(位31)为1时,低位数据指向下一层目录块的起始地址,也就是一个IMAGE_RESOURCE_DIRECTORY结构
  2. 在三级目录中:当字段的位31为0时,指针指向的是用来描述资源数据块情况的IMAGE_RESOURCE_DATA_ENTRY指针

注意,上面两个字段如果表示的是地址,那么这个地址是相对于资源块开始的地方的偏移地址(RESOURCES数据目录项中指定的RVA)。

资源数据项IMAGE_RESOURCE_DATA_ENTRY

结构中的OffsetToData字段的值是指向资源数据的指针,奇怪的是,这个指针却是一个RVA值,而不是以资源块的起始地址为基址的,这是读者需要特别注意的地方。

结构中的第3个字段是CodePage,这个字段的名称有些奇怪,因为当前资源的代码页已经在第3层目录中指明了,在这里再定义一次有重复之嫌,在实际的应用中,这个字段好像未被使用,因为随便找一个PE文件看看就会发现这里的值总是为0。

通过工具解析资源

这里推荐使用Resource Hacker来查看一个程序的资源,该工具还可以编辑程序中的资源:

相关推荐
Hello.Reader5 天前
编译器的六大阶段详解以一行赋值语句为例
编译原理·逆向工程
阿昭L6 天前
浅析64位Windows的SEH机制
windows·逆向工程·seh
阿昭L6 天前
静态反调试技术
逆向工程·反调试
胡耀超12 天前
Web Crawling 网络爬虫全景:技术体系、反爬对抗与全链路成本分析
前端·爬虫·python·网络爬虫·数据采集·逆向工程·反爬虫
阿昭L13 天前
CodePatch hook api
hook·逆向工程
阿昭L15 天前
《逆向工程核心原理》使用调试函数hook api的实验在64位Windows11上的复现
hook·逆向工程
Pure_White_Sword1 个月前
bugku-reverse题目-NoString
网络安全·ctf·reverse·逆向工程
阿昭L2 个月前
PE文件之导入表(一):导入函数调用机制、导入表基本结构
逆向工程·pe文件
Pure_White_Sword2 个月前
bugku-reverse题目-游戏过关
游戏·网络安全·ctf·reverse·逆向工程