首页
社区
课程
招聘
[求助]动态加载的dll中如何调用外部函数
发表于: 2006-2-12 14:53 7170

[求助]动态加载的dll中如何调用外部函数

2006-2-12 14:53
7170
假定我要在一个dll中调用CreateFileA,可以这么做
6504E7DE  |. FF15 B4F10465  CALL DWORD PTR DS:[<&KERNEL32.CreateFile>; \CreateFileA
如果是静态加载该dll,执行到这里没问题。
但是如果程序动态加载该dll,跟踪到这里就变成
xxxxE7DE CALL DWORD PTR DS:[6504F1B4]
然后就出现exception,
请问各位应如何解决?

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

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
2
Dll的重定位表被删除了吧
2006-2-12 22:02
0
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
这个dll自己也有调用CreateFileA的地方,动态加载时没问题。
我要做的是在它的code section添加一段代码,其中要调用CreateFileA,
并且要保证动态加载时能正确执行。
请问各位有什么办法?
2006-2-13 08:48
0
雪    币: 183
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
invoke GetModuleHandle,addr kernel32.dll
invoke GetProcAddress,eax,addr CreateFileA
call [eax]
2006-2-13 09:15
0
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
既然调用CreateFileA会失败,调用GetModuleHandle也同样会失败吧?

import table里肯定有CreateFileA,
我希望手工修改重定位表,当系统加载dll时自动修正调用地址,
请问应如何实现?
2006-2-13 10:55
0
雪    币: 183
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
最初由 jtbuaa 发布
既然调用CreateFileA会失败,调用GetModuleHandle也同样会失败吧?

import table里肯定有CreateFileA,
我希望手工修改重定位表,当系统加载dll时自动修正调用地址,
请问应如何实现?

把你的DLL放上来
2006-2-13 13:16
0
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
谢谢各位,我想我已找到解决办法。

假定有个xx.dll,其基址是65000000。
我们要对xx.dll打补丁,增加一些功能。
补丁中要调用一个zz函数(假定xx.dll的引入表中有这个函数,如果没有我们可以用LordPE等工具添加这个函数),
这个函数在xx.dll的引入表中地址为[65071020]。
调用方式如下
65032733     FF15 20100765  CALL DWORD PTR DS:[<&yy.zz>]    ;  yy.zz
65032738   . 90             NOP

静态加载xx.dll时,上面的做法没问题。
[65071020]指向zz函数的实际地址,这个地址是在系统加载时重定位的正确地址。

但动态加载xx.dll时,它的基地址会随机变化,这句话就会变成
xxxx2733     call dword ptr [65071020]
没有人知道[65071020]会指向哪里。程序执行到这里会raise exception。

错误在于我们不应该使用hard code方式确定函数在引入表中的位置,
因为上述代码是我们自己添加的,reloc段中没有这部分的索引,
系统加载dll时也就不可能替我们修正。
精华五中的一篇文章(对于DLL通过增加重定位项直接调用引入表函数
http://www.pediy.com/bbshtml/BBS5/pediy50339.htm)给出了一种修改reloc段来添加函数引用的方法,
可惜我对reloc段的结构不了解,没办法尝试。
好在我找到了一种替代的方法,据说是病毒常用的方法。

我们知道zz函数的正确地址确实存在于xx.dll中的import table中,偏移量为a(71020)。
我们的代码偏移量为b(32738)。因此从代码到引入表的绝对偏移是一个常数c。
动态加载时我们只要知道基地址,或者知道代码的实际地址,加上常数c就是指向zz函数的真实地址。
做法是在xx.dll的代码段中找一段空闲的位置,加入
6504E770  /$ 58             POP EAX                        ;调用语句的下一行代码地址
6504E771  |. 50             PUSH EAX                        ;恢复堆栈
6504E772  |. 05 E8E80300    ADD EAX,3E8E8                ;加上常数c
……
6504E779  |. FF10           CALL DWORD PTR DS:[EAX]        ;[eax]指向zz的实际地址
6504E77B  \. C3             RETN
再把开始的调用代码改为
65032733   . E8 38C00100    CALL impeg34.6504E770
这样就ok了。
2006-2-13 16:44
0
游客
登录 | 注册 方可回帖
返回
//