时间:2025-05-10 09:49
人气:
作者:admin
Windows系统建立在事件驱动机制上,整个系统通过消息传递实现的。在Windows系统里,消息Hook就是一个Windows消息的拦截机制,可以拦截单个进程的消息(线程钩子),也可以拦截所有进程的消息(系统钩子),也可以对拦截的消息进行自定义的处理:
- 如果对于同一事件(如鼠标消息)既安装了线程Hook又安装了系统Hook,那么系统会自动先调用线程Hook,然后调用系统Hook(类似栈)。
- 对于同一事件消息可安装多个Hook处理过程,这些Hook处理过程形成了Hook链,后加入的有优先控制权。
在Windows中,利用SetWindowsHookEx函数创建钩子(Hooks)可以实现DLL注入,本实验使用消息Hook实现dll注入,实现类似插桩的效果。
实验环境:Win xp sp3、vc6.0


添加一个代码文件KeyHook.cpp

#include "stdio.h"
#include "windows.h"
#define DEF_PROCESS_NAME "notepad.exe" //定义hook进程名称
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;
}
//Hook函数(自定义的键盘消息处理函数)
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{//这里对第二个参数lParam进行了处理
char szPath[MAX_PATH] = {0,};
char *p = NULL;
if( nCode >= 0 ){
// lParam 第31位bit: 0 => key press, 1 => key release
if( !(lParam & 0x80000000) ) { //当按键被释放时
GetModuleFileNameA(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
//比较当前进程名称,若为notepad.exe,则消息不会继续传递
if( !_stricmp(p + 1, DEF_PROCESS_NAME) )
return 1; //丢弃该Keyboard消息
}
}
//若不为notepad.exe,调用CallNextHookEx()函数将消息传递给下一个“钩子”或应用程序
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
#ifdef __cplusplus //这里定义了两个导出函数HookStart()、HookStop(),允许外部调用
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
得到项目文件夹下的KeyHook.dll文件

编写DLL注入功能的可执行文件
新建一个VC6的控制台程序,添加源文件HookMain.cpp如下:
#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;
hDll = LoadLibraryA(DEF_DLL_NAME); // 加载KeyHook.dll (这里为相对路径,dll与exe要位于同一路径下)
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);
HookStart(); // 开始Hook
// 等待直到用户输入'q'
printf("press 'q' to quit!\n");
while( _getch() != 'q' ) ;
HookStop(); // 结束Hook
FreeLibrary(hDll); // 卸载KeyHook.dll
}
将HookMain.exe和KeyHook.dll放在相同目录下,运行HookMain.exe安装键盘消息Hook后,将实现notepad.exe进程的键盘消息拦截,使之无法显示在记事本中。直到输入“q”才可停止键盘Hook。
结果: