PE文件结构(五)基址重定位

PE文件结构(五)

参考

书:《加密与解密》

视频:小甲鱼 解密系列 视频

基址重定位

链接器生成一个PE文件时,它会假设程序被装入时使用的默认ImageBase基地址(VC默认exe基地址00400000h,dll基地址10000000h),并且会把代码中所有指令中用到的地址都使用默认的基地址(例如 程序代码中 push 10001000,就是把10000000h当做了基地址,把push 10001000写入到文件中)。如果一个exe程序中一个dll装载时的地址与其它dll地址发生冲突(因为windows程序是虚拟地址空间,exe一般不会有地址冲突,加载dll时可能会有地址冲突),就需要修改代码中的地址,如push
10001000,call 10002000等。这时就需要用进行基址重定位。而基址重定位表中存放了,如果默认地址被改,需要修改的代码的地址。在PE文件中,基址重定位表一般放在一个单独的 ".reloc" 区,可以通过IMAGE_OPTIONAL_HEADER 中 的DataDirectory[5] 查看 基址重定位表 的RVA。

例如:

用W32Dasm 查看 Demo.dll  (下载地址:http://pan.baidu.com/s/1qWDepo4)

图片1

可以发现MyMessageBox 这个函数,看看它的代码中的push 10006040 , push 10006030 中的地址是指向字符串的。如果一个程序在加载Demo.dll时因为Demo.dll 默认的地址被占用了,而使用其它的基地址,例如使用20000000h作为基地址,Demo.dll就从20000000h开始装载。这样字符串“Demo”和“Hello World!” 就不是在10006040h跟10006030h中了,这时就需要把push 10006040 , push 10006030改成push
20006040 , push 20006030 。

基址重定位表是由一个一个IMAGE_BASE_RELOCATION结构  构成的。

图片2

IMAGE_BASE_RELOCATION 结构:

typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;
    DWORD   SizeOfBlock;
//  WORD    TypeOffset[];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

其中 VirtualAddress  表示 这一组地址的起始RVA。SizeOfBlock表示当前这个IMAGE_BASE_RELOCATION 结构的大小。TypeOffset是一个数组,它的元素个数就是( SizeOfBlock - 8 ) / 2 ,TypeOffset 每一个元素占用两个字节即16位,其中高4位表示重定位类型(一般都为3),低12位表示重定位地址。

实例分析:

查看Demo.dll的第一个 IMAGE_BASE_RELOCATION 结构

图片3

可以发现:

VirtualAddress  为1000h

SizeOfBlock      为 0164h

TypeOffset[0]   0333h  即 3是重定位类型  33h为重定位地址

TypeOffset[1]   0338h

TypeOffset[2]   0340h

........

通过Type低12位+VirtualAddress 可以知道前三个的地址为1033h,1038h,1040h 。

再来看看图片1中Demo.dll的代码,可以发现1033h就是图片1中的push 10006040中的10006040,1038h就是push 10006030中的10006030 。

如果加载dll,发现不是使用默认的基地址,PE加载器就会把基址重定位表中所写的地址的值改掉。改掉方法是把原先的值加上 实际基地址 - 默认基地址 的值。

时间: 2024-10-22 22:34:03

PE文件结构(五)基址重定位的相关文章

[PE结构分析] 10.基址重定位

源代码如下: typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; } IMAGE_BASE_RELOCATION; typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; 重定位表是一个数组,这个数组的大小记载在 _IMAGE_OPTIONAL_HEADER 的 .D

小甲鱼PE详解之基址重定位详解(PE详解10)

今天有一个朋友发短消息问我说“老师,为什么PE的格式要讲的这么这么细,这可不是一般的系哦”.其实之所以将PE结构放在解密系列继基础篇之后讲并且尽可能细致的讲,不是因为小甲鱼没事找事做,主要原因是因为PE结构非常重要,再说做这个课件的确是很费神的事哈.在这里再次强调一下,只要是windows操作程序,其就要遵循PE格式,再说人家看雪的网址就是www.pediy.com. 简单的讲是可以,但是怕就怕有些朋友知识点遗漏了或者错误理解意思.不能深刻体会等,这样的效果是不好的~所以,小甲鱼尽管这系列视频可

解析PE资源表与重定位表

#include<Windows.h> #include<iostream> #include<stdio.h> #include<stdlib.h> #include<commdlg.h> using namespace std; DWORD dwFileSize; BYTE* g_pFileImageBase = 0; PIMAGE_NT_HEADERS g_pNt = 0; DWORD RVAtoFOA(DWORD dwRVA); //显示

基址重定位

一.需要重定位的原因 http://blog.sohu.com/s/NDg4ODAyODQ/179103126.html 二.需要重定位的指令 但凡涉及到直接寻址的指令都需要进行重定位处理 http://blog.sohu.com/s/NDg4ODAyODQ/179103126.html 三.参考 http://blog.csdn.net/misskissc/article/details/43063419 http://www.52pojie.cn/thread-101281-1-1.html

PE文件结构详解(六)重定位

前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里,IE的iexplorer.exe导入了Kernel32.dll的GetCommandLineA函数,可以看到这是个间接call,00401004这个地址的内存里保存了目的地址, 根据图中显示的符号信息可知,00401004这个地址是存在于iexplorer.exe模块中的,实际上也就是一项IAT的

PE文件结构(五岁以下儿童)基地搬迁

PE文件结构(五岁以下儿童) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 基址重定位 链接器生成一个PE文件时,它会如果程序被装入时使用的默认ImageBase基地址(VC默认exe基地址00400000h.dll基地址10000000h),而且会把代码中全部指令中用到的地址都使用默认的基地址(比如 程序代码中 push 10001000,就是把10000000h当做了基地址,把push 10001000写入到文件里).如果一个exe程序中一个dll装载时的地址与其他dll地址发生

C++应用程序在Windows下的编译、链接(二)COFF/PE文件结构

2.1概述 在windows操作系统下,可执行文件的存储格式是PE格式:在Linux操作系统下,可执行文件的存储格式的WLF格式.它们都是COFF格式文件的变种,都是从COFF格式的文件演化而来的. 在windows平台下,目标文件(.obj),静态库文件(.lib)使用COFF格式存储:而可执行文件(.exe),动态链接库文件(.dll)使用PE格式存储.静态库文件其实就是一堆目标文件的集合. 在“WinNT.h”头文件中定义了COFF格式文件,以及PE格式文件的数据结构.这些定义是一系列的结

PE文件结构(32/64差异)

1 基本概念 下表描述了贯穿于本文中的一些概念: 名称 描述 地址 是“虚拟地址”而不是“物理地址”.为什么不是“物理地址”呢?因为数据在内存的位置经常在变,这样可以节省内存开支.避开错误的内存位置等的优势.同时用户并不需要知道具体的“真实地址”,因为系统自己会为程序准备好内存空间的(只要内存足够大) 镜像文件 包含以EXE文件为代表的“可执行文件”.以DLL文件为代表的“动态链接库”.为什么用“镜像”?这是因为他们常常被直接“复制”到内存,有“镜像”的某种意思.看来西方人挺有想象力的哦^0^

程序地址重定位和模块绑定

1.程序的构建 在构建程序的时候,链接器都会给程序设置一个默认的加载地址,即首选基地址,它表示该模块被映射到进程地址空间时最佳的内存地址.默认情况下,对于EXE程序而言,windows链接器会将它的首选基地址设置为0X400000(四十万),而DLL程序的首选基地址则被设置为0X10000000(1千万),然后链接器将该地址以及一些相关数据和代码的地址写入到PE文件中.首选基地址的是为了系统程序加载器设计的,作用是告诉加载器把程序优选加载到该首选基地址,然后就可以直接将其他的数据和代码加载到内存