小圈圈 发表于 2016-6-21 15:34:50

Visual Studio2013 设置全局钩子遇到的问题

本帖最后由 小圈圈 于 2016-6-21 15:38 编辑

1.Hook简介:作用是拦截某些消息,关键函数是SetWindowsHookEX()
2实例:编写一个屏蔽所有进程和所有线程的钩子程序。钩子函数在DLL中,要被某个程序调用才行。
1.新建一个DLL工程名为0616Hook
2.增加0616Hook.cpp
3.代码如下:
#include <windows.h>包含头文件

HHOOK g_hMouse=NULL;
HHOOK g_hKeyboard=NULL;

#pragma data_seg("MySec")新建了一个节,用于将下 面的这个变量设为全局共享。
HWND g_hWnd=NULL;这个变量是全局共享的。
#pragma data_seg()

//#pragma comment(linker,"/section:MySec,RWS")
/*HINSTANCE g_hInst;

BOOL WINAPI DllMain(
   HINSTANCE hinstDLL,// handle to the DLL module
   DWORD fdwReason,   // reason for calling function
   LPVOID lpvReserved   // reserved
)
{
g_hInst=hinstDLL;
}*/

LRESULT CALLBACK MouseProc(
   int nCode,      // hook code
   WPARAM wParam,// message identifier
   LPARAM lParam   // mouse coordinates
)
{
return 1;拦截了鼠标消息。
}

LRESULT CALLBACK KeyboardProc(
   int code,       // hook code
   WPARAM wParam,// virtual-key code
   LPARAM lParam   // keystroke-message information
)
{
if(VK_F2==wParam)如果是F2键,则退出。
{
   SendMessage(g_hWnd,WM_CLOSE,0,0);
   UnhookWindowsHookEx(g_hMouse);当退出时将钩子卸掉。
   UnhookWindowsHookEx(g_hKeyboard);
}
return 1;
}

void SetHook(HWND hwnd)此函数设置了钩子。
{
g_hWnd=hwnd;注意这种传递调用它的进程的句柄的方法,比较巧妙!
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle("Hook"),0);
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("Hook"),0);
}

0616Hook.DEF的代码如下:
LIBRARY Hook
EXPORTS
SetHook@2
SEGMENTS
MySec READ WRITE SHARED也可以设置节的属性。
    4.新建一个工程调用此钩子函数。工程名为0619HookTest,基于对话框的。在OnInitDialog()中调用SetHook(),要事先声明_declspec(dllimport) void SetHook(HWND hwnd);
      然后在右键工程->属性->链接器->输入 加入0616Hook.lib,并将0616Hook.dll和0616Hook.lib拷贝到当前目录。
int cxScreen,cyScreen;
cxScreen=GetSystemMetrics(SM_CXSCREEN);
cyScreen=GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(&wndTopMost,0,0,cxScreen,cyScreen,SWP_SHOWWINDOW);将窗口保持在最前面。
SetHook(m_hWnd);
但是最终运行的时候出现一个问题:窗口能正常打开关闭,但是写入的钩子函数没起作用,想要调试定位,但是……

由于dll是自己写的,调试的时候要加载编译dll生成的pdb文件,但问题是不知道怎么把这个pdb加载进来(下面的浏览并查找0616Hook.pdb试过了,没用的)
这时改造函数,让SetHook函数有返回值,根据返回值MessageBox弹出不同窗口。
bool SetHook(HWND hwnd)
{
    g_hwnd = hwnd;
    g_hMouse = ::SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle("0616Hook.dll"), 0);
    g_hKeyboard = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle("0616Hook.dll"), 0);
    if (g_hMouse)
      return true;
    else
      return false;
}
窗口测试程序修改为
if (!SetHook(m_hWnd))
    {
      MessageBox("创建钩子失败!");
    }
最终定位到
::SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle("0616Hook.dll"), 0);
::SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle("0616Hook.dll"), 0);
这两个函数返回的是空指针
那么问题来了,0616Hook.dll和0616Hook.lib已经放在测试程序的根目录下了,.lib文件也链接了,但SetWindowsHookEx函数就是不生效。问了一下冰琥珀,说把GetModuleHandle("0616Hook.dll")单拎出来看返回值,没想到奇迹出现了


全局钩子竟然生效了,虽然还有些许问题,想必这是第一次看到360报警还这么激动吧!
这次学会了两个东西:1、debug的时候思路要灵活,没有de不掉的bug 2、有些bug就是这么稀里糊涂的被de掉的,谁也说不清楚为什么。。

wtsqq123 发表于 2016-6-21 16:30:25

Sty,涛 发表于 2016-6-21 18:52:05

云游者 发表于 2016-6-21 20:36:53

云游者 发表于 2016-6-21 23:56:41

CHRIS 发表于 2016-6-22 00:51:55

支持,看起来还是可以的

CHRIS 发表于 2016-6-22 01:40:39

谢谢楼主的分享

ruguoruo 发表于 2016-6-22 03:32:01

谢谢楼主的分享

cl476874045 发表于 2016-6-22 03:45:47

谢谢楼主的分享

54hacker 发表于 2016-6-22 05:45:04

非常感谢
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: Visual Studio2013 设置全局钩子遇到的问题