acococ 发表于 2016-11-28 20:29:03

windows 消息钩子 KeyHook 函数问题

首先是主程序:
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include <iostream>

#define DEF_DLL_NAME "hookDLL.dll"
#define DEF_HOOKSTART "HookStart"
#define DEF_HOOKSTOP "HookStop"

typedef void(*PFN_HOOKSTART)();//类型定义 PFN_HOOKSTART A 等价于 void(*a)()
typedef void(*PFN_HOOKSTOP)();

void main()
{
       //#define DECLARE_HANDLE(name) struct name##__{ int unused; };
      //typedef struct name##__ *name;
      //DECLARE_HANDLE(HINSTANCE);
      //typedef HINSTANCE HMODULE;
      HMODULE hDll = NULL;//模块句柄
       PFN_HOOKSTART HookStart = NULL;
      PFN_HOOKSTOP HookStop = NULL;
       unsigned int Error, Error1;
      char ch = 0;

      hDll = LoadLibraryA(DEF_DLL_NAME);//静态链接
       if (hDll <= 0)
      {
                std::cout << "modole Load failed " << std::endl;
                system("pause");
                return;
      }
      else
                std::cout << "Load the success.modole address:"<<hDll << std::endl;
               
      
      try
      {
                //GetProcAddress如果函数调用成功,返回值是DLL中的输出函数地址。
                //如果函数调用失败,返回值是NULL。得到进一步的错误信息,调用函数GetLastError
                //第一个参数:包含此函数的DLL模块的句柄。LoadLibrary、AfxLoadLibrary 或者GetModuleHandle函数可以返回此句柄。
                //第二个参数:包含函数名的以NULL结尾的字符串,或者指定函数的序数值。
                //如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。
               HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
               if (!HookStart)
                        throw Error = GetLastError();
                HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
                if (!HookStop)
                        throw Error1 = GetLastError();
      }
       catch (unsigned int)
      {
                if (!HookStart)
                        std::cout << "Load failed:" << Error << std::endl;
                else if (!HookStop)
                        std::cout << "Load failed:" << Error1 << std::endl;
                return;
      }
      
                HookStart();
                printf("press 'q' to quit!\n");                //消息循环
                while (_getch() != 'q');
                        HookStop();
                        FreeLibrary(hDll);
      
               
      system("pause");
}

下面为HookDLL的代码部分:
#include "stdio.h"
#include "windows.h"
#include <iostream>
#define DEF_PROCSS_NAME "notepad.exe"

HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
/*静态链接时,或动态链接时调用LoadLibrary和FreeLibrary都会调用DllMain函数
第二个参数指明了系统调用DLL的原因.
它可能是::
DLL_PROCESS_ATTACH--进程映射
DLL_PROCESS_DETACH--进程卸载
DLL_THREAD_ATTACH--线程映射
DLL_THREAD_DETACH--线程卸载。
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpveserved)
{
        switch (dwReason)
        {
        case DLL_PROCESS_ATTACH:
                std::cout << "HookDll Attach " << std::endl;
                g_hInstance = hinstDLL;
                break;
        case DLL_PROCESS_DETACH:
                std::cout << "HookDll Detach " << std::endl;
                break;
        }
        return TRUE;
}

/*
nCode:根据这个数值决定怎样处理消息
code可以是下列值:
HC_ACTION:wParam和lParam包含按键消息
HC_NOREMOVE:wParam和lParam包含按键消息,并且按键消息不能从消息队列中移除(一个被PeekMessage函数调用的请求,指定PM_NOREMOVE标志)
wParam:
按键的虚拟键值消息,例如:VK_F1
lParam:
32位内存,内容描述包括:指定扩展键值,扫描码,上下文,重复次数。
*/
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
        char szPath[MAX_PATH] = { 0, };
        char *p = NULL;
        //MessageBox(NULL, TEXT("来到这里了"), TEXT("HOOK"), MB_OK);
        if (nCode = 0)
        {
                //bit 31: 0=key press,1 = key release
                if (!(lParam & 0x80000000))//释放键盘按键时
                {
                        //获取当前进程已加载模块的文件的完整路径,该模块必须由当前进程加载。
                       
                        GetModuleFileNameA(NULL, szPath, MAX_PATH);
                        std::cout << szPath << std::endl;
                        p = strrchr(szPath, '\\');

                        //比较当前进程名称,若为notepad.exe,则消息不会传递给应用程序(或下一个钩子)
                        if (!_stricmp(p + 1, DEF_PROCSS_NAME))
                        {
                                return 0;
                        }
                }
        }

        return CallNextHookEx(g_hHook, nCode, wParam, lParam);//调用下一个HOOK函数
}

#ifdef __cplusplus
extern "C" {
#endif
        __declspec(dllexport) void HookStart()
        {
                g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
                if (g_hHook == NULL)
                {
                        std::cout << "Hook failed" << std::endl;
                }
                else
                        std::cout << "Hook success return: " << g_hHook << std::endl;
        }
        __declspec(dllexport) void HookStop()
        {
                if (g_hHook)
                {
                        UnhookWindowsHookEx(g_hHook);
                        g_hHook = NULL;
                }
        }
#ifdef __cplusplus
}
#endif


acococ 发表于 2016-11-28 20:38:25

上面这段代码是安装键盘钩子,只要发现键盘输入事件,OS就会强制将HookDLL注入相应进程.加载HookDLL的进程中.发生键盘事件时会首先调用执行HookDLL.KeyboardProc().
KeyboardProc()函数中发生键盘输入事件时,就会比较当前进程的名称与"notepad.exe"字符串,若相同,则返回1,终止KeyboardProc()函数,这意味着截获删除消息,这样,键盘消息就不会传递到notepad.exe程序的消息队列.

问题是我怎么运行了这个程序后 并没有这样的效果 到底是哪里出了问题????

acococ 发表于 2016-11-29 20:08:26

都一天了 来个大神帮帮忙解决一下吧
页: [1]
查看完整版本: windows 消息钩子 KeyHook 函数问题