可惜一个漂亮mm已经问了,大家都嫌她分少。本着助人为乐的精神,帮她问问。请大家帮忙啊。监视WM_ENDSESSION和WM_QUERYENDSESSION消息用了全局钩子,可是我用了还是没有反应,
不知哪位有过相关经验,如能告知,不胜感激!我在dll里建立了一个全局的钩子,如下:
SetWindowsHookEx(WH_GETMESSAGE, MyProc, hInst, 0);回掉函数中来监视消息
LRESULT CALLBACK MyProc(int code, WPARAM wParam, LPARAM lParam)
{
switch (((MSG*)lParam)->message)
{
case WM_QUERYENDSESSION:
{
switch( ((MSG*)lParam)->lParam )
{
case ENDSESSION_LOGOFF:
{
AfxMessageBox(TEXT("log off"));
//some other functions here
((MSG*)lParam)->message=NULL;
}
break;
}
}
return ::CallNextHookEx(g_hHookscreensaver, code, wParam, lParam);
}可是点击注销后,没有弹出对话框,而且消息没有变空,还是直接注销了!
不知道为什么?
不知哪位有过相关经验,如能告知,不胜感激!我在dll里建立了一个全局的钩子,如下:
SetWindowsHookEx(WH_GETMESSAGE, MyProc, hInst, 0);回掉函数中来监视消息
LRESULT CALLBACK MyProc(int code, WPARAM wParam, LPARAM lParam)
{
switch (((MSG*)lParam)->message)
{
case WM_QUERYENDSESSION:
{
switch( ((MSG*)lParam)->lParam )
{
case ENDSESSION_LOGOFF:
{
AfxMessageBox(TEXT("log off"));
//some other functions here
((MSG*)lParam)->message=NULL;
}
break;
}
}
return ::CallNextHookEx(g_hHookscreensaver, code, wParam, lParam);
}可是点击注销后,没有弹出对话框,而且消息没有变空,还是直接注销了!
不知道为什么?
解决方案 »
- Insert into not exist 的问题
- 控制台vc应用错误
- 又送分啦!
- 如何使用iphlpapi.dll呢?弱弱地问
- 我用ENUM可以找到所有能在"网上邻居"显示的计算机,但是怎么样能能把所有能PING到的机子都找出来呢?
- 用 SQLConfigDataSource 怎么建立一个目录为 d:\ 的 free table 数据源?
- 请问动态添加的Listctrl控件如何响应WM_LBUTTONDOWN消息???
- vc如何快速入门?
- 根据端口映射方式,NAT的分类问题
- 急!急!如何增大状态栏的字体大小?(
- 我的服务器程序接受到多个客户端的连接,每个连接我用一个SOCKET句柄保存,在发送数据的时候我就根据已有的SOCKET句柄进行发送,但是我不
- 在vc设计控件时,怎样向VB那样有一个界面,可以在上面加入其它控件,所见即所得
2 确认一下switch语句是否走到了;
另外,我认为监视注销最好的方法是API HookHook API:ExitWindows/ExitWindowsEx
不是使用强制的方法,是正常的注销,就是因为在switch处设了断点也没用,才想问问各位经验丰富的人啦!
要注意的是:因为系统存在的窗口可能比较多,所以用钩子拦截这个消息的时候会出现很多次!
我去试试看。谢谢啦,有问题可能还要麻烦您呢!
其实我不是要阻止,那是试验,是想判断到用户注销,在注销前先处理自己的一些函数!
我刚用WH_CALLWNDPROC钩子试了一下,不能响应注销消息呀,一点注销系统就说是否结束调试,应该怎么设参数,怎么响应消息呀?
{
switch (((CWPSTRUCT*)lParam)->message)
{
case WM_QUERYENDSESSION:
{
switch( ((CWPSTRUCT*)lParam)->lParam )
{
case ENDSESSION_LOGOFF:
{
FILE *pFile = NULL;
((CWPSTRUCT*)lParam)->message = 0;
AfxMessageBox(TEXT("log off"));
return 0;
}
break;
}
}
}
return ::CallNextHookEx(g_hMessage, code, wParam, lParam);
}
拦截api
遇到这个问题,顺便再去研究研究拦截api的hook。以前没用过,今天一搜看见好多帖子,学习ing~~~
{
LPCSTR szFunc;//被HOOK的API函数名称。
PROC pNewProc;//替代函数地址。
PROC pOldProc;//原API函数地址。
}HOOKAPI, *LPHOOKAPI; (3) 打开ActiveKey.cpp文件,首先加入一个函数,用于定位输入库在输入数据段中的IAT地址。代码如下: extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR
LocationIAT(HMODULE hModule, LPCSTR szImportMod)
//其中,hModule为进程模块句柄;szImportMod为输入库名称。
{
//检查是否为DOS程序,如是返回NULL,因DOS程序没有IAT。
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;
if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;
//检查是否为NT标志,否则返回NULL。
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+ (DWORD)(pDOSHeader->e_lfanew));
if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;
//没有IAT表则返回NULL。
if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL;
//定位第一个IAT位置。
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
//根据输入库名称循环检查所有的IAT,如匹配则返回该IAT地址,否则检测下一个IAT。
while (pImportDesc->Name)
{
//获取该IAT描述的输入库名称。
PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name));
if (stricmp(szCurrMod, szImportMod) == 0) break;
pImportDesc++;
}
if(pImportDesc->Name == NULL) return NULL;
return pImportDesc;
} 再加入一个函数,用来定位被挡截API函数的IAT项并修改其内容为替代函数地址。代码如下: extern "C" __declspec(dllexport)
HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI pHookApi)
//其中,hModule为进程模块句柄;szImportMod为输入库名称;pHookAPI为HOOKAPI结构指针。
{
//定位szImportMod输入库在输入数据段中的IAT地址。
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule, szImportMod);
if (pImportDesc == NULL) return FALSE;
//第一个Thunk地址。
PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk));
//第一个IAT项的Thunk地址。
PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk));
//循环查找被截API函数的IAT项,并使用替代函数地址修改其值。
while(pOrigThunk->u1.Function)
{
//检测此Thunk是否为IAT项。
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
//获取此IAT项所描述的函数名称。
PIMAGE_IMPORT_BY_NAME pByName =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData));
if(pByName->Name[0] == '\0') return FALSE;
//检测是否为挡截函数。
if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0)
{
MEMORY_BASIC_INFORMATION mbi_thunk;
//查询修改页的信息。
VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
//改变修改页保护属性为PAGE_READWRITE。
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
//保存原来的API函数地址。
if(pHookApi->pOldProc == NULL)
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function;
//修改API函数IAT项内容为替代函数地址。
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc;
//恢复修改页保护属性。
DWORD dwOldProtect;
VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);
}
}
pOrigThunk++;
pRealThunk++;
}
SetLastError(ERROR_SUCCESS); //设置错误为ERROR_SUCCESS,表示成功。
return TRUE;
} (4) 定义替代函数,此实例中只给MessageBoxA和recv两个API进行挡截。代码如下: static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
//过滤掉原MessageBoxA的正文和标题内容,只显示如下内容。
return MessageBox(hWnd, "Hook API OK!", "Hook API", uType);
}
static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )
{
//此处可以挡截游戏服务器发送来的网络数据包,可以加入分析和处理数据代码。
return recv(s,buf,len,flags);
} (5) 在KeyboardProc函数中加入激活挡截API代码,在if( wParam == 0X79 )语句中后面加入如下else if语句: ......
//当激活F11键时,启动挡截API函数功能。
else if( wParam == 0x7A )
{
HOOKAPI api[2];
api[0].szFunc ="MessageBoxA";//设置被挡截函数的名称。
api[0].pNewProc = (PROC)MessageBoxA1;//设置替代函数的地址。
api[1].szFunc ="recv";//设置被挡截函数的名称。
api[1].pNewProc = (PROC)recv1; //设置替代函数的地址。
//设置挡截User32.dll库中的MessageBoxA函数。
HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);
//设置挡截Wsock32.dll库中的recv函数。
HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&api[1]);
}
...... (6) 在ActiveKey.cpp中加入头文件声明 "#include "wsock32.h"。 从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标签,在“对象/库模块”中输入Ws2_32..lib。 (7) 重新编译ActiveKey项目,产生ActiveKey.dll文件,将其拷贝到Simulate.exe目录下。运行Simulate.exe并启动全局钩子。激活任意应用程序,按F11键后,运行此程序中可能调用MessageBoxA函数的操作,看看信息框是不是有所变化。同样,如此程序正在接收网络数据包,就可以实现封包功能了。抄来的文章,没测试过 :)
如果要拦截所有应用程序的API,应该使用WH_GETMESSAGE等钩子
就是一个DLL,HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify下创建一个项项里的说明:
Asynchronous[REG_DWORD]:表明是否异步处理winlogon事件,如设为 1,winlogon将启动一个新线程来处理。
DllName[REG_EXPAND_SZ]:指定要加载的DLL名。
Impersonate[REG_DWORD]:表明是否以登陆用户的权限来处理事件。
Lock[REG_SZ]:锁定桌面事件。
Logoff[REG_SZ]:注销事件。
Logon[REG_SZ]:登陆事件。
Shutdown[REG_SZ]:关机事件。
StartScreenSaver[REG_SZ]:启动屏保事件。
StartShell[REG_SZ]:启动shell(一般指explorer.exe)事件。
Startup[REG_SZ]:系统开机事件。
StopScreenSaver[REG_SZ]:停止屏保事件。
Unlock[REG_SZ]:解除桌面锁定事件。
void CListeningSocket::OnAccept(int nErrorCode)
{
.........//要写什么就看你自己的了
}
定义了一个OnAccept()函数却没有实现,当然会出错了