为什么相同的HOOK,在98和2000下表现不同,该如何解决? 用exeA将dllB通过HOOK(GETMESSAGE)插入到进程C中,插入成功后,关闭exeA,此时98下dllB仍在进程C中,但2000下dllB却随着exeA的退出也同时从进程C中退出。请问这是怎么回事,该如何解决? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我也发现,查PSDK文档未有说明哪位知道原因? DLL:#include "stdafx.h"#include <afxdllx.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#pragma data_seg("SharedDataName")HHOOK hkb = NULL; HINSTANCE hins = NULL;#pragma data_seg()#pragma comment(linker,"section:shareddata,rws")LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);static AFX_EXTENSION_MODULE Hook1DLL = { NULL, NULL };extern "C" int APIENTRYDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved){ //以上部分略去 hins = hInstance; return 1; // ok}////////////////////////////////////////////////////////////////////////////////////////////////extern "C" _declspec(dllexport) BOOL InstallHook() { DWORD dwThreadId = 0; HWND hFindWnd = NULL; hFindWnd = FindWindow(NULL, "abc"); if(!hFindWnd) { return FALSE; } dwThreadId = GetWindowThreadProcessId(hFindWnd, NULL); hkb = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, hins, dwThreadId); PostThreadMessage(dwThreadId, WM_NULL, 0, 0); return TRUE; }////////////////////////////////////////////////////////////////////////////////////////////////extern "C" _declspec(dllexport) BOOL UnInstallHook(){ UnhookWindowsHookEx(hkb); return TRUE;} ////////////////////////////////////////////////////////////////////////////////////////////////LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx( hkb, nCode, wParam, lParam); }EXE部分只是简单的调用InstallHook和UnInstallHook。HOOK也十分普通,GetMsgProc也只是简单的将消息传下去,没对消息做任何操作。拜托哪位给指点一下,不胜感激。 在98中hook是靠自己来维护的,系统不知道有哪些hook在hook链上。而在2000中系统记录了正在运行的所有hook,所以会导致这样的结果。在98要保持hook链的完整CallNextHookEx的第一个参数不能是NULL,而在2000中系统会忽略这个参数。也是这个道理。 那意思是不是说2000下,系统根据使用hook的进程(exeA)的退出,所以也同时将此hook从hook链中剔除? 如果你是ExeA中调用了UnInstallHook当然就行删除了。如果没有调用UnInstallHook会出现什么情况就不知道了,你可以试试。 在2000中,exe文件使用SetWindowsHookEx给指定线程安装hook后,直接退出,也导致dll退出(情况是提示该内存不可read,是否是dll退出了)。这与PSDK中,关于DLL counter lock的说明不相同? 我的情况正如migr(migr)所说的那样。而且通过VC的DEBUG也确实发现,当使用SetWindowsHookEx的exe文件退出后(未使用UnhookWindowsHookEx),dll确实从被hook的线程中退出了。但不知道为什么? http://ddcrack.myetang.com/assembler/material/iczelion/lion-tut-c24.htm 有一段话:在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。也就是说每个进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。#pragma data_seg预处理指令用于设置共享数据段。例如:#pragma data_seg("SharedDataName")HHOOK hHook=NULL;#pragma data_seg()在#pragma data_seg("SharedDataName")和#pragma data_seg()之间的所有变量 将被访问该Dll的所有进程看到和共享。这样看如果我在DLL中将钩子返回的值先设为共享,这样会不会保留下来呢? 不过如果DLL使用计数器为0了,是不是还要退出呀 我也遇到了这个问题。不但如此,我曾在一个远线程里将DLL加载到寄生的进程中,结果发现如果这个远线程仍在运行那么DLL仍在,如果线程结束了,即使进程仍在DLL也卸载了。这是因为线程结束的时候要减引用次数,减到0了就卸载。我是在2000下的,确实是这样。98下的情况没试过。另外楼上的意见我不大赞同。DLL卸载的时候,全部物理存储器都被回收了,进程空间也没有它的地址了,是不是共享段于事无补。 如果楼主是想保持这个HOOK有效的话,我的建议是建立远线程将DLL注入另一个恒存在的进程中,例如explorer.exe。还要注意不要让这个线程结束掉。有两个方式保持其存活,其一是让它不停的空转,即:while(1){ __asm nop;}不过这样很浪费CPU资源。第二个办法就是建立线程的消息泵,即:GetMessage(){// do someting or nothing...}以上意见供参考。 上贴有个地方说的不恰当,应该是在远线程中启动你的HOOK,即在远线程中LoadLibrary你的DLL并调用其中的函数设置钩子。 关于TOKEN_ELEVATION_TYPE的问题 网络电子邮箱也是用的SMTP协议? 二值图像可以用双线性插值法旋转吗? SoftICE 高手请帮忙 avi播放问题,急,在线等!(分可另加) 如何创建一个文件夹? 马上给分:为什么会跳过delete? activex控件工程中 加入一个自己的写的类会出问题。。。。。。 com组件注册与un注册的问题 求助!!VC调串口的问题!! 怪了 QQ登陆框的标题就是获不到?? 求救!
哪位知道原因?
#include <afxdllx.h>#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif#pragma data_seg("SharedDataName")
HHOOK hkb = NULL;
HINSTANCE hins = NULL;
#pragma data_seg()
#pragma comment(linker,"section:shareddata,rws")
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);static AFX_EXTENSION_MODULE Hook1DLL = { NULL, NULL };extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
//以上部分略去 hins = hInstance;
return 1; // ok
}////////////////////////////////////////////////////////////////////////////////////////////////extern "C" _declspec(dllexport) BOOL InstallHook()
{
DWORD dwThreadId = 0;
HWND hFindWnd = NULL;
hFindWnd = FindWindow(NULL, "abc");
if(!hFindWnd)
{
return FALSE;
}
dwThreadId = GetWindowThreadProcessId(hFindWnd, NULL);
hkb = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, hins, dwThreadId);
PostThreadMessage(dwThreadId, WM_NULL, 0, 0); return TRUE;
}////////////////////////////////////////////////////////////////////////////////////////////////extern "C" _declspec(dllexport) BOOL UnInstallHook()
{
UnhookWindowsHookEx(hkb);
return TRUE;
} ////////////////////////////////////////////////////////////////////////////////////////////////LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx( hkb, nCode, wParam, lParam);
}
EXE部分只是简单的调用InstallHook和UnInstallHook。
HOOK也十分普通,GetMsgProc也只是简单的将消息传下去,没对消息做任何操作。拜托哪位给指点一下,不胜感激。
在98要保持hook链的完整CallNextHookEx的第一个参数不能是NULL,而在2000中系统会忽略这个参数。也是这个道理。
而且通过VC的DEBUG也确实发现,当使用SetWindowsHookEx的exe文件退出后(未使用UnhookWindowsHookEx),dll确实从被hook的线程中退出了。
但不知道为什么?
在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。也就是说每个进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。
因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。
#pragma data_seg预处理指令用于设置共享数据段。例如:
#pragma data_seg("SharedDataName")
HHOOK hHook=NULL;
#pragma data_seg()
在#pragma data_seg("SharedDataName")和#pragma data_seg()之间的所有变量 将被访问该Dll的所有进程看到和共享。这样看如果我在DLL中将钩子返回的值先设为共享,这样会不会保留下来呢? 不过如果DLL使用计数器为0了,是不是还要退出呀
{
__asm nop;
}不过这样很浪费CPU资源。
第二个办法就是建立线程的消息泵,即:GetMessage()
{
// do someting or nothing...
}以上意见供参考。