鱼C论坛

 找回密码
 立即注册
查看: 2092|回复: 2

windows 消息钩子 KeyHook 函数问题

[复制链接]
发表于 2016-11-28 20:29:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
首先是主程序:
#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


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

问题是我怎么运行了这个程序后 并没有这样的效果 到底是哪里出了问题????
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-11-29 20:08:26 | 显示全部楼层
都一天了 来个大神帮帮忙解决一下吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-27 18:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表