吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 21949|回复: 8
收起左侧

[原创] 基址重定位的作用及详细解析

  [复制链接]
Kris 发表于 2011-7-25 14:27
本帖最后由 Kris 于 2011-7-25 14:39 编辑

大家都知道,很多程序都带有重定位,特别是DLL文件,总是会出现,这给我们对程序的研究和修改造成了一些麻烦,同时重定位的定义,作用,修改也还有很多童鞋都不会(我也一样=.=都是小菜),就此,我这几天通过查找大量资料并研究,对重定位终于有所理解,所以发表这篇帖子与大家一起分享我对重定位的一些见解,当然,我已经说了,我也是一个刚入门的新手,在这次的分析中,可能会出现错误,希望发现错误的大牛们能及时指正,灰常感谢!

重定位定义:
重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程,也就是说在装入时对目标程序中指令和数据的修改过程。他是实现多道程序在内存中同时运行的基础.

这里给出几句代码,来说明重定位的作用
1.jpg
从这几句代码中不难发现,这几句代码的目的地址都是用直接寻址的方式来表示的,在代码的十六进制中,可以看到都是直接使用地址来表示的,当文件运行时,系统会分配一块内存给文件,如果分配的内存与文件镜像基址相同,这些代码则可以正常执行,但是当分配到的内存与文件镜像基址不同的时候,这些指令就会出现错误了,这个时候系统将会获取文件的重定位信息,并把错误指令修正.
比如PUSH 403010这一句是在某个基址为400000的文件中的,当文件运行的时候,系统分配到的内存为500000,那么PUSH 403010这一指令如果是在重定位中,
系统就会在加载时把它修复为PUSH 503010
这样就保证了分配到的内存与基址不同的时候也能正常运行

重定位结构:
struct _IMAGE_BASE_RELOCATION
{
    DWORD   VirtualAddress;  //重定位数据开始的RVA地址
    DWORD   SizeOfBlock; //重定位块的长度
   WORD    TypeOffset;  //重定位项位数组
} IMAGE_BASE_RELOCATION;
VirtualAddress:
是这一组重定位数据的开始RVA地址.各重定位项的地址加上这个值才是该重定位项完整的RVA地址.
SizeOfBlock:
是重定位结构的大小
TypeOffset:
是一个数组.数组每项大小为两个字节,共16位.它又分为高4位和低12位,高4位代表重定位类型;低12位是重定位地址,它与VirtualAddress相加即是指向PE映像中需要修改的地址数据的指针.

看了基本的重定位知识,大家是不是感到有点迷茫?没关系,下面来示例分析说明一下重定位的作用和结构

首先,要明确一点,EXE通常是不需要重定位的,为证明这一点,
我们来用LordPE看一下本例中的DEDE.EXE,
2.jpg
该EXE是存在重定位的,现在我们将重定位手动删除,首先记录下重定位的RVA地址:001B6000,转换为文件偏移为:001AFC00,重定位大小为:0001B4E4,
我们把1AFC00~1CB0E4(1AFC00+1B4E4)用00填充,并且在LordPE中把重定位的RVA和大小都填0
3.jpg

现在我们再来运行DEDE.EXE,发现该EXE仍然能正常运行.这就证明了该EXE文件并不需要重定位

现在,我们再来研究DLL15.DLL,该DLL为我自己写出来的一个DLL,其代码仅此一句
::MessageBox(NULL,"Yeah,Success!","Test",NULL);
我们和刚才一样,使用LordPE查看其重定位表,并删除其重定位,
4.jpg
该DLL文件的重定位RVA为4000(文件偏移同为4000),大小为10,
也就是说我们需要对4000~4010用00填充,
5.jpg

之后把LordPE里面的重定位信息删掉
6.jpg
接着,我们用OD加载该DLL并运行
7.jpg
发现会出现错误
而我们用OD加载原来的DLL运行,则能正常运行并弹出Message
8.jpg
现在我们再来做1个实验
我们用LordPE的PE编辑器可以看到,
DEDE.EXE的镜像基址为400000,然后把它载入到OD中,发现系统分配的内存空间与EXE的基址相同
9.jpg

DLL15.DLL的镜像基址为400000,然后把它载入到OD中,发现系统分配的内存空间与EXE的基址不同
10.jpg

就此我们就可以得到如下理论:
EXE作为独立的可执行程序,它初始化时系统会给它分配独立的进程内存空间,这个刚分配的内存空间肯定是可以分配一块与EXE的基址相同地址的内存来装载EXE本身,因此通常不需要重定位.而DLL没有独立的进程空间,每次系统分配到的内存地址与基址不一定是相同的,所以DLL总是需要重定位.

接下来我们继续深入解析一下重定位结构IMAGE_BASE_RELOCATION,我们就用DLL15.DLL来分析.
通过前面的实验,已经知道其重定位的偏移量为4000,大小为10,现在我们把它载入到C32Asm中,跳到重定位,可以看到
11.jpg
接下来我们继续载入到LordPE中,发现与我们刚才分析得到的数据是一样的
12.jpg
这就说明了我们的分析的正确的,也说明了,我们在修改程序的过程中,如果碰到修改重定位数据应该对对应的TypeOffset进行修改,以保证程序的正常运行
那么这次对基址重定位的分析就到这里了,我也是一个刚入门的新手,在这次的分析中,可能会出现错误,希望发现错误的大牛们能及时指正,灰常感谢!

附上DLL15.DLL


DLL15.rar (508 Bytes, 下载次数: 64)

免费评分

参与人数 2热心值 +2 收起 理由
寒枫雨雪 + 1 谢谢@Thanks!
Sloth + 1 膜拜。。

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
劳资小旭 发表于 2011-7-25 14:40
提示: 作者被禁止或删除 内容自动屏蔽
jacalhu 发表于 2011-7-25 14:45
小闫 发表于 2011-7-25 15:25
感悟 发表于 2011-7-25 16:01
远路风尘跑来支持阿曾
tyhack 发表于 2011-8-8 22:30
支持小曾
加菲猫 发表于 2013-5-9 16:12
附上Dll文件源码,编译即可生成dll文件,
#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
                                           DWORD ul_reason_for_call,
                                           LPVOID lpReserved
                                           )
{
        MessageBoxW(NULL, L"Yeah,Success!", L"Test",0);
        return TRUE;
}
加菲猫 发表于 2013-5-9 16:13
附上Dll文件源码,编译即可生成dll文件,
#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
                                           DWORD ul_reason_for_call,
                                           LPVOID lpReserved
                                           )
{
        MessageBoxW(NULL, L"Yeah,Success!", L"Test",0);
        return TRUE;
}
鱼无论次 发表于 2014-3-30 23:23
谢谢楼主!我正好需要这个东西
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-18 01:20

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表