前言
在PE文件结构中,数据目录表对应的信息很重要,这里对其中几个常用的进行介绍。
资源表
资源表用来存储程序的各种界面数据,比如菜单、图标、版本信息等,其结构体如下
1 | typedef struct _IMAGE_RESOURCE_DIRECTORY { |
资源在PE文件中是以目录结构的形式存在的,一般情况下这个目录分3层,从根目录开始分别为资源类型、
目录资源ID、资源代码页。每层的头部是一个 IMAGE_RESOURCE_DIRECTORY
结构,并且在其后面跟着一个IMAGE_RESOURCE_DIRECTORY_ENTRY
结构数组,然后结构数组的每个成员则分别指向下一层目录结构。
1 | typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { |
第一个联合体的信息,是根据当前结构体所处的目录层次来决定的,位于 第1层
目录时 Name
有效,保存的
信息是 资源类型
。位于 第2层
目录时 Id
或 结构体
有效,取决于此资源的 索引方式
,如果用的是 编号索引
就是 Id
有效,否则 结构体
有效。位于 第3层
目录时 Name
有效,保存的信息是 语言类型
。
第二个联合体的信息,理论上是根据具体情况而定的,如果下级是一个 子目录
的话,那么就是 结构体
生效,
如果下级是 资源数据
则是字段 OffsetToData
生效。
当 NameIsString
为 1
时,NameOffset
指向一个 IMAGE_RESOURCE_DIR_STRING_U
结构体
1 | typedef struct _IMAGE_RESOURCE_DIR_STRING_U { |
当 Name
位于 第1层
目录时表示的 资源类型
如下表所示
类型值 | 资源类型 | 类型值 | 资源类型 |
---|---|---|---|
0x00000001 | 鼠标指针(Cursor) | 0x00000008 | 字体(Font) |
0x00000002 | 位图(Bitmap) | 0x00000009 | 快捷键(Accelerators) |
0x00000003 | 图标(Icon) | 0x0000000A | 非格式化资源(Unformatted) |
0x00000004 | 菜单(Menu) | 0x0000000B | 消息列表(Message Table) |
0x00000005 | 对话框(Dialog) | 0x0000000C | 鼠标指针组(Group Cursor) |
0x00000006 | 字符串列表(String Table) | 0x0000000E | 图标组(Group Icon) |
0x00000007 | 字体目录(Font Directory) | 0x00000010 | 版本信息(Version Information) |
在经过3层目录的索引后,最后是一个 IMAGE_RESOURCE_DATA_ENTRY
结构体,定义如下
1 | typedef struct _IMAGE_RESOURCE_DATA_ENTRY { |
资源表的3层目录关系,如下图所示
重定位表
系统在加载DLL文件时,并不是每次都能加载到预期的 ImageBase
基址上,所以DLL都存在 基址重定位表
,
用来修正相关的地址信息,另外EXE的 动态基址
技术,也是用 基址重定位表
实现的。
PE文件中的重定位信息是由多个 IMAGE_BASE_RELOCATION
结构体组成的,每个结构体只描述一个 4KB
大小
的分页内重定位信息,也就是 0x1000
字节,因此结构体中 VirtualAddress
的值总是为 0x1000
的倍数。
1 | typedef struct _IMAGE_BASE_RELOCATION { |
重定位的本质非常简单,就是比较实际加载地址与 ImageBase
的值,如果相等则不需要做任何操作,如果
不相等就需要把重定位表中指定的地址处加上这个差值。
TypeOffset
由两部分数据组成,高4位
表示 类型
,低12位
表示 偏移
。类型定义如下
值 | 信息 | 宏定义 |
---|---|---|
0 | 无重定位操作,填0后用于4字节对齐 | IMAGE_REL_BASED_ABSOLUTE |
1 | 重定位偏移指向位置的高2个字节需要被修正 | IMAGE_REL_BASED_HIGH |
2 | 重定位偏移指向位置的高2个字节需要被修正 | IMAGE_REL_BASED_LOW |
3 | 重定位偏移指向的4个字节的地址需要被修正 | IMAGE_REL_BASED_HIGHLOW |
4 | 需要使用两项TypeOffset才能完成索引操作 | IMAGE_REL_BASED_HIGHADJ |
5 | 基址重定位应用于MIPS jump指令 | IMAGE_REL_BASED_MIPS_JMPADDR |
6 | 保留 | IMAGE_REL_BASED_RESERVED |
9 | 基址重定位应用于MIPS16 jump指令 | IMAGE_REL_BASED_IA64_IMM64 |
10 | 重定位偏移指向的8个字节(64位)地址需要被修正 | IMAGE_REL_BASED_DIR64 |
重定位表结构如下图所示