好友
阅读权限 10
听众
最后登录 1970-1-1
fily
发表于 2021-6-4 15:14
本帖最后由 fily 于 2021-6-4 20:12 编辑
手动添加重定位
00 什么是重定位
什么是重定位?
在32程序中内存有4G空间,其中高2G是系统空间,低2G是用户空间,当一个程序被加载,会被安排到这个空间中的某个地方,默认情况下EXE会被加载到0x00400000,dll会被加载到0x10000000位置。
一般情况下dll都必须开启重定位,应为一个程序中会存在多个dll,如果所有的dll都加载到0x10000000位置,dll相互直接会被覆盖。而exe可以选择不开启重定位,一个程序中只有一个主模块。
而在程序中,如果有引用到绝对地址的代码,例如下
那么程序如果开启随机基址,那么这个指令将执行失败,应为它并不是指向当前加载的地址,而是以0x00400000为基址的数据,此时这个地址是无法访问的。
加载器如何修复重定位的?
当一个可执行程序,被加载到内存中,首先会判断是否开启随机基址,可以通过两个字段
IMAGE_FILE_HEADER FileHeader; //文件头
FileHeader.Characteristics; // 属性字段
IMAGE_OPTIONAL_HEADER OptionalHeader;// 扩展头
OptionalHeader.DllCharacteristics;// 属性字段
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; //RVA,指向一个分页的基址,都是0x1000的倍数
DWORD SizeOfBlock; //这个重定位数据总大小
// WORD TypeOffset[1]; //需要修复的数据块项,个数= (SizeOfBlock-8)/2
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
// 数据块结构
typedef struct _TYPEDATA {
WORD offset : 12; // 一个分页的偏移
WORD type : 4; // 重定位块的属性,通常如果为3,表示32位地址需要修复
}TYPEDATA, * PTYPEDATA;
加载器中这个重定位表获取 VirtualAddress + TYPEDATA.offset 找到要修复的数据,按照修复公式进行修复
修复后的地址 = 待修复的数据(0x00402000) - 默认基址(0x00400000) + 当前加载基址(0x00A80000)
01 编写测试代码
.386
.model flat,stdcall
include user32.inc
includelib user32.lib
.data
szText db "hello",0
.code
main:
push 0
push 0
push offset szText ;待修复的地址 0x00403000
push 0
call MessageBox
ret
end main
end
该程序没有重定位表,没有开启随机基址
02 开启重定位
将FileHeader.Characteristics第0位置0
03 构建重定位表
、
04 验证程序
免费评分
查看全部评分
发帖前要善用【论坛搜索 】 功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。