Hook是什么?

您无法不知道到的Hook!,不驾驭Hook!

Hook是什么?

 
 
 hook翻译之后是钩子的意思,hook的用处主若是用来阻拦消息的,看到此间大家莫不会盲目,What is a
hook?所以此时就不得不普及一下操作系统的规律。

   
举个例证:假若你是一名玩耍热衷者,在玩游戏时,你要自由技能那么您就会对键盘鼠标举办操作,表面上你是直接操作游戏,其实当中经过了多少个环节。

                 
首先,你操作键盘鼠标,那么总计机底层键盘鼠标的驱动就会吸收接纳二个音信。

                  然后,那几个驱动会把音信传个操作系统。

                  其次,操作系统会咬定那么些音讯是效果在哪个程序上。

                 
最终,操作系统会把那个事件传给相应的次第,那么,你就足以见到你操作游戏的榜样了。

做团结的Hook!

   
好!说了那几个,我们想想假若你写了2个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个钩子。

 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个钩子,上边笔者放出一体化程序的代码

 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()再跳转1次,就能够会到原来调用的代码处了,这几个是或不是很棒,大家可以回家自行试验,也得以巩固一下前些天所学的学识。

  若是中间有怎么着错误,还请权威能帮作者提议。

 

您必须知道到的Hook,钩子监听。 Hook是怎么着?
hook翻译之后是钩子的情趣,hook的用途重如若用来堵住新闻的,看到那里大家或许会迷茫…

Hook是什么?

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

Posted
on 2013-08-15

 
 
 hook翻译之后是钩子的意趣,hook的用处首要是用来阻止新闻的,看到此间我们只怕会盲目,What is a
hook?所以那时就只能普及一下操作系统的规律。

 
 
 hook翻译之后是钩子的意思,hook的用处主即便用来阻拦消息的,看到此间我们莫不会盲目,What is a
hook?所以那时候就不得不普及一下操作系统的原理。

茵蒂克丝

  • 怎样成立贰个窗口
    • 手动创制窗口的流程
    • 其实代码
  • 安装钩子 (Install
    hook)

    • 钩子简介
    • SetWindowsHookEx
      函数
  • 设置监听【键盘】音讯
  • 安装监听【鼠标】新闻

   
举个例子:要是你是一名玩耍热衷者,在玩游戏时,你要自由技能那么你就会对键盘鼠标进行操作,表面上您是一贯操作游戏,其实个中经过了多少个环节。

   
举个例证:就算你是一名玩耍热衷者,在玩游戏时,你要自由技能那么你就会对键盘鼠标举行操作,表面上您是一向操作游戏,其实在那之中经过了多少个环节。

何以创制二个窗口

除此以外七个再录的 Windows
SDK教程 里面有讲到急速创建窗口的章程,不过如此的话要分好几个文件,感觉有点混所以那里就用原来的艺术开创1个窗口。

那么,为何讲到
hook(钩子)的时候要去创制窗口呢?其实这么些标题说起来也不复杂,不难点说,按博主那样写不用写DLL也不用能源文件,实际上是把标题简化了某些。常常hook
是用来监听本身窗口上的键盘和鼠标输入的,监听全局的家常是安装有个别大局的热键(如QQ的
Ctrl+Alt+Z
调出QQ窗口),那么些周边的职能也都以要依托窗口才能存在。所以我们先来归纳说出手动建立3个窗口的流程。

                 
首先,你操作键盘鼠标,那么总括机底层键盘鼠标的驱动就会收下三个音信。

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

手动创造窗口的流程

  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
机制】,就就像于3个【音信过滤网】,尽管大家向操作系统申请并打响对有些窗口设置了三个【hook】钦命了【回调函数】,那么那几个【回调函数】也就一定于大家人为对那些窗口添加了3个【音讯过滤网】。此时当
windows
操作系统要对这么些窗口发送任何消息的时候(例如按键、鼠标点击等音信)操作系统会先调用大家在【消息过滤网】中装置的【回调函数】去接受、处理、过滤等等,当然即使您在【回调函数】中得到了数码却并未继续传递给窗口来说,就一定于阻挡了那一个音信。

打个简易的如若,假若你在系统全局安装了三个【键盘音信】的钩子,并且在其钦点的【回调函数】中从不把这么些键盘新闻持续传递给系统上的窗口,那么你的有所【键盘音讯】都被那么些【hook】也就大家挂在这几个【音讯过滤网】上的【回调函数】给拦住了,那也代表你的键盘会失灵。

做和好的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)

   
好!说了这么些,大家想想假设你写了多个hook,在旁人的微处理器上阻碍了这些消息,操作系统就不驾驭那个新闻,你能够把这些音信通过互联网发到你的电脑,那么些那台电脑的一坐一起你都清楚….(当然我教我们那一个不是目的在于您们做坏事,而是同过hook更透彻学习总计    机    和维护本身电脑),上面小编来同过二个总结的次序来让我们理解hook。

   
好!说了这个,我们想想借使你写了2个hook,在别人的微处理器上阻碍了那一个消息,操作系统就不知情这么些音讯,你能够把这一个音信通过互联网发到你的电脑,那一个那台总结机的举措你都清楚….(当然笔者教大家这一个不是期待您们做坏事,而是同过hook更透彻学习总结    机    和掩护本人电脑),下边作者来同过叁个归纳的程序来让我们精晓hook。

设置监听【键盘】新闻

PKBDLLHOOKSTRUCT 是 WH_KEYBOARD_LL
格局可行来选用新闻的结构体,大家可以到 WindUser.h 中多逛逛。

笔者们监听键盘的时候根本用的是该结构体的 vkCode(value code)和 scanCode
那四个字段。即键盘的【值码】和【扫描码】那么为啥判断三个按键要分成多少个部分吗,原因是因为世界上的键盘有不少种,差异国家、不一样厂商生产的键盘甚,至同多个键盘上【同样的键】分歧的地方按下都恐怕会有异样。vkCode
是广泛的相似都以公用的键盘值,而 scanCode
扫描码则是用来补助区分的一个三个参数,例就像是样是按下 ctrl 键,他们的
vkCode 是平等的然则 scanCode 却不比。

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
#include <windows.h>
 
HHOOK myhook;   // 保存当前钩子句柄
 
/****************************************************************
  WH_KEYBOARD hook procedure
  鍵盤钩子处理过程
 ****************************************************************/
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{  
    char text[50], data[20];    // 输出字符串
    const char *info = NULL;    // 类型字符指针
    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; // 获取按键消息
    HDC hdc;    // 画图设备句柄
 
    // 判断是否收到键盘消息
    if (nCode >= 0)
    {
        // 判断消息类型
        if      (wParam == WM_KEYDOWN)      info = "普通按鍵抬起";
        else if (wParam == WM_KEYUP)        info = "普通按鍵按下";
        else if (wParam == WM_SYSKEYDOWN)   info = "系統按鍵抬起";
        else if (wParam == WM_SYSKEYUP)     info = "系統按鍵按下";
 
        // 初始化数组
        ZeroMemory(text, sizeof(text));
        ZeroMemory(data, sizeof(data));
        // 拼装字符串
        wsprintf(text, "%s - 键盘码 [%04d], 扫描码 [%04d]  ", info, p->vkCode, p->scanCode);
        wsprintf(data, "按鍵目测为: %c  ", p->vkCode);
 
        // 此处调用 GDI 画图函数来将截取到的内容画在窗口上
        hdc = GetDC(画图的窗口句柄);       // 获取要画图的设备句柄
        TextOut(hdc, 10, 10, text, strlen(text));   // 在窗口上画文字
        TextOut(hdc, 10, 30, data, strlen(data));   // 参数分别是 目标设备, x坐标, y坐标, 字符串内容, 字符串长度
        ReleaseDC(画图的窗口句柄, hdc);        // 释放设备句柄
    }
 
    // 将消息继续往下传递
    return CallNextHookEx(myhook, nCode, wParam, lParam);
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    /* 其他代码 */
 
    // 设置键盘全局监听
    myhook = SetWindowsHookEx(
        WH_KEYBOARD_LL, // 监听类型【键盘消息】
        KeyboardProc,   // 处理函数
        hInstance,      // 当前实例句柄
        0               // 监听线程ID(NULL为全局监听)
    );
 
    // 判断是否成功
    if(myhook == NULL)
    {      
        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());
        MessageBox(hwnd, text, TEXT("错误"), MB_OK);
    }
 
    /* 其他代码 */
}

注:在那之中在出口按键的时候,直接用 %c 输出了 p->vkCode
部分,这么些实际上不是很纯粹。

顺手提一句,各位也不要用那么些意义去做什么坏事,比如去监听QQ窗口的键盘新闻然后偷到密码盗旁人号之类的, 博主已经试过了 那几个作者有带防护的,用户在输密码的时候,会有搅和的键盘音信也一起冒出来所以没那么不难能到到外人输的密码。至于写个程序去阻拦外人的键盘还有鼠标音信令人家的微处理器不可能用的境况,那些真的很简单形成,而且貌似杀毒软件都不可能防,只好本身在本人的电脑上留个后门,怎么写后门?后边的网络编制程序会说这么些。

键盘监听完整代码:

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <windows.h>
 
HWND hgWnd;
HHOOK myhook;
 
/****************************************************************
  WH_KEYBOARD hook procedure
  鍵盤钩子处理过程
 ****************************************************************/
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{  
    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
    const char *info = NULL;
    char text[50], data[20];
 
    PAINTSTRUCT ps;
    HDC hdc;
 
    if (nCode >= 0)
    {
        if      (wParam == WM_KEYDOWN)      info = "普通按鍵抬起";
        else if (wParam == WM_KEYUP)        info = "普通按鍵按下";
        else if (wParam == WM_SYSKEYDOWN)   info = "系統按鍵抬起";
        else if (wParam == WM_SYSKEYUP)     info = "系統按鍵按下";
 
        ZeroMemory(text, sizeof(text));
        ZeroMemory(data, sizeof(data));
        wsprintf(text, "%s - 键盘码 [%04d], 扫描码 [%04d]  ", info, p->vkCode, p->scanCode);
        wsprintf(data, "按鍵目測為: %c  ", p->vkCode);
 
        hdc = GetDC(hgWnd);        
        TextOut(hdc, 10, 10, text, strlen(text));
        TextOut(hdc, 10, 30, data, strlen(data));
        ReleaseDC(hgWnd,hdc);
    }
     
    return CallNextHookEx(myhook, nCode, wParam, lParam);
}
 
// 5. 窗口过程处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{  
    hgWnd = hwnd;
 
    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);
 
    // 设置键盘全局监听
    myhook = SetWindowsHookEx(
        WH_KEYBOARD_LL, // 监听类型【键盘】
        KeyboardProc,   // 处理函数
        hInstance,      // 当前实例句柄
        0               // 监听窗口句柄(NULL为全局监听)
    );
 
    if(myhook == NULL)
    {      
        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());
        MessageBox(hwnd, text, TEXT("错误"), MB_OK);
    }
 
 
    // 5. 消息循环
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}
1 int main()
2 {
3     MessageBox(NULL, L"Hello world", L"this",MB_OK);
4     system("pause");
5     return 0;
6 }
1 int main()
2 {
3     MessageBox(NULL, L"Hello world", L"this",MB_OK);
4     system("pause");
5     return 0;
6 }

运营截图

澳门金沙国际 3

 
那是一段简单的顺序,其意义是为了突显一个会话窗口。这几个对话窗口操作系统已经帮我们写好了,我们实在是在调用那段代码。好!大家想转手大家能不可能在调用这一个函数此前截断这么些调用,让程序调用自个儿的函数。(想想做插件是还是不是那几个原理)答案是自然的,我们能够截断这一个音信并让他调用本身的函数。上边咱们来代码达成一下。

 
这是一段简单的程序,其功用是为了显示七个对话窗口。那几个对话窗口操作系统已经帮大家写好了,大家实际上是在调用那段代码。好!大家想转手大家能否在调用这么些函数从前截断这么些调用,让程序调用自身的函数。(想想做插件是或不是这些规律)答案是自然的,大家能够截断那个消息并让他调用本身的函数。上边大家来代码实现一下。

安装监听【鼠标】音信

与键盘监听类似,各位直接看代码:

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <windows.h>
 
HWND hgWnd;
HHOOK myhook;
 
/****************************************************************
  WH_KEYBOARD hook procedure
  鍵盤钩子处理过程
 ****************************************************************/
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{  
    LPMSLLHOOKSTRUCT p = (LPMSLLHOOKSTRUCT)lParam;
    POINT   pt = p->pt;
    DWORD   mouseData = p->mouseData;
    const char *info = NULL;
    char text[60], pData[50], mData[50];
 
    PAINTSTRUCT ps;
    HDC hdc;
 
    if (nCode >= 0)
    {
        if   (wParam == WM_MOUSEMOVE)       info = "鼠标移动    ";
        else if(wParam == WM_LBUTTONDOWN)   info = "鼠标【左键】按下";
        else if(wParam == WM_LBUTTONUP)     info = "鼠标【左键】抬起";
        else if(wParam == WM_LBUTTONDBLCLK) info = "鼠标【左键】双击";
        else if(wParam == WM_RBUTTONDOWN)   info = "鼠标【右键】按下";
        else if(wParam == WM_RBUTTONUP)     info = "鼠标【右键】抬起";
        else if(wParam == WM_RBUTTONDBLCLK) info = "鼠标【右键】双击";
        else if(wParam == WM_MBUTTONDOWN)   info = "鼠标【滚轮】按下";
        else if(wParam == WM_MBUTTONUP)     info = "鼠标【滚轮】抬起";
        else if(wParam == WM_MBUTTONDBLCLK) info = "鼠标【滚轮】双击";
        else if(wParam == WM_MOUSEWHEEL)    info = "鼠标【滚轮】滚动";
 
        ZeroMemory(text, sizeof(text));
        ZeroMemory(pData, sizeof(pData));
        ZeroMemory(mData, sizeof(mData));
 
        wsprintf( text, "当前状态: %10s   ", info);
        wsprintf(pData, "0x%x - X: [%04d], Y: [%04d]  ", wParam, pt.x, pt.y);
        wsprintf(mData, "附带数据: %16u   ", mouseData);
 
        hdc = GetDC(hgWnd);        
        TextOut(hdc, 10, 10,  text, strlen(text));
        TextOut(hdc, 10, 30, pData, strlen(pData));
        TextOut(hdc, 10, 50, mData, strlen(mData));
        ReleaseDC(hgWnd,hdc);
    }
     
    return CallNextHookEx(myhook, nCode, wParam, lParam);
}
 
// 5. 窗口过程处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{  
    hgWnd = hwnd;
 
    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);
 
    // 设置鼠标全局监听
    myhook = SetWindowsHookEx(
        WH_MOUSE_LL,    // 监听类型【鼠标】
        MouseProc,  // 处理函数
        hInstance,      // 当前实例句柄
        0               // 监听窗口句柄(NULL为全局监听)
    );
 
    if(myhook == NULL)
    {      
        wsprintf(text, "键盘监听失败!error : %d n", GetLastError());
        MessageBox(hwnd, text, TEXT("错误"), MB_OK);
    }
 
 
    // 5. 消息循环
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

澳门金沙国际 4

 

 

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

   
 那是自笔者写的三个函数(注意:函数重回值和参数一定要和Message博克斯一样,那样接口才能对上,不然会报错),大家要让程序执行大家的函数,那么大家将要写二个钩子。

   
 那是本身写的1个函数(注意:函数再次来到值和参数一定要和MessageBox一样,那样接口才能对上,不然会报错),大家要让程序执行我们的函数,那么我们将要写3个钩子。

 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 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个钩子,上边作者放出一体化程序的代码

     小编早已写好了2个钩子,上边小编放出总体程序的代码

 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     }
 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注释掉运营。运转结果如下。

    首先大家把Hook注释掉运转。运营结果如下。

澳门金沙国际 5

澳门金沙国际 6

   
 如何加上hook,你会发觉一件令人开心的业务,并不曾弹出对话框。运维结果如下

   
 怎么样加上hook,你会意识一件令人欢喜的工作,并没有弹出对话框。运营结果如下

澳门金沙国际 7

澳门金沙国际 8

 

 

 
 通过那些事例相信大家对hook有了有的询问,今后我们肯能会有二个疑团,笔者能跳转,能或不能够重临吗,答案是能的。作者也给大家提供二个点思路ReadProcessMemory()用那个api来保存原来的段地址和内部存款和储蓄器中的代码,回去时在采纳WriteProcessMemory()再跳转一次,就能够会到原来调用的代码处了,这一个是还是不是很棒,大家能够回家自行试验,也得以巩固一下昨日所学的文化。

 
 通过那几个例子相信大家对hook有了部分询问,今后我们肯能会有贰个疑点,作者能跳转,能否回去吧,答案是能的。作者也给大家提供贰个点思路ReadProcessMemory()用那一个api来保存原来的段地址和内存中的代码,回去时在应用WriteProcessMemory()再跳转一遍,就能够会到原来调用的代码处了,这么些是或不是很棒,我们能够回家自行试验,也得以巩固一下明日所学的学问。

 

  假设中间有啥样错误,还请权威能帮小编建议。

 

相关文章