首页
社区
课程
招聘
[求助]DLL虚拟地址和真实地址转换问题
发表于: 2009-1-18 23:51 5490

[求助]DLL虚拟地址和真实地址转换问题

2009-1-18 23:51
5490
传说中……~开玩笑啦~
这个问题困扰我N久了,一般来说,DLL的入口点应该是用RVA基址加上LORDPE里面的入口点地址吧,如图1

但是我居然遇到这样一个DLL,跟这个算法不一样啊`如图2

大牛来讲解一下吧~
还有一个难题我一直不明白,在看雪也问了几次了,就是DLL的重定位问题,让DLL不能加重定位指令怎么办啊~

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
2
一般来说,DLL的入口点应该是用RVA基址加上LORDPE里面的入口点地址吧,如图1


入口点的虚拟地址VA(也就是虚拟地址的定义)确实是RVA+BASE,但这个BASE是指模块被加载后在内存中的基地址,而对DLL来说这个加载基址不一定与图中LordPE显示的那个值(叫默认基址,由PE头中相关字段给出)相等,而对EXE来说几乎总是相等。

但是我居然遇到这样一个DLL,跟这个算法不一样啊`如图2


图2看起来没什么问题啊,入口点RVA=001EB2C,加载后的VA是003EEB2C,说明加载的基址是003D0000

还有一个难题我一直不明白,在看雪也问了几次了,就是DLL的重定位问题,让DLL不能加重定位指令怎么办啊~


没读明白你这句话的意思,什么叫“让DLL不能加重定位指令怎么办”???
2009-1-19 00:55
0
雪    币: 210
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
DLL因为加载他的程序不同,DLL文件的基址是会变的,所以需要重定位,不是PE里面显示的基址。OD入口点地址减去PE入口点地址就是新的基址了。SratMain.DLL我接触过,用OC换算文件偏移成内存地址(OC),这个内存地址是错的,新内存地址VA=内存地址(OC)+(新的基址-PE基址)。这样讲应该比较详细了。。。
2009-1-19 01:02
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
就是经常在给DLL写入命令的时候,只要写入比如,CALL,PUSH **** RETN这种跳转指令的时候总是会出现CPU100%,后来找到个方法就是吧跳转的地址写入重定位表,但是这个每次都写不方便吧,所以来问一下。。
还有个小小问题就是,我能不能把DLL的LORDPE里面显示的那个基址RVA(0040000)改成003D0000呢??改了貌似DLL不能用了,要是要改怎么改呢??
哇哈哈~得到两位的相助,半夜回帖,非常感谢啊`
2009-1-19 11:31
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
为什么没人理我了~~~
2009-1-19 12:29
0
雪    币: 211
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我都看懂了,
你把基址改了是没用的,dll之所以能找到入口点,仍然的根据原来的基址做换算得来的,或者说在重定位表里有它的地址(个人猜测),如果你改了基址,dll加载的时候就再也定位不到原来的位置了

不知道我理解得对不对
2009-1-19 12:35
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼上的好像说得没错啊,我去掉了重定位表就不能再载入DLL了~也就是DLL不能找到入口了~但是这种问题怎么解决呢?》

最重要的问题还是
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
只要写入比如,CALL,PUSH **** RETN这种跳转指令的时候总是会出现卡机的现象
~~~~~~~~~~~~~~~~~~~~~~
2009-1-19 14:16
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
自发自定~期待高哦人帮助~
2009-1-19 16:30
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
9
DLL文件最好还是保留重定位信息比较好,否则遇到默认基址已经被使用的情况时程序就加载不了了;不像EXE,加载器几乎总是把它加载到默认基址上,因为一般不需要重定位。

你说的push + retn,push后面的地址是绝对地址,必须添加到重定位表才能保证程序可以正确执行。

call指令,分不同的情况。

如果是near的call,即机器码0xe8,0xAAAAAAAA,只要目的地址在同一个dll中,就不用重定位,因为这每次指令使用相对地址(0xAAAAAAAA)。而如果要call不同模块中的地址,通常不用near call,而用下面的函数指针的call。

如果是call [BBBBBBBB],机器码是0xff,0x15,0xBBBBBBBB,这里的函数指针0xBBBBBBBB是绝对地址,就必须重定位了。并且0xBBBBBBBB处的值也需要重定位(当然IAT中的指针是加载器自动重定位的,但自定义的指针则需要手动添加重定位信息)。
2009-1-19 17:24
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
明白了,以前只是知道方法,现在知道原因了~哇哈,书呆彭厉害啊~
那有没有方法可以解决这个问题呢?除了写入重定位表就没别的办法了?
2009-1-19 22:15
0
游客
登录 | 注册 方可回帖
返回
//