• 小甲鱼PE详解之资源(PE详解11)


    原文出自:www.fishc.com

    最近一直在安排第一届鱼C 学习班的事情,忙活了好一阵子,真是对不住大家,还大家久等了,这里要跟大家说声不好意思 ^_^

    今天我们来谈谈资源部分,资源部分可以说是 PE 文件所有结构中,最复杂的一部分,也最让人揪心。很多朋友都想通过自己动手修改一些游戏的资源、工具的界面、或者一些软件的图标等,都知道要改资源部分。但纯粹一进去就像走进了迷宫……出不来……

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


    小甲鱼PE详解之资源(PE详解11)

    我们知道,Windows 将程序的各种界面定义为资源,包括加速键(Accelerator)、位图(Bitmap)、光标(Cursor)、对话框(Dialog Box)、图标(Icon)、菜单(Menu)、串表(String Table)、工具栏(Toolbar)和版本信息(Version Information)等。

    为了吸引大家的兴趣和目光,咱先来做个学前试验,然后再憧憬一下我们将来学习的内容有啥意义!好,小甲鱼先来演示一下如何用工具来修改资源实现汉化、改图 标等,接着我们进一步从原理上来解剖 PE文件如何对资源进行存放和索引。最后,在 PE系列章节讲解完毕后,小甲鱼和大家将所有学到的知识结合在一起,我们自己打造属于我们的个性 PE工具。

    试验对象:360zip(实在找不到几个鸟文软件,我们就随便改改,不做汉化了,做“英化”^_^)
    所需工具:Resource Hacker,eXeScope(附件提供下载
    小小演示:请看视频哈 @_@


    资源结构

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




    我们知道我们的资源有很多种类型,每种类型的资源中可能存在多个资源项,这些资源项用不同的ID 或者名称来区分。但是要将这么多种类型的不同ID 的资源有序地组织起来是一件非常痛苦的事情,因此,我们采取类似于磁盘目录结构的方式保存。

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


    资源目录结构

    数据目录表中的 IMAGE_DIRECTORY_ENTRY_RESOURCE 条目(第三项)包含资源的 RVA 和大小。资源目录结构中的每一个节点都是由 IMAGE_RESOURCE_DIRECTORY 结构和紧跟其后的数个IMAGE_RESOURCE_DIRECTORY_ENTRY 结构组成的。(是不是有点像我们之前提到的文件目录?文件夹每个都长得一样,一个嵌套另一个,这样子可以实现将非常复杂的数据细化切分,小泽玛利亚、苍井空、吉泽明步、松岛枫……)

    我们再来看这张图:



    认识了这层关系后,我们来看下 IMAGE_RESOURCE_DIRECTORY 这个结构,该结构长度为 16 字节,共有 6 个字段,定义如下:

    IMAGE_RESOURCE_DIRECTORY STRUCT

    Characteristics        DWORD      ?   ;理论上为资源的属性,不过事实上总是0
    TimeDateStamp      DWORD      ?   ;资源的产生时刻
    MajorVersion          WORD        ?   ;理论上为资源的版本,不过事实上总是0
    MinorVersion          WORD        ?
    NumberOfNamedEntries  WORD     ?   ;以名称(字符串)命名的入口数量
    NumberOfIdEntries         WORD     ?   ;以ID(整型数字)命名的入口数量

    IMAGE_RESOURCE_DIRECTORY ENDS

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


    资源目录入口的结构(
    IMAGE_RESOURCE_DIRECTORY_ENTRY

    IMAGE_RESOURCE_DIRECTORY_ENTRY 紧跟在资源目录结构后,此结构长度为 8 个字节,包含 2 个字段。该结构定义如下:

    IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT

    Name                  DWORD    ?   ;目录项的名称字符串指针或ID
    OffsetToData        DWORD    ?   ;目录项指针

    IMAGE_RESOURCE_DIRECTORY_ENTRY ENDS

    Name 字段完全是个百变精灵,改字段定义的是目录项的名称或ID。当结构用于第一层目录时,定义的是资源类型;当结构定义于第二层目录时,定义的是资源的名称;当结构用于第三层目录时,定义的是代码页编号。

    注意:当最高位为 0  的时候,表示字段的值作为 ID 使用;而最高位为 1 的时候,字段的低位作为指针使用(资源名称字符串是使用 UNICODE编码),但是这个指针不是直接指向字符串哦,而是指向一个 IMAGE_RESOURCE_DIR_STRING_U 结构的。
    该结构定义如下:
    IMAGE_RESOURCE_DIR_STRING_U STRUCT

    Length             DWORD       ?   ; 字符串的长度
    NameString      DWORD       ?   ; UNICODE字符串,由于字符串是不定长的。由Length 制定长度

    IMAGE_RESOURCE_DIR_STRING_U ENDS

    OffsetOfData 字段是一个指针,当最高位为 1 时,低位数据指向下一层目录块的其实地址;当最高位为 0 时,指针指向 IMAGE_RESOURCE_DATA_ENTRY 结构。

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

    最后,在上图中我们看到,在第一层的时候,
    IMAGE_RESOURCE_DIRECTORY_ENTRY的Name 字段作为资源类型使用。

    具体类型匹配见下表:




    资源数据入口

    经 过三层 IAMGE_RESOURCE_DIRECTORY_ENTRY (一般是3层,偶尔更年期少一些。第一层资源类型,第二层资源名,第三层是资源的 Language),第三层目录结构中的 OffsetOfData 指向 IMAGE_RESOURCE_DATA_ENTRY 结构。该结构描述了资源数据的位置和大小,定义如下:

    IMAGE_RESOURCE_DATA_ENTRY STRUCT

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

    IMAGE_RESOURCE_DATA_ENTRY ENDS

    千山万水,此处的 
    IMAGE_RESOURCE_DATA_ENTRY 结构就是真正的资源数据了。结构中的OffsetOfData 指向资源数据的指针,其为 RVA 值。


    资源结构实例分析(具体过程将在视频中演示,这里不再罗嗦^_^)

    工具:PEinfo.exe, UltraEdit

  • 相关阅读:
    敏捷开发系列学习总结(5)——这几招搞定团队协同Coding
    敏捷开发系列学习总结(4)—Git管理工具sourcetree的安装
    Java基础学习总结(74)——Java常见笔试题及答案汇总
    iOS 极光推送
    iOS UI控件没有显示时的调试技巧
    iOS 搜索之拼音搜索
    iOS MJExtension框架之字典数组转模型数组
    iOS 单例
    iOS 切换键盘
    iOS 正则表达式
  • 原文地址:https://www.cnblogs.com/zheh/p/4008270.html
Copyright © 2020-2023  润新知