分享
 
 
 

通过挂钩插入DLL(转载)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

可以使用挂钩将D L L插入进程的地址空间。为了使挂钩能够像它们在1 6位Wi n d o w s中那样工作,M i c r o s o f t不得不设计了一种方法,使得D L L能够插入另一个进程的地址空间中。

下面让我们来看一个例子。进程A(类似Microsoft Spy++的一个实用程序)安装了一个挂钩W N _ G E T M E S S A G E,以便查看系统中的各个窗口处理的消息。该挂钩是通过调用下面的S e t Wi n d o w s H o o k E x函数来安装的:

第一个参数W H _ G E T M E S S A G E用于指明要安装的挂钩的类型。第二个参数G e t M s g P r o c用于指明窗口准备处理一个消息时系统应该调用的函数的地址(在你的刂房占渲校5三个参数h i n s t D l l用于指明包含G e t M s g P r o c函数的D L L。在Wi n d o w s中,D L L的h i n s t D l l的值用于标识DLL被映射到的进程的地址空间中的虚拟内存地址。最后一个参数0用于指明要挂接的线程。

对于一个线程来说,它可以调用S e t Wi n d o w s H o o k E x函数,传递系统中的另一个线程的I D。通过为这个参数传递0,就告诉系统说,我们想要挂接系统中的所有G U I线程。

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

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 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的环境下运行的线程中调用。

若要为另一个进程中的线程创建的窗口建立子类,首先可以在创建该窗口的挂钩上设置一个W H _ G E T M E S S A G E挂钩,然后,当G e t M s g P r o c函数被调用时,调用S e t Wi n d o w L o n g P t r函数 来建立窗口的子类。当然,子类的过程必须与G e t M s g P r o c函数位于同一个D LL中。

与插入D L L的注册表方法不同,这个方法允许你在另一个进程的地址空间中不再需要DL L时删除该D L L的映像,方法是调用下面的函数:

当一个线程调用U n h o o k Wi n d o w s H o o k E x函数时,系统将遍历它必须将D L L插入到的各个进程的内部列表,并且对D L L的自动跟踪计数进行递减。当自动跟踪计数时,D L L就自动从进程的地址空间中被删除。应该记得,就在系统调用G e t M s g P r o c前,它对D L L的自动跟踪计数进行了递增(见上面的第6个步骤)。

该自动跟踪计数没有递增,那么当进程B的线程试图执行G e t M s g P r o c函数中的代胧,系统中运行的另一个线程就可以调用U n l o o k Wi n d o w s H o o k E x函数。

这一切意味着不能撤消该窗口的子类并且立即撤消该挂钩。该挂钩必须在该子类的寿命期内保持有效状态。

3.使用远程线程插入DLL

插入D L L的另一个方法是使用远程线程。这种方法具有更大的灵活性。它要求你懂得若干个Wi n d o w s特性、如进程、线程、线程同步、虚拟内存管理、D L L和U n i c o d e等(如果对这些特性不清楚,请参阅本书中的有关章节)。Wi n d o w s的大多数函数市斫讨欢宰己进行操作。

这是很好的一个特性,因为它能够防止一个进程破坏另一个进程的运行。但是,有些函数却允许一个进程对另一个进程进行操作。这些函数大部分最初是为调试程序和其他工具杓的。不过任何函数都可以调用这些函数。

这个D L L插入方法基本上要求目标进程中的线程调用L o a d L i b r a r y函数来载必要的D L L。

由于除了自己进程中的线程外,我们无法方便地控制其他进程中的线程,因此这种解决方案要求我们在目标进程中创建一个新线程。由于是自己创建这个线程,因此我们能够控扑执行什么代码。幸好,Wi n d o w s提供了一个称为C r e a t e R e m o t e T h r e a d的函数,使我们能够非常容易地在另一个进程中创建线程:

C r e a t e R e m o t e T h r e a d与C r e a t e T h r e a d很相似,差别在于它增加了一个参数h P r o c e s s。该参数指明拥有新创建线程的进程。参数p f n S t a r t A d d r指明线程函数的内存地址。当然,该内存地址与远程进程是相关的。线程函数的代码不能位于你自己进程的地址空间中。

Windows 98 在Windows 98中,C r e a t e R e m o t e T h r e a d函数不存在有用的实现代码,它只是返回N U L L。调用G e t L a s t E r r o r函数将返回E R R O R _ C A L L _ N O T _ I M P L E M E N T E D(C r e a t e T h r e a d函数包含用于在调用进程中创建线程的完整的实现代码)。由于C r e a t e R e m o t e T h r e a d没有实现,因此,在Windows 98下,不能使用本方法来插入D L L。

好了,现在你已经知道如何在另一个进程中创建线程了,但是,如何才能让该线程加载我们的D L L呢?答案很简单,那就是需要该线程调用L o a d L i b r a r y函数。

我们将详细步骤说明如下:

1) 使用Vi r t u a l A l l o c E x函数,分配远程进程的地址空间中的内存。

2) 使用Wr i t e P r o c e s s M e m o r y函数,将D L L的路径名拷贝到第一个步骤中已经分配的内存中。

3) 使用G e t P r o c A d d r e s s函数,获取L o a d L i b r a r y A或L o a dL i b r a t y W函数的实地址(在K e r n e l 3 2 . d l l中)。

4) 使用C r e a t e R e m o t e T h r e a d函数,在远程进程中创建一个线程,它调用正确的L o a d L i b r a r y函数,为它传递第一个步骤中分配的内存的地址。这时, D L L已经被插入远程进程的地址空间中,同时D L L的D l l M a i n函数接收到一个D L L _ P R O C E S S _ AT TA C H通知,并且能够执行需要的代码。当D l l M a in函数返回时,远程线程

从它对L o a d L i b r a r y的调用返回到B a s e T h r e a d S t a r t 函数(第6 章中已经介绍。然后B a s e T h r e a d S t a r t调用E x i t T h r e a d,使远程线程终止运行。

现在远程进程拥有第一个街柚蟹峙涞哪诖婵椋鳧 L L则仍然保留在它的地址空间中。

若要将它删除,需要在远程线程退出后执行下面的步骤:

5) 使用Vi r t u a l F r e e E x函数,释放第一个步骤中分配的内存。

6) 使用G e t P r o c A d d r e s s函数,获得F r e e L i b r a r y函数的实地址(在K e r n e l 3 2 . d l l中)。

7) 使用C r e a t e R e m o t e T h r e a d函数,在远程进程中创建一个线程,它调用F r e e L i b r a r y函数,传递远程D L L的H I N S TA N C E。

这就是它的基本操作步骤。这种插入D L L的方法存在的唯一一个不足是, Windows 98并不支持这样的函数。只能在Windows 2000上使用这种方法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有