xml地图|网站地图|网站标签 [设为首页] [加入收藏]
来自 每日资讯 2019-10-01 01:06 的文章
当前位置: 新濠国际登录平台 > 每日资讯 > 正文

那么计算机底层键盘鼠标的驱动就会收到一个消

Hook是什么?

你不能不知道到的Hook!,不知道Hook!

Hook是什么?

    hook翻译之后是钩子的意思,hook的用途主要是用来拦截消息的,看到这里大家可能会迷茫,What is a hook?所以这时就不得不普及一下操作系统的原理。

    举个例子:假如你是一名游戏热衷者,在玩游戏时,你要释放技能那么你就会对键盘鼠标进行操作,表面上你是直接操作游戏,其实中间经过了几个环节。

                  首先,你操作键盘鼠标,那么计算机底层键盘鼠标的驱动就会收到一个消息。

                  然后,这个驱动会把消息传个操作系统。

                  其次,操作系统会判断这个消息是作用在哪个程序上。

                  最后,操作系统会把这个事件传给相应的程序,那么,你就可以看到你操作游戏的样子了。

做自己的Hook!

    好!说了这些,大家想想假如你写了一个hook,在别人的电脑上拦截了这个消息,操作系统就不知道这个消息,你可以把这个消息通过网络发到你的电脑,那个那台电脑的一举一动你都清楚....(当然我教大家这个不是希望你们做坏事,而是同过hook更深入学习计算     机    和保护自己电脑),下面我来同过一个简单的程序来让大家了解hook。

1 int main()
2 {
3     MessageBox(NULL, L"Hello world", L"this",MB_OK);
4     system("pause");
5     return 0;
6 }

  这是一段简单的程序,其功能是为了显示一个对话窗口。这个对话窗口操作系统已经帮我们写好了,我们实际上是在调用这段代码。好!大家想一下我们能不能在调用这个函数之前截断这个调用,让程序调用自己的函数。(想想做插件是不是这个原理)答案是肯定的,我们能够截断这个消息并让他调用自己的函数。下面我们来代码实现一下。

 1 int WINAPI myMSG( HWND hWnd,
 2                   LPCTSTR IpText, 
 3                   LPCTSTR IpCaption,
 4                   UINT uType)
 5 {
 6 
 7     printf("哈哈你的消息被我截断了"); 
 9     return 1;
10 }

     这是我写的一个函数(注意:函数返回值和参数一定要和MessageBox一样,这样接口才能对上,不然会报错),我们要让程序执行我们的函数,那么我们就要写一个钩子。

 1 bool Hook()
 2 {
 3     //获取调用代码的首地址
 4     PROC p = GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW");
 5     if (!p) return 0;
 6 
 7            BYTE b[5] = { 0 };
 8     //0xE9无条件跳转(学过汇编的同学应该知道)
 9     b[0] = 0xE9;
10        //计算偏移地址。 偏移地址 = 跳转地址-MessageBox的地址 
11     *(DWORD*)(b + 1) = (DWORD)myMSG - (DWORD)p - 5;
12        /*通过上面三行代码,这个数组储存的代码意思是(无条件跳转到我的函数地址位置)*/
13 
14         //在计算位置的内存中写入数据
15     WriteProcessMemory(GetCurrentProcess(), p, b, 5, NULL);
16     return 1;
17 }

     我已经写好了一个钩子,下面我放出完整程序的代码

 1  #include <stdio.h>
 2  #include <Windows.h>
 3  
 4  int WINAPI myMSG( HWND hWnd,
 5                     LPCTSTR IpText, 
 6                    LPCTSTR IpCaption,
 7                     UINT uType)
 8   {
 9       printf("哈哈你的消息被我截断了");
10      return 1;
11  }
12  
13  bool Hook()
14  {
15       //获取调用代码的首地址
16       PROC p = GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW");
17       if (!p) return 0;
18   
19              BYTE b[5] = { 0 };
20       //0xE9无条件跳转(学过汇编的同学应该知道)
21       b[0] = 0xE9;
22         //计算偏移地址。 偏移地址 = 跳转地址-MessageBox的地址 
23      *(DWORD*)(b + 1) = (DWORD)myMSG - (DWORD)p - 5;
24         /*通过上面三行代码,这个数组储存的代码意思是(无条件跳转到我的函数地址位置)*/
25  
26          //在计算位置的内存中写入数据
27      WriteProcessMemory(GetCurrentProcess(), p, b, 5, NULL);
28      return 1;
29  }
30  int main() 
31 { 
32      Hook(); 
33      MessageBox(NULL, L"Hello world", L"this",MB_OK);         system("pause");
34      return 0; 
35     }

 

    首先我们把Hook注释掉运行。运行结果如下。

新濠国际登录平台 1

     如何加上hook,你会发现一件令人兴奋的事情,并没有弹出对话框。运行结果如下

新濠国际登录平台 2

 

   通过这个例子相信大家对hook有了一些了解,现在大家肯能会有一个疑问,我能跳转,能不能回去呢,答案是能的。我也给大家提供一个点思路ReadProcessMemory()用这个api来保存原来的段地址和内存中的代码,回去时在利用WriteProcessMemory()再跳转一次,就可以会到原来调用的代码处了,这些是不是很棒,大家可以回家自行试验,也可以巩固一下今天所学的知识。

  如果中间有什么错误,还请高手能帮我指出。

 

Hook是什么? hook翻译之后是钩子的意思,hook的用途主要是用来拦截消息的,看到这里大家可能会迷茫...

Windows API 教程(七) hook 钩子监听

Posted on 2013-08-15

    hook翻译之后是钩子的意思,hook的用途主要是用来拦截消息的,看到这里大家可能会迷茫,What is a hook?所以这时就不得不普及一下操作系统的原理。

茵蒂克丝

  • 如何创建一个窗口
    • 手动创建窗口的流程
    • 实际代码
  • 安装钩子 (Install hook)
    • 钩子简介
    • SetWindowsHookEx 函数
  • 设置监听【键盘】消息
  • 设置监听【鼠标】消息

    举个例子:假如你是一名游戏热衷者,在玩游戏时,你要释放技能那么你就会对键盘鼠标进行操作,表面上你是直接操作游戏,其实中间经过了几个环节。

如何创建一个窗口

另外一个再录的 Windows SDK教程 里面有讲到快捷创建窗口的方式,不过这样的话要分好几个文件,感觉有点混所以这里就用原始的方式创建一个窗口。

那么,为什么讲到 hook(钩子)的时候要去创建窗口呢?其实这个问题说起来也不复杂,简单点说,按博主这样写不用写DLL也不用资源文件,实际上是把问题简化了一些。通常 hook 是用来监听自己窗口上的键盘和鼠标输入的,监听全局的通常是设置一些全局的热键(如QQ的 Ctrl+Alt+Z 调出QQ窗口),这些常见的功能也都是要依托窗口才能存在。所以我们先来简单说下手动建立一个窗口的流程。

                  首先,你操作键盘鼠标,那么计算机底层键盘鼠标的驱动就会收到一个消息。

手动创建窗口的流程

  1. 设置注册窗口结构体
  2. 使用【窗口结构体】注册窗口
  3. 创建窗口
  4. 显示窗口
  5. 窗口过程处理
  6. 消息循环

                  然后,这个驱动会把消息传个操作系统。

实际代码

这里不会详细讲这个,有感兴趣的可以去追博主的 SDK教程 或者去搜 杨中科的《C语言也能干大事》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <windows.h>
 
// 5. 窗口过程处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{  
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;  // 更多详细都可以去百度的 http://baike.baidu.com/view/1750396.htm
    HWND hwnd;
    MSG Msg;
    char text[30];
 
    const char szClassName[] = "myWindowClass";
 
    // 1. 设置注册窗口结构体
    wc.cbSize        = sizeof(WNDCLASSEX);              // 注册窗口结构体的大小
    wc.style         = 0;                               // 窗口的样式
    wc.lpfnWndProc   = WndProc;                         // 指向窗口处理过程的函数指针
    wc.cbClsExtra    = 0;                               // 指定紧跟在窗口类结构后的附加字节数
    wc.cbWndExtra    = 0;                               // 指定紧跟在窗口事例后的附加字节数
    wc.hInstance     = hInstance;                       // 本模块的实例句柄
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 光标的句柄
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);        // 背景画刷的句柄
    wc.lpszMenuName  = NULL;                            // 指向菜单的指针
    wc.lpszClassName = szClassName;                     // 指向类名称的指针
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标
 
    // 2. 使用【窗口结构体】注册窗口
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
 
    // 3. 创建窗口
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,       // 窗口的扩展风格
        szClassName,            // 指向注册类名的指针
        TEXT("窗口标题"),       // 指向窗口名称的指针
        WS_OVERLAPPEDWINDOW,    // 窗口风格
        CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高
        NULL,                   // 父窗口的句柄
        NULL,                   // 菜单的句柄
        hInstance,              // 应用程序实例的句柄
        NULL                    // 指向窗口的创建数据
        );
 
    if(hwnd == NULL)
    {
        MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
 
    // 4. 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
 
    // 6. 消息循环
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

因为是比较死的形式,以上代码大家混个脸熟,大概知道各个部分的作用就行了,博主也从来没有专门记过。

                  其次,操作系统会判断这个消息是作用在哪个程序上。

安装钩子 (Install hook)

                  最后,操作系统会把这个事件传给相应的程序,那么,你就可以看到你操作游戏的样子了。

简介

窗口建好了之后就要开始转到我们的正题了,首先我们需要明确的是,这个钩子(hook)到底是什么,那么博主这里也不做太书面的解释留下几个链接:

百度百科:hook
MSDN: Hooks.aspx)
博客园: Beginning HOOK

各位可以多多参考,那么博主说下自己的理解:

windows 系统中的【hook 机制】,就类似于一个【消息过滤网】,如果我们向操作系统申请并成功对某个窗口安装了一个【hook】指定了【回调函数】,那么这个【回调函数】也就相当于我们人为对这个窗口添加了一个【消息过滤网】。此时当 windows 操作系统要对这个窗口发送任何消息的时候(例如按键、鼠标点击等消息)操作系统会先调用我们在【消息过滤网】中设置的【回调函数】去接受、处理、过滤等等,当然如果你在【回调函数】中拿到了数据却没有继续传递给窗口的话,就相当于拦截了这些消息。

打个简单的比方,如果你在系统全局安装了一个【键盘消息】的钩子,并且在其指定的【回调函数】中没有把这个键盘消息继续传递给系统上的窗口,那么你的所有【键盘消息】都被这个【hook】也就我们挂在这个【消息过滤网】上的【回调函数】给拦截了,这也意味着你的键盘会失灵。

做自己的Hook!

SetWindowsHookEx 函数

新濠国际登录平台,那么 SetWindowsHookEx 函数就是我们用来在 windows 操作系统上安装钩子的函数,我们简单来看一下这个函数的原型:

1
2
3
4
5
6
HHOOK WINAPI SetWindowsHookEx(
  _In_  int idHook,         // 安装的钩子类型
  _In_  HOOKPROC lpfn,      // 处理消息的回调函数
  _In_  HINSTANCE hMod,     // 当前实例句柄
  _In_  DWORD dwThreadId    // 线程ID
);

钩子类型有很多种,本页中留的大部分链接上都有讲到这里就不废话了,关于 hMod(当前实例句柄)和 dwThreadId(线程ID)之间的一些小九九博主这里也不多说,各位可以到下方的链接中去看看,博主这里就举一个容易实现的实例。

百度百科: SetWindowsHookEx
MSDN: SetWindowsHookEx;k(SETWINDOWSHOOKEX);k(DevLang-%22C%2B%2B%22);k(TargetOS-WINDOWS)&rd=true)

本文由新濠国际登录平台发布于每日资讯,转载请注明出处:那么计算机底层键盘鼠标的驱动就会收到一个消

关键词: