大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。
全局钩子注入
全局钩子介绍
hook,指利用api来提前拦截并处理windows消息的一种技术。如键盘钩子,许多木马都有这东西,监视你的键盘操作。
全局钩子是系统钩子的一种,当指定的一些消息被系统中任何应用程序所处理时,这个钩子就被调用
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。对每种类型的钩子由系统来维护一个钩子链,最近安装的钩子放在链的开始,而最先安装的钩子放在最后,也就是后加入的先获得控制权。要实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx
来安装这个钩子函数,这个函数的原型是HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId)
其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx
来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。
SetWindowsHookEx
设置钩子API
HHOOK WINAPI SetWindowsHookEx(
_In_ int idHook, // 设置钩子的类型.意思就是我要设置的钩子是什么钩子. 可以是监视窗口过程.可以是监视消息队列.
_In_ HOOKPROC lpfn, // 根据钩子类型.设置不同的回调函数.
_In_ HINSTANCE hMod, // 钩子设置的Dll实例句柄,就是DLL的句柄
_In_ DWORD dwThreadId // 设置钩子的线程ID. 如果为0 则设置为全局钩子.
);
// HHOOK 返回值. 是一个钩子过程句柄.
参数
idHook
要安装钩子的程序类型
lpfn
:
一个指向钩子程序的指针。如果dwThread参数为0或指定由不同进程创建线程标识符,则lpfn参数必须指向DLL中的钩子过程,否则,lpfn可以指向与前进程关联的代码中的钩子过程。
hMod
:
包含由lpfn参数指向的钩子过程的 DLL 句柄。所述HMOD参数必须设置为NULL,如果dwThreadId参数指定由当前进程,并且如果钩子程序是与当前过程相关联的所述代码中创建的线程。
dwThreadId
:
与钩子过程关联的线程的标识符。对于桌面应用程序,如果此参数为零,则挂钩过程与调用线程在同一桌面上运行的所有现有线程相关联。
返回值
如果函数成功,则返回值是钩子过程的句柄,否则返回值为NULL。
GetModuleHandle
获取模块句柄API
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName // 获取的实例句柄的文件名.可以是Dll可以使exe 如果为NULL 这是当前dll/exe的实例句柄
);
UnhookWindowsHookEx
取消设置钩子API
BOOL WINAPI UnhookWindowsHookEx(
_In_ HHOOK hhk //参数一是 SetWindowHookEx的返回值.也就是钩子过程句柄.
);
CallNextHookEx
继续调用钩子链中的钩子过程
LRESULT WINAPI CallNextHookEx(
_In_opt_ HHOOK hhk, //保存的钩子过程,也就是SetWindowsHookEx返回值.
_In_ int nCode, // 根据SetWindowsHookEx设置的钩子回调而产生的不同的nCode代码. 什么意思? 意思就是如果设置的钩子类型是鼠标消息.那么那个nCode就是鼠标消息.如果是键盘这是键盘
_In_ WPARAM wParam, // 同2参数一样.附加参数. 根据钩子回调类型.附加参数有不同的意义.比如如果是鼠标.那么这个有可能代表的就是鼠标的x位置.键盘就可能是键代码
_In_ LPARAM lParam /// 同3参数一样.附加参数.
);
代码案例1
#include <Windows.h>
#include<stdio.h>
HHOOK g_hHook;
LRESULT GetMsgProc(
int code,
WPARAM wParam,
LPARAM lParam)
{
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
int main()
{
HMODULE hDll;
hDll = ::LoadLibrary("hookdll.dll");
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, hDll, 0);
if (g_hHook == NULL) {
printf("Hook Failed!\n");
return -1;
}
else
{
printf("Hook Success!\n");
system("pause");
}
UnhookWindowsHookEx(g_hHook);
printf("UnHook");
}
DLL文件编写
#include "pch.h"
#include<Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(0, 0, "Success", 0);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
代码案例2
cpp代码
#include <Windows.h>
#include<stdio.h>
int main() {
typedef BOOL(*_SetGlobalHook)();
typedef BOOL(*_UnsetGlobalHook)();
HMODULE hmodoule;
hmodoule =::LoadLibrary("hookdll.dll");
_SetGlobalHook SetGlobalHook =(_SetGlobalHook)GetProcAddress(hmodoule, "SetGlobalHook");
int a = SetGlobalHook();
if (a) {
printf("HOOK");
}
else
{
printf("HOOK ERRER!!!");
}
_UnsetGlobalHook UnsetGlobalHook = (_UnsetGlobalHook)GetProcAddress(hmodoule, "UnsetGlobalHook");
UnsetGlobalHook();
printf("UNHOOK");
system("pause");
return 0;
}
dll代码
#include "pch.h"
#include<Windows.h>
//共享内存
#pragma data_seg("mydata") //而不是放在shared中,从而导致多个进程之间的共享行为失败
#pragma data_seg()
#pragma comment(linker,"/SECTION:mydata,RWS")
HHOOK g_hHook = NULL; //必须赋初值,否则微软编译器会把没有初始化的数据放到普通的未初始化数据段中
HMODULE g_hModule; //钩子句柄
extern "C" _declspec(dllexport)
//卸载钩子
BOOL UnsetGlobalHook()
{
if (g_hHook)
{
UnhookWindowsHookEx(g_hHook);
}
return TRUE;
}
//钩子的回调函数
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
MessageBox(NULL, "你被监视了", "提示", MB_ICONWARNING | MB_OKCANCEL);
//CallNextHookEx函数表示将当前钩子传递给钩子链中的下一个钩子
//第一个参数当前钩子的句柄。如果直接返回0,则表示中断钩子传递
//对钩子进行拦截
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
extern "C" _declspec(dllexport)
//设置全局钩子
BOOL SetGlobalHook()
{
//SetWindowsHookEx,第一个参数表示钩子的类型,WH_GETMESSAGE表示安装消息队列的消息钩子
//可以监视发送到消息队列的消息。第二个参数表示钩子回调函数,第三个参数表示包含钩子回调
//函数的DLL模块句柄,如果要设置全局钩子,则该参数必须指定DLL模块句柄,第四个参数表示与
//钩子关联的线程ID,0表示为全局钩子,关联所有线程。
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hModule, 0);
if (g_hHook == NULL)
{
return FALSE;
}
return TRUE;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
g_hModule = hModule;
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119850.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...