第一课 Windows消息的HOOK

您所在的位置:网站首页 dll编写线程钩子 第一课 Windows消息的HOOK

第一课 Windows消息的HOOK

2023-04-14 13:15| 来源: 网络整理| 查看: 265

本文是我学习《逆向工程核心原理》一书dll注入部分的学习总结,如有理解不到位或错误的地方欢迎大家以评论的方式完善指正

 

很多朋友一谈到Hook就觉得很神秘,其实Hook很好理解

那么如何打开spy++呢?

如下图所示

Spy++ (SPYXX.EXE) 是一个基于 Win32 的实用工具,它提供系统的进程、线程、窗口和窗口消息的图形视图。使用 Spy++ 可以执行下列操作: 显示系统对象(包括进程、线程和窗口)之间关系的图形树。 搜索指定的窗口、线程、进程或消息。 查看选定的窗口、线程、进程或消息的属性。

下图是打开后Spy++的界面

我们在winuser.h中看一下这个函数的定义

我们在微软的支持库里看一下这个函数的解释

如果英文的看不懂,就看下文的中文解释

 

HOOKPROClpfn不太好理解,单独说下,它的意思是钩子过程

 

如果还看不懂就看下图的详细解释

 

做一个练习,用键盘hook技术拦截notepad.exe进程的键盘消息,使之无法显示在记事本中

首先看一下HookMain.exe的源码(关键代码处我已经做好了中文注释)

#include "stdio.h" #include "conio.h" #include "windows.h"#define DEF_DLL_NAME "KeyHook.dll" #define DEF_HOOKSTART "HookStart" #define DEF_HOOKSTOP "HookStop"typedef void (*PFN_HOOKSTART)(); typedef void (*PFN_HOOKSTOP)();void main() {HMODULE hDll = NULL;PFN_HOOKSTART HookStart = NULL;PFN_HOOKSTOP HookStop = NULL;char ch = 0;// 加载KeyHook.dll hDll = LoadLibraryA(DEF_DLL_NAME);if( hDll == NULL ){printf("LoadLibrary(%s) failed!!! [%d]", DEF_DLL_NAME, GetLastError());return;}//获取导出函数地址HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);//开始hookHookStart();//用户输入‘q’停止hookprintf("press 'q' to quit!\n");while( _getch() != 'q' ) ;// 停止hookHookStop();//卸载 KeyHook.dllFreeLibrary(hDll); }

 

接下来看KeyHook.dll的源码

#include "stdio.h" #include "windows.h"#define DEF_PROCESS_NAME "notepad.exe"HINSTANCE g_hInstance = NULL; HHOOK g_hHook = NULL; HWND g_hWnd = NULL;BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) {switch( dwReason ){case DLL_PROCESS_ATTACH:g_hInstance = hinstDLL;break;case DLL_PROCESS_DETACH:break; }return TRUE; }LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {char szPath[MAX_PATH] = {0,};char *p = NULL;if( nCode >= 0 ){// bit 31 : 0 => press, 1 => releaseif( !(lParam & 0x80000000) )//释放键盘按键时{GetModuleFileNameA(NULL, szPath, MAX_PATH);p = strrchr(szPath, '\\');// 比较当前进程名称,若为notepad.exe,则消息不会传递给应用程序(或者下一个钩子)if( !_stricmp(p + 1, DEF_PROCESS_NAME) )return 1;}}// 如果不是notepad.exe,则调用CallNextHookEx函数,将消息传递给应用程序return CallNextHookEx(g_hHook, nCode, wParam, lParam); }#ifdef __cplusplus extern "C" { #endif__declspec(dllexport) void HookStart(){g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);}__declspec(dllexport) void HookStop(){if( g_hHook ){UnhookWindowsHookEx(g_hHook);g_hHook = NULL;}} #ifdef __cplusplus } #endif

 

 

 

 

 

我们再通过图来更深的了解一下HookMain.exe和keyhook.dll的关系

 

 

接下来开始运行调试我们写好的HookMain.exe

首先dll和注入器要在一个文件夹里(windows调用dll时会优先从同目录下寻找dll,所以不用放在system32文件夹里)

用OD打开HookMain.exe

上图显示的是 HookMain . exe 的 EP 代码,它是典型的 VC + +启动函数,其中最受关注的是开始进行键盘钩取的部分。 查找核心代码有几种方法可以帮助我们找到关注的核心代码: 入口逐行跟踪。 入口检索相关 API 。 入口检索相关字符串。 第一种方法是程序无法正常运行或难以预测时使用的下策,此处略去不谈。这样就剩下后面 2 种方法(检索 API 或字符串)了。由于已经运行过 HookMain . exe 程序,我们知道了该程序的功能(键盘钩取)与输出的字符串,所以下面要使用检索字符串( “ Press ' q ' to quit ! " )的方法。引用该字符串代码的前后就是我们关注的代码。在 OllyDbg 的代码窗口中,选择鼠标右键菜单中的 search for :一 All referenced text strings 项 双击进去,到达main函数

出现如下代码

执行完dll中的键盘hook函数后,键盘钩子就已经安装好了

用Process Explorer查看我们装好的钩子

然后我们运行到40104D处,让控制台输出字符串

执行40104D处的代码,程序跑起来了

不管按什么键盘按键,记事本什么都不显示,因为我们发出的键盘消息被拦截,它现在什么都收不到(可怜的记事本~~~~~~)

 

 

 

检索注入keyhook.dll的所有进程(查找——查找句柄或DLL)

输入要查找的dll,可以看到我们所有进程都被注入了keyhook.dll

因为我们安装的是全局钩子(前文讲SetWindowsHookEx参数时已经说明白了,不懂回去看)

源码中也可以看到为什么我们设置的全局钩子但只对notepad.exe有效了

接下来调试Notepad.exe进程内的KeyHook.dll

 

我使用学破解论坛的2.0OD

我们在段首下CC断点

然后在nopad.exe中随便输入一个字符

程序会断下

看堆栈可以看到充当回调函数的是user32.dll中的函数,user32.dll也就是参数HOOKPROCl pfn的实际过程

 

 

总结一下上述操作的顺序

好了,历经6个小时,终于写完了这一课,大家一定要自己亲手操作来学习,切不可走马观花,下一课会讲DLL注入,比这一课难很多,如果这节课没有理解,DLL注入的3种方法更不可能理解了。



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3