PE格式第九讲,资源表解析
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格式第九讲,资源表解析的更多相关文章
- PE格式第七讲,重定位表
PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...
- PE格式第四讲,数据目录表之导入表,以及IAT表
PE格式第四讲,数据目录表之导入表,以及IAT表 一丶IAT(地址表) 首先我们思考一个问题,程序加载的时候会调用API,比如我们以前写的标准PE 那么他到底是怎么去调用的? 他会Call 下边的Jm ...
- PE格式第八讲,TLS表(线程局部存储)
PE格式第八讲,TLS表(线程局部存储) 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶复习线程相关知识 首先讲解 ...
- PE格式第五讲,手工添加节表
PE格式第五讲,手工添加节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 首先我们要用汇编编写一段汇编代码,用来生成 ...
- PE格式第六讲,导出表
PE格式第六讲,导出表 请注意,下方字数比较多,其实结构挺简单,但是你如果把博客内容弄明白了,对你受益匪浅,千万不要看到字数多就懵了,其实字数多代表它重要.特别是第五步, 各种表中之间的关系. 作者: ...
- PE格式文件的解析代码
#include "Global.h" ; //标志,用于表示是否为pe32+文件 ; //标志,用于表示读入的模式,若为0代表是内存读入,不为0,代表是文件打开,此时mode是文 ...
- Windows PE资源表编程(枚举资源树)
资源枚举 写一个例子,枚举一个PE文件的资源表.首先说下资源相关的作为铺垫. 1.资源类型也是PE可选头中数据目录的一种.位于第三个类型. 2.资源目录分为三层.第四层是描述文件相关的.这些结构是按照 ...
- [PE结构分析] 11.资源表结构
资源表是一个树形结构,可以设置成2的31次方的层数,Windows 使用了3级: 类型->名称->语言 其中涉及到四个结构: Data Description Resource Direc ...
- WindowsPE 第七章 资源表
资源表 在程序设计中,总会设计一些数据.这些数据可能是源代码内部需要用到的常量,菜单选项.界面描述等:也可能是源代码外部的,比如程序的图标文件.北京音乐文件.配置文件等,以上这些数据统称为资源.按照程 ...
随机推荐
- 201521123086《java程序设计》第四周
本章学习总结 尝试使用思维导图总结有关继承的知识点 1.2 使用常规方法总结其他上课内容. 为了不必要写重复的代码,可以运用继承,用关键字extends来定义一个类,被继承的类叫做父类,继承的类叫做子 ...
- 201521123016《java程序设计》第4周学习总结
1. 本周学习总结 2. 书面作业 注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 面向对象设计(大作业1,非常重要) 2.1 将在网上商城购物或 ...
- 201521123111《Java程序设计》第3周学习总结
1. 本章学习总结 你对于本章知识的学习总结 2. 书面作业 1. 代码阅读 代码阅读 public class Test1 { private int i = 1;//这行不能修改 private ...
- 201521123002《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...
- 201521123013 《Java程序设计》第13周学习总结
1. 本周学习总结 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? ping值 ...
- 初识ELF格式 ABI,EABI,OABI
尽管每天都在调用linux的elf文件做各种事,但却很少去了解他,最近尝试在orangepi上编译个elf到android手机上运行,因为两个CPU都是ARMv8的.结果运行失败了.遂查找原因.结果挖 ...
- 理解G1垃圾回收日志
本篇文章主要介绍在-XX:+PrintGCDetails选项的情况下G1 GC log打印的信息.(注:本文假设读者对G1算法的基本原理已经有所了解) 下面是一段G1垃圾收集器相关的log信息 0.5 ...
- 微软云linux服务器FTP文件传输错误解决办法
在微软云上新建了linux虚拟机之后,通过Xshell连接到服务器(微软云默认的账号是:azureuser,不是root),却发现通过FTP传输文件错误,一直找不到头绪,询问微软云相关人员才知道.FT ...
- CSV导出大量数据
$csvname = $csvname . '.csv'; header('Content-Type: application/vnd.ms-excel;charset=GB2312'); heade ...
- 西邮linux兴趣小组2014纳新免试题(二)
[第二关] 题目 http://round2.sinaapp.com/ 分析 打开后,戳进去发现一句名言,然后下一戳的url提示. 在网页源码中得到Page1024提示,于是写一个脚本 #!/bin/ ...