@author: dlive

@date: 2016/12/19

0x01 SetWindowsHookEx()

  1. HHOOK SetWindowsHookEx(
  2. int idHook, //hook type
  3. HOOKPROC lpfn, //hook procedure(回调函数)
  4. HINSTANCE hMod, //hook procedure所属的DLL句柄
  5. DWORD dwThreadId //想要挂钩的线程ID
  6. );

使用SetWindowsHookEx() API可以轻松实现消息钩子。用于将制定的“钩子过程”注册到钩链中。无论在DLL内部还是外部都可以调用。(下面的例子是在DLL内部调用的)

hook procedure(钩子过程) 是由操作系统调用的回调函数,安装消息钩子时,钩子过程需要存在于某个DLL内部,且该DLL的instance handle(示例句柄)即是hMod

若dwThreadID参数被设置为0,则安装的钩子为全局钩子,它会影响到运行中的所有进程

0x02 HookMain.exe

  1. #include "stdio.h"
  2. #include "conio.h"
  3. #include "windows.h"
  4. #define DEF_DLL_NAME "KeyHook.dll"
  5. #define DEF_HOOKSTART "HookStart"
  6. #define DEF_HOOKSTOP "HookStop"
  7. typedef void (*PFN_HOOKSTART)();
  8. typedef void (*PFN_HOOKSTOP)();
  9. void main()
  10. {
  11. HMODULE hDll = NULL;
  12. PFN_HOOKSTART HookStart = NULL;
  13. PFN_HOOKSTOP HookStop = NULL;
  14. char ch = 0;
  15. //加载DLL
  16. hDll = LoadLibraryA(DEF_DLL_NAME);
  17. if( hDll == NULL )
  18. {
  19. printf("LoadLibrary(%s) failed!!! [%d]", DEF_DLL_NAME, GetLastError());
  20. return;
  21. }
  22. //从DLL中获取函数地址
  23. HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
  24. HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
  25. //执行HookStart函数
  26. HookStart();
  27. printf("press 'q' to quit!\n");
  28. while( _getch() != 'q' ) ;
  29. HookStop();
  30. //卸载DLL
  31. FreeLibrary(hDll);
  32. }

0x03 KeyHook.dll

  1. #include "stdio.h"
  2. #include "windows.h"
  3. #define DEF_PROCESS_NAME "notepad.exe"
  4. HINSTANCE g_hInstance = NULL;
  5. HHOOK g_hHook = NULL;
  6. HWND g_hWnd = NULL;
  7. //DLL中的Main函数
  8. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
  9. {
  10. switch( dwReason )
  11. {
  12. //DLL加载的时候
  13. case DLL_PROCESS_ATTACH:
  14. //钩子过程(KeyboardProc)所属DLL句柄,即本DLL
  15. g_hInstance = hinstDLL;
  16. break;
  17. //DLL卸载的时候
  18. case DLL_PROCESS_DETACH:
  19. break;
  20. }
  21. return TRUE;
  22. }
  23. //钩子过程
  24. //MSDN对KeyboardProc的定义:https://msdn.microsoft.com/en-us/library/ms644984(v=vs.85).aspx
  25. //nCode :HC_ACTION(0), HC_NOREMOVE(3)
  26. //wParam : 虚拟键值(virtual key code),对于键盘而言a和A具有相同的虚拟键值
  27. //lParam 额外信息
  28. LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
  29. {
  30. char szPath[MAX_PATH] = {0,};
  31. char *p = NULL;
  32. if( nCode >= 0 )
  33. {
  34. // bit 31 : 0 => press, 1 => release
  35. if( !(lParam & 0x80000000) )
  36. {
  37. //获得应用程序的目录路径
  38. GetModuleFileNameA(NULL, szPath, MAX_PATH);
  39. p = strrchr(szPath, '\\');
  40. //对比当前进行是否为notepad.exe
  41. if( !_stricmp(p + 1, DEF_PROCESS_NAME) )
  42. //终止KeyboardProc函数,意味着截获并删除信息
  43. return 1;
  44. }
  45. }
  46. //Passes the hook information to the next hook procedure in the current hook chain.
  47. return CallNextHookEx(g_hHook, nCode, wParam, lParam);
  48. }
  49. #ifdef __cplusplus
  50. //关于为何使用ifdef __cplusplus
  51. //参考:http://blog.csdn.net/miyunhong/article/details/4589541
  52. extern "C" {
  53. #endif
  54. //DLL的导出函数
  55. __declspec(dllexport) void HookStart()
  56. {
  57. //设置消息钩子
  58. //WH_KEYBOARD 钩子类型
  59. //参考:https://msdn.microsoft.com/en-us/library/ms644959(v=vs.85).aspx#wh_keyboardhook
  60. //KeyboardProc 钩子过程(回调函数)
  61. //g_hInstance 钩子过程所在DLL的句柄
  62. //0 想要挂钩的线程ID,若为0则为全局Hook
  63. g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
  64. }
  65. __declspec(dllexport) void HookStop()
  66. {
  67. if( g_hHook )
  68. {
  69. UnhookWindowsHookEx(g_hHook);
  70. g_hHook = NULL;
  71. }
  72. }
  73. #ifdef __cplusplus
  74. }
  75. #endif

0x04 调试KeyLogger.dll

首先运行notepad.exe

然后再OD的”调试选择“中选择Event->Break on new moudle(DLL)

开启该选项后,每当有新的DLL装入被调试进程时就会停止调试

0x05 参考资料

  1. MSDN Hook

    https://msdn.microsoft.com/en-us/library/ms644959(v=vs.85).aspx

Windows消息钩取的更多相关文章

  1. DLL注入之windows消息钩取

    DLL注入之windows消息钩取 0x00 通过Windows消息的钩取 通过Windows消息钩取可以使用SetWindowsHookEx.该函数的原型如下: SetWindowsHookEx( ...

  2. 《逆向工程核心原理》Windows消息钩取

    DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...

  3. Reverse Core 第三部分 - 21章 - Windows消息钩取

    @author: dlive @date: 2016/12/19 0x01 SetWindowsHookEx() HHOOK SetWindowsHookEx( int idHook, //hook ...

  4. 逆向学习-Windows消息钩取

    钩子 Hook,就是钩子.偷看或截取信息时所用的手段或工具. 消息钩子 常规Windows流: 1.发生键盘输入事件时,WM_KEYDOWN消息被添加到[OS message queue]. 2.OS ...

  5. SetWindowsHookEx 消息钩取进程卡死

    <逆向工程核心原理> windows消息钩取部分的例子在win10下卡死,失败.通过搜索发现,要保证钩取的进程与注入的dll要保持cpu平台相同 SetWindowsHookEx可用于将d ...

  6. windows消息钩子注册底层机制浅析

    标 题: [原创]消息钩子注册浅析 作 者: RootSuLe 时 间: 2011-06-18,23:10:34 链 接: http://bbs.pediy.com/showthread.php?t= ...

  7. x64 下记事本WriteFile() API钩取

    <逆向工程核心原理>第30章 记事本WriteFile() API钩取 原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中.在原代码基础上进行修改: 1 ...

  8. Windows消息机制详解

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

  9. Windows消息机制知识点总结

    1.windows消息类型 以下四种,前三种是系统消息,范围在[0x0000, 0x03ff],第四种是用户自定义消息. 1.1 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...

随机推荐

  1. 一道JS面试题所引发的"血案",透过现象寻本质,再从本质看现象

    觉得本人写的不算很烂的话,可以登录关注一下我的GitHub博客,新手写东西写的不好之处,还望见谅,毕竟水平有限,写东西只为交流提高,一起学习,还望大神多加指点,指出纰漏,和提出宝贵的意见,博客会坚持写 ...

  2. DevOps - CI/CD - Jenkins

    Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建.测试和部署等功能.本文以 CentOS7 环境为例,总结了 Jenkin ...

  3. HTTP协议原理

    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP).通过使用网页浏览器.网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80).我们称这个客户 ...

  4. 学习python第四天 列表

    模块的导入是使用 import sys#导入模块sysprint(sys.path)#打印环境变量,可能存在的目录print(sys.argv)#打印脚本的名字,相对路径 import os os.s ...

  5. web开发框架Flask学习二

    jinja2模板规范 在当前项目中创建一个文件为templates的文件夹,将其设置为模板文件夹,新建的html为模板页面, 在视图函数中使用render_template(".html的文 ...

  6. Python9-MySQL-Homework-day43

    表结构 SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure f ...

  7. Linux程序编辑器

    重点回顾:Linux底下的配置文件多为文本文件,故使用vim即可进行设定编辑: vim可视为程序编辑器,可用以编辑shell script,配置文件等,避免打错字 vi为所有unix like的操作系 ...

  8. datagrid的修改和删除功能的实现

    1.修改 双击,进入一行的编辑状态的功能的实现 2.删除 3.扩展easyui的datagrid,添加动态增加或删除Editor的方法 (1)背景要求: 对于某一列,比如密码,动态增加时候,是可以编辑 ...

  9. PostgreSQL 数组类型

    PostgreSQL 支持表的字段使用定长或可变长度的一维或多维数组,数组的类型可以是任何数据库内建的类型.用户自定义的类型.枚举类型, 以及组合类型.但目前还不支持 domain 类型. 数组类型的 ...

  10. Leetcode 583.两个字符串的删除操作

    两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例 1: 输入: "se ...