PE格式第九讲,资源表解析

一丶熟悉Windows管理文件的方法

首先,为什么标题是这个,主要是为了下边讲解资源方便,因为资源结构体很乱.如果直接拿出来讲解,那么就会很晕.

1.windows管理文件方法

树形结构

可以看出结构

根目录

  子目录

    文件.xxx

  子目录

    子目录 (子目录里面还可以有文件夹)

  .....    

那么我们的资源也是这样存储的.

二丶资源结构体解析

首先,资源结构体分为很多个,但是有用的就3个.一般也分为三个

IMAGE_RESOURCE_DIRECTORY            根目录(资源目录头)
IMAGE_RESOURCE_DIRECTORY_ENTRY         子目录(资源目录项)其中根目录下可以有很多子目录(也就是说根目录下会有子目录的)
IMAGE_RESOURCE_DATA_ENTRY            文件(资源数据)
结构体解析: 1.资源目录头(也可以看做管理文件的根目录)
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;          资源属性
DWORD TimeDateStamp;           时间戳
WORD MajorVersion;            资源大版本号
WORD MinorVersion;            资源小版本号
WORD NumberOfNamedEntries;       按照名称命名的数量
WORD NumberOfIdEntries;         按照ID命名的数量
// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

首先我们看到资源目录头的结构体了,这里大家要知道,有用的就最后两个成员,还有一段注释.

1.按照名称命名的数量

意思就是我们的资源是字符串命名加载的有多少个

2.按照ID命名的数量

意思就是我们的资源如果按照ID有多少个.

一般都是用ID的.

最后两个字段主要是资源的标识,是以ID的有多少个,以字符串标识的有多少个.

2.资源目录项(子目录)

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset:;          位段: 低31位飘逝偏移 定义了目录项的名称或者ID
DWORD NameIsString:;          位段: 高位, 如果这位为1,则表示31位的偏移指向的是一个Unicode字符串的指针偏移
};                       这里列出结构体,自己去看,IMAGE_RESOURCE_DIR_STRING_U 里面是字符串长度还有字符串,不是\0结尾         
DWORD Name;                 
WORD Id;
};
union {
DWORD OffsetToData;            偏移RVA因为是联合体,所以有不同的解释
struct {
DWORD OffsetToDirectory:;    看高位,如果高位是1,那么RVA偏移指向的是新的(根目录)
DWORD DataIsDirectory:;      
};
};
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

前边我们说了

根目录(资源目录头)下面存放的是这个结构体,这个结构体是一个联合体,所以会有不同的解释

1.首先,联合体是8个字节大小.

2.其中第一个DWORD大小,看高位,如果高位是1,那么低31位是指向新的目录项名称的结构体IMAGE_RESOURCE_DIR_STRING_U

3.如果高位为0,则是ID号,这个ID号说的是 资源ID类型,比如3类型指的就是ICON

具体,可以随便写个RT_XXX开头的宏去查看.

这里我写下,跟一下看看.

4.第二个DWORD量,也是RVA偏移,如果高位为1,那么代表它还是一个目录,也就是指向了一个新的根目录了,这是个不断递归的过程.

如果不是,则指向文件偏移结构体了.

文件偏移结构体:(应该是资源数据结构体)

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;          资源数据的偏移RVA
DWORD Size;               大小
DWORD CodePage;             代码页缓冲(CMD设置窗口的时候就是这个,没用)
DWORD Reserved;             保留
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

这个就很简单了,直接前边4个字节指向就是ICON资源的位置.

三丶实战演练,定位ICON资源.

看了上面结构体,可能会晕,因为联合体很多,不同的方式有不同的解释方法,那么一步一步的跟随

1.首先通过数据目录定位资源根目录(也就是根目录,占16个字节,第一个结构体)

由此得出 RVA = 1B000

然后查看属于哪个节

由此得出,节的虚拟地址也是从1b000开始的,那么直接看文件偏移即可.

因为此时FA = RVA了,为了方便,一次截图就指明了,在文件的7800h位置

然后我们定位到7800h的位置

2.找到位置,查看结构体

找到位置后,我们对比结构体成员,看看是什么一次,因为这个是资源根目录,所以查看资源根目录结构体

typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

我们发现,意思就是按照ID分类的资源有多少个,我们得出是7个,字符串标识的资源有0个,所以不用看了.

3.定位资源目录项(子目录)

我们知道,资源根目录下面是子目录,现在有7个按照ID分类的资源,那么就有7个资源目录项(子目录)

我们看下结构体.

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset:;
DWORD NameIsString:;
};
DWORD Name;
WORD Id;
};
union {
DWORD OffsetToData;
struct {
DWORD OffsetToDirectory:;
DWORD DataIsDirectory:;
};
};
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

首先,我们不要被这个结构体弄晕.我们首先要知道结构体的大小

结构体是2个union(联合体,共用体),而里面的最大类型是DWORD,所以这个结构体大小是8个字节.

那么我们就知道了,在资源根目录下有7各这样的数组大小,也就是 7 * 8 = 56字节,整个数组占56个字节

那么我们看下

第二个红色箭头没有弄完,截图就完了,不好意思,第二个箭头的意思就是,整个56个字节,是资源目录项,其中黄色区域,属于第一个资源目录项

那么根据上面的结构体,我们先看黄色区域的第一的4个字节,看看高位是否是1

这里有两种解释方式

1.如果高位为1,那么表示一个字符串,那么低31位指向了一个字符串结构体

2.如果高位为0,那么表示是一个双字节的ID (资源类型)

现在得出  00000003  很显然,高位为0,那么表示一个资源类型,而资源类型上面看过了,3表示是一个ICON

那么在看黄色区域的第二的4个字节

1.高位为1,那么低31位表示指向了一个新的"根目录" (结构体大小还是16个字节,还是最后4个字节有用,也就是上面第一个结构体)

2.如果高位为0,那么低31位表示指向了一个资源数据结构体(可以表示为文件)

现在得出, 80000048  很显然高位为1,因为高1位是个8,那么低31位则表示指向一个新的"根目录"

得出RVA偏移得48

那么根据刚才的FA = RVA  FA = 7800 那么现在新的目录的FA = 7800 + 48 = 7848

那么在7848h表示新的根目录,跟过去看下.

4.定位新的根目录

可以看出,有是4个新的数据目录项,那么我们接着看下4个数组是什么.

我们还是继续,看资源类型为3的,通过上图,我们得出,资源数据类型为三的(ICON)的高4个字节的高1位还是8

也就会80000140,那么意思就是又指向了一个新的"根目录"

5.继续寻找新的根目录

上图得出 偏移是140  FA = 7800 + 140  = 7940

那么文件位置7940是新的根目录,接着数16个字节.

我们看到7940位置是一个新的根目录,那么我们看出,它按照ID分类,就一项了,那么下面8个字节就是数据目录项了.(子目录)

那么我们由此得出,它的高位不是1,

现在的 00000238 高位不是1了,那么根据 "子目录"结构体的定义,高位不是1那么这个RVA偏移则是指向了一个文件结构体的偏移

我们继续计算FA ,一致FA = 7800 ,得出的RVA = 238  则FA = 7800+238 = 7A38h

6.定位资源数据(文件)

那么我们定义为7A38的位置,看下资源数据结构是什么样子

为了防止大家结构体忘记,重新拷贝到这里观看.

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

就第一个个成员有用,4个字节,表示ICON的RVA偏移.

那么定位到7A38

得出第一个成员的RVA偏移是 0001c018

RVA = 1C018

按照FA = RVA  ,的知刚才的RVA = 1B000

求FA = ?

FA = 1C018 - 1B000 + 7800 =  8818

那么文件偏移8818的位置,则是ICON的数据了.

我们看下.

可以看出,很像图标资源了,那么此时,我们去看下我们的图标二进制,是不是这个.

对比文件

我们可以看出,位置确实是这个地方了.那么此时就已经成功的找到了ICON类型的资源了

作者:IBinary
出处:http://www.cnblogs.com/iBinary/
版权所有,欢迎保留原文链接进行转载:)

												

PE格式第九讲,资源表解析的更多相关文章

  1. PE格式第七讲,重定位表

    PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...

  2. PE格式第四讲,数据目录表之导入表,以及IAT表

    PE格式第四讲,数据目录表之导入表,以及IAT表 一丶IAT(地址表) 首先我们思考一个问题,程序加载的时候会调用API,比如我们以前写的标准PE 那么他到底是怎么去调用的? 他会Call 下边的Jm ...

  3. PE格式第八讲,TLS表(线程局部存储)

    PE格式第八讲,TLS表(线程局部存储) 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶复习线程相关知识 首先讲解 ...

  4. PE格式第五讲,手工添加节表

    PE格式第五讲,手工添加节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 首先我们要用汇编编写一段汇编代码,用来生成 ...

  5. PE格式第六讲,导出表

    PE格式第六讲,导出表 请注意,下方字数比较多,其实结构挺简单,但是你如果把博客内容弄明白了,对你受益匪浅,千万不要看到字数多就懵了,其实字数多代表它重要.特别是第五步, 各种表中之间的关系. 作者: ...

  6. PE格式文件的解析代码

    #include "Global.h" ; //标志,用于表示是否为pe32+文件 ; //标志,用于表示读入的模式,若为0代表是内存读入,不为0,代表是文件打开,此时mode是文 ...

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

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

  8. [PE结构分析] 11.资源表结构

    资源表是一个树形结构,可以设置成2的31次方的层数,Windows 使用了3级: 类型->名称->语言 其中涉及到四个结构: Data Description Resource Direc ...

  9. WindowsPE 第七章 资源表

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

随机推荐

  1. 201521123095 《Java程序设计》第1周学习总结

    1. 本周学习总结     开始了对JAVA的初步了解和学习,了解了如何编写简单的JAVA程序.      了解了Java的诞生及发展以及如何运用JVN JRE JDK      JVM让JAVA可以 ...

  2. 201521123069 《Java程序设计》 第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  3. Shiro第五篇【授权过滤、注解、JSP标签方式、与ehcache整合】

    授权过滤器测试 我们的授权过滤器使用的是permissionsAuthorizationFilter来进行拦截.我们可以在application-shiro中配置filter规则 <!--商品查 ...

  4. Java图的邻接矩阵实现

    /** * * 图的邻接矩阵实现 * @author John * * @param <T> */ class AMWGraph<T> { private ArrayList& ...

  5. 百度编辑器不能插入html标签解决方法

    找到此方法: me.addInputRule(function (root) { var allowDivTransToP = this.options.allowDivTransToP; var v ...

  6. ResourceManager的HA

    大家都知道在hadoop2中对HDFS的改进很大,实现了NameNode的HA:也增加了ResourceManager.但是ResourceManager也可以实现HA.你没看错,确实是Resourc ...

  7. angular 自定义指令详解 Directive

    在angular中,Directive,自定义指令的学习,可以更好的理解angular指令的原理,当angular的指令不能满足你的需求的时候,嘿嘿,你就可以来看看这篇文章,自定义自己的指令,可以满足 ...

  8. css样式引入优先级?

    css中的优先级讲的有 1.选择器的优先级. 2.样式引入的优先级. 今天要研究的是样式引入的优先级.网上又很多答案都是如下的,但是真的是这样的吗,让我们来探一探究竟是如何. 四种样式的优先级别是:行 ...

  9. 再探Spring IOC

    这次做了提纲 下面再来一个case study case描述: 这是工具类  //bean的配置信息略去 class MyUtil{ private static UserDao userDao; p ...

  10. 在JavaScript中使用json.js:使得js数组转为JSON编码

    在json的官网中下载json.js,然后在script中引入,以使用json.js提供的两个关键方法. 1.数组对象.toJSONString() 这个方法将返回一个JSON编码格式的字符串,用来表 ...