第16章:基址重定位(2)

PE重定位

使得硬编码在程序中的内存地址随当前加载地址的变化而变化就是PE重定位.

若不添加重定位,而加载时内存地址被占用,则会出现"内存地址引用错误",使得程序异常终止.

PE重定位的操作原理:

 

查找硬编码地址需要用到重定位表(Relocation Table),它是记录硬编码地址偏移列表.是PE文件构建过程中(编译/链接的时候提供的).

 

重定位表在 Image_optional_header/DataDirectory[5] 中可找到地址,转化为 FileOffset 即可.

 

查看各个节区头的信息,发现在 reloc 节区中,直接查该节区头的 PointerToRawData 字段中的地址.即红色框起来的四字节.

 

SizeOfBlock 后面跟着的元素是很多两字节的 TypeOffset.末端以0结尾.所有重定位块以一个 VirtualAddress 字段为 0 的 IMAGE_BASE_RELOCATION 结构结束

第一个为例:3424. 高四位(此处是3)是重定位类型,低12位(此处是424)是偏移.

在网上搜索可知,在 Windows 中大部分只采用的 Image_Rel_Based_HighLow(3) 这种类型.

硬编码地址的计算为:1000(Virtual Address)+424(Offset) = 1424(RVA).

转到地址 824 处,占 4 字节,此处为 010010C8:

 

 在可选头中查找到 ImageBase 值,一般来说是 1000000.

 

偏移地址为 010010C8-1000000 = 10C8.从系统获取程序实际加载的基地址,二者相加即可得到重定位地址.

 此处就是10C8+210000 = 2110C8即可看到导入的 DLL 的函数地址.

 

增加一个空节区:

第一:修改 SizeOfImage 大小,需要约进到 SectionAlignment.

第二:修改 FileHeader 中的 NumberOfSections.

第三:添加节区头,根据前面的节区,计算得到后面的值,其中 VirtualSize 可以为0,但是 SizeOfRawData 不能为0.DLL属性可以不填.

需要注意的一点是,如果PE文件中末地址没有包含到自己添加的节区,那么需要自己添加0填充,直到自己添加节区的末地址.

 

posted @ 2020-07-06 19:03  Rev_omi  阅读(221)  评论(0编辑  收藏  举报