概述
加载PE文件到虚拟内存时,EXE默认IMAGEBASE一般为400000,DLL默认IMAGEBASE一般为10000000。
-
一般情况下,EXE都是可以按照ImageBase的地址进行加载的.因为Exe拥有自己独立的4GB 的虚拟内存空间。 但DLL 不是 DLL是有EXE使用它,才加载到相关EXE的进程空间的。
-
为了提高搜索的速度,模块间(各个Dll之间)地址也是要对齐的模块地址对齐为10000H 也就是64K。
为什么需要重定位表存在?
运行一个程序一般需要多个DLL文件,如果都按默认位置加载,则造成冲突。这时就需要重定位表根据RVA为数据重新分配位置。(说白了一般程序加载都写死代码位置,比如全局变量等。所以需要根据RVA重新调整位置。)
- 如果程序能够按照预定的ImageBase来加载的话,那么就不需要重定位表。这也是为什么exe很少有重定位表,而DLL大多都有重定位表的原因。
- 一旦某个模块没有按照ImageBase进行加载,那么所有类似上面中的地址就都需要修正,否则,引用的地址就是无效的。
- 一个EXE中,需要修正的地方会很多,那我们如何来记录都有哪些地方需要修正呢? 答案就是重定位表。
如果在代码编写中使用重定位技术,你就可以将代码随意地部署到内存中,而不影响程序的运行。
重定位表定位
重定位表为数据目录中注册的数据类型之一,其描述信息处于数据目录的第6个目录项中。
Size没什么用。
重定位表项IMAGE_BASE_RELOCATION结构
IMAGE_BASE_RELOCATION STRUCT
VirtualAddress dd ? ;重定位内存页的起始RVA
SizeOfBlack dd ? ;重定位块的长度
IMAGE_BASE_RELOCATION ENDS
结构详解
结构详解:
重定位表项都以块来分类,便于空间的节约紧凑。
高四位补充(主要记住0 && 3含义就可以):
在实际的PE文件中,我们只能看到0和3这两种情况,也就是说这一项要么是对齐用,要么是需要全部全部修正。
定位实例
1.找数据目录第6项
RVA = 0x4000
SIZE=0xB4
FOA=0xC00
2.获得表项
第一项RVA = 0X1000
SizeOfBlock = 0XB4
可得第一块重定位项数:
(0xB4-8)/2 = 0x56=86D
3.以第一项2字节(0x3036)为例
3036确实是需要修正的数据。
实际VA = imagebase + 第一项RVA(0X1000) + 低12位值
得出:实际VA=0x00101036
4.验证调用此模块的数据,查看0x00101036位置
写死全局变量的位置,所以此处必须修正。