SetWindowsHook时的dll映射问题

yangyanglee111 2010-04-02 02:34:45
原文如下
“进程A(类似Microsoft Spy++的一个实用程序)安装了一个挂钩W N _ G E T M E S S A G E,以便查看系统中的各个窗口处理的消息。该挂钩是通过调用下面的SetWindowsHookEx函数来安装的:


HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
hinstDll, 0);

现在让我们来看一看将会发生什么情况:

1) 进程B中的一个线程准备将一条消息发送到一个窗口。

2) 系统查看该线程上是否已经安装了W H _ G E T M E S S A G E挂钩。

3) 系统查看包含G e t M s g P r o c函数的D L L是否被映射到进程B的地址空间中。

4) 如果该D L L尚未被映射,系统将强制该D L L映射到进程B的地址空间,并且将进程B中的D L L映像的自动跟踪计数递增1。

5) 当D L L的h i n s t D l l用于进程B时,系统查看该函数,并检查该D L L的h i n s t D l l是否与它用于进程A时所处的位置相同。

如果两个h i n s t D l l是在相同的位置上,那么G e t M s g P r o c函数的内存地址在两个进程的地址空间中的位置也是相同的。在这种情况下,系统只需要调用进程A的地址空间中的G e t M s g P r o c函数即可。

如果h i n s t D l l的位置不同,那么系统必须确定进程B的地址空间中G e t M s g P r o c函数的虚拟内存地址。这个地址可以使用下面的公式来确定:


GetMsgProc B = hinstDll B + (GetMsgProc A - hinstDll A)
将GetMsgProc A的地址减去hinstDll A的地址,就可以得到G e t M s g P r o c函数的地址位移(以字节为计量单位)。将这个位移与hinstDll B的地址相加,就得出G e t M s g P r o c函数在用于进程B的地址空间中该D L L的映像时它的位置。
6) 系统将进程B中的D L L映像的自动跟踪计数递增1。

7) 系统调用进程B的地址空间中的G e t M s g P r o c函数。

8) 当G e t M s g P r o c函数返回时,系统将进程B中的D L L映像的自动跟踪计数递减1。

注意,当系统插入或者映射包含挂钩过滤器函数的D L L时,整个D L L均被映射,而不只是挂钩过滤器函数被映射。这意味着D L L中包含的任何一个函数或所有函数现在都存在,并且可以从进程B的环境下运行的线程中调用。”(原文结束)


问题是如果说进程A调用SetWindowsHookEx,使得进程B发送消息时会触发钩子从而将dll文件映射到B的进程空间,这没问题,但是我不理解为什么进程A中同样会将dll映射进来呢?(如上面原文5所说)。进程A不需要dll文件中的函数啊,那些函数不提供给进程B触发钩子后调用的吗,A无非是设置下钩子顺带着告诉下触发后调用什么函数以及这个函数所在的dll不就ok了吗,干嘛要把dll弄进自己的进程空间呢?是我哪理解错了吗?望指教
...全文
261 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
......我的意思是说A进程调用SetWindowsHookEx,使得进程B发送消息时会触发钩子从而将dll文件映射到B的进程空间并且触发B进程空间中的GetMsgProc,而A空间中映射进的dll文件里的代码(如A进程空间中的GetMsgProc)不会被执行吧?
wangk 2010-04-02
  • 打赏
  • 举报
回复
会被执行的。不被执行计算地址干什么。GetMsgProc就在拦截的消息的进程里被系统调用。
你可以在GetMsgProc函数体内写log用GetCurrentProcessId记录进程ID你就知道了。


yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
再次万分感谢,这个问题我扯远了。
总之调用SetWindowsHookEx进程(进程A)中载入的dll中的代码应该不会被执行吧无非起到计算个地址的作用?
wangk 2010-04-02
  • 打赏
  • 举报
回复
……,我对我的表达能力彻底失望了。

进程A,知道Dll中偏移地址1000是个函数,B不知道啊,GetMsgProc A是一个绝对地址。
那么你告诉我怎么让B知道hinstDll B+1000是GetMsgProc?
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
hinstDll A - GetMsgProc A不就又等于计算了一下这个编译时就已知的偏移地址1000吗
wangk 2010-04-02
  • 打赏
  • 举报
回复
Dll加载是这样=>进程映射到一个虚拟内存地址(就是上面一直说的hinstDll),然后对齐呀、重定位啊、修正导出表、导入表啊。

6楼说的如果用【Dll的路径】C:\123.dll类似的。另外Dll中导出函数的相当地址是确定的,但你在程序中使用的函数地址GetMsgProc是绝对地址的啊,进程加载dll后自动就给你弄成绝对地址了。

A进程自然不需要,直接使用GetMsgProc就可以了。但是B进程需要啊。GetMsgProc B =(hinstDll B + hinstDll A - GetMsgProc A)
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
总结下
如果像我#7说得GetMsgProc的相对地址1000在编译时就知道了,那么即便SetWindowsHookEx的第三个参数接收的是dll的路径名那么也不该有性能损失啊。被SetHook的线程触发后载入dll那么dll的在这个载入进程中的首地址他自己是知道的直接加上1000的偏移量不就OK了?
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
#6的话我没看懂,尤其“如果用Dll的地址”您的如果用指的是谁用?
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
另外一个弱弱的问题:好比dll文件首地址是0,GetMsgProc相对于该首地址是的地址1000,这个相对地址应该在编译dll的时候就能确定了吧?需要进程A加载dll之后再通过GetMsgProc A - hinstDll A计算吗?
wangk 2010-04-02
  • 打赏
  • 举报
回复
可以。不过效率会降低。

如果用Dll的地址,那么SetWindowsHookEx函数执行的时候要先在本进程查表获取Dll的加载地址,然后就可以和现在的使用hinstDll一致了。
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
再次谢谢wangk,我了解2,3之差是GetMsgProc相对位移加上具体载入dll文件的hinstDll就是那个具体文件中的GetMsgProc地址,但是这不是我想了解的。
我把问题的方式变一下吧:像我在#2说的假如MS在定制SetWindowsHookEx这个函数时把hinstDll的类型改成PCSTR接受dll文件路径供触发钩子的进程需要时加载,会怎么样呢?
jbz001 2010-04-02
  • 打赏
  • 举报
回复
好多工具我也用的不熟悉
wangk 2010-04-02
  • 打赏
  • 举报
回复
不是,hinstDll配合GetMsgProc,也就是2、3参数用来计算2在其他进程中的函数地址的。

因为对不同进程来说,即使是同一个dll的hinstDll也很有可能是不同的。
yangyanglee111 2010-04-02
  • 打赏
  • 举报
回复
#1说的是,这点我考虑了,但是我在这里只能无知的瞎YY:如果出于这点MS做SetWindowsHookEx时大可把hinstDll改成dll文件路径之类的供触发钩子的进程即可,不必让SetWindowsHookEx的主调进程载入这个“没用”的dll。我只是觉得我这种YY还是有些意义的。要么就是A进程中映射进的dll除了提供hinstDll外有别的用处;要么就是除了提供hinstDll之外真的没用,做成这种形式是出于MS的喜好。不知道到底哪种可能,望得到确切的指点。
wangk 2010-04-02
  • 打赏
  • 举报
回复
如果A不映射Dll怎么得到SetWindowsHookEx第三个参数hinstDll?

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧