钩子(HOOK)
英文Hook一词,翻成中文是“钩子”、“鱼钩”的意思,泛指钓取所需东西而使用的一切工 具。“钩子”这一基本含义延伸发展为“偷看或截取信息时所用的手段或工具”。下面举例向各位 进一步说明“钩子”这一概念。
消息钩取
Windows操作系统向用户提供GUI (Graphic User Interface,图形用户界面),它以事件驱动 (Event Driven)方式工作。在操作系统中借助键盘、鼠标,选择菜单、按钮,以及移动鼠标、改 变窗口大小与位置等都是事件(Event )o发生这样的事件时,OS会把事先定义好的消息发送给相 应的应用程序,应用程序分析收到的信息后执行相应动。也就是说,敲击键盘时,消息会从OS移动到应用程序。所谓的“消息钩子
通过Windows消息的钩取
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKpROC lpfn, // hook procedure
HINSTANCE hMod, //hook procedure所属的DLL句柄
DWORD dwThreadId //需要挂钩的线程ID,为0时表示为全局钩子(Global Hook)
);
hook proceduce是由操作系统调用的回调函数;安装消息钩子时,钩子过程需要存在于某个DLL内部,且该DLL的示例句柄即为hMod。
使用SetWindowsHookEx()设置好钩子后,在某个进程中生成指定消息时,OS就会将相关的DLL文件强制注入(injection)相应进程,然后调用注册的钩子程序。
我们通过一个HookMain.exe实现对将要注入的dll的控制。
//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)();
int main()
{
HMODULE hDll=NULL;
PFN_HOOKSTART HookStart=NULL;
PFN_HOOKSTOP HookStop=NULL;
char ch=0;
//加载KeyHook.dll
hDll=LoadLibraryA(DEF_DLL_NAME);
//获取导出函数地址
HookStart=(PFN_HOOKSTART)GetProcAddress(hDll,DEF_HOOKSTART);
HookStop=(PFN_HOOKSTART)GetProcAddress(hDll,DEF_HOOKSTOP);
//开始钩取
HookStart();
//等待直到用户输入“q”
printf("press 'q' to quit!\n");
while(_getch()!='q');
//终止钩取
HookStop();
//卸载KeyHook.dll
FreeLibrary(hDll);
return 0;
}
#define DEF_DLL_NAME "D:\\攻防对抗\\Dll2\\Debug\\Dll2.dll"?
dll的路径要替换成自己的路径,填写自己的,并且使用转义字符。
?dll代码,建立动态库
#include "main.h"
#include <winnt.h>
#include <windef.h>
// a sample exported function
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hInstance=NULL;
HHOOK g_hHook=NULL;
HWND g_hWnd=NULL;
// a sample exported function
//LRESULT是一个数据类型,指的是从窗口程序或者回调函数返回的32位值
//lParam wParam 是宏定义,一般在消息函数中带着两个类型的参数,通常用来存储窗口消息的参数。wParam用来存储小段消息,如标志。lParam 通常用于存储消息所需的对象。
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
char szPath[MAX_PATH]={0,};
char *p=NULL;
if (nCode>=0)
{
//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;
}
}
//若非notepad.exe,则调用CallNextHookEx()函数,将消息传递给应用程序(或下一个“钩子”)。
return CallNextHookEx(g_hHook,nCode,wParam,lParam);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
g_hInstance=hinstDLL;
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void HookStart()
{
//钩子类型、回调函数地址、实例句柄、线程ID
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
?
打开笔记本
调试,启动DLL和EXE(一定是先调试运行DLL,再调试运行EXE)
会弹出窗口
先向记事本输入,会发现键盘被锁住了,不管输入什么,都不会有输出
但是向浏览器或是WSP输入,都是没有问题的
在窗口里输入"q"回车就能退出
记事本就可以写东西啦?
|