热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

进程注入之全局钩子注入

全局钩子注入Windows中大部分的应用程序都是基于消息机制的,它们都有一个消息过程函数比如SetWindowsHookEx函数,根据不同的消息完成不同的功能。消息钩子是windo

全局钩子注入

Windows中大部分的应用程序都是基于消息机制的,它们都有一个消息过程函数比如SetWindowsHookEx函数

,根据不同的消息完成不同的功能。

消息钩子是windows提供的一种消息过滤和预处理机制,可以用来截获和监视系统中的消息。

按照钩子作用范围不同,又可以分为局部钩子和全局钩子。局部钩子是针对某个线程的,而全局钩子是作用于整个系统的基于消息的应用。全局钩子需要使用DLL文件,在DLL文件中实现相应的钩子函数。


核心函数介绍

HHOOK WINAPI SetWindowsHookExW(
_In_ int idHook,
_In_ HOOKPROC lpfn,
_In_opt_ HINSTANCE hmod,
_In_ DWORD dwThreadId);

1.idHook 要安装的钩子(HOOK)的类型,它决定了HOOKPROC被调用的时机,可选参数如下。







































































WH_MSGFILTER = -1线程级,截获用户与控件交互的消息
WH_JOURNALRECORD = 0系统级,记录所有消息队列送出的输入消息
WH_JOURNALPLAYBACK = 1系统级,回放由WH_JOURNALRECORD记录的消息
WH_KEYBOARD = 2系统级或线程级,截获键盘消息
WH_GETMESSAGE = 3系统级或线程级,截获从消息队列送出的消息
WH_CALLWNDPROC = 4系统级或线程级,截获发送到目标窗口的消息
WH_CBT = 5系统级或线程级,截获系统基本消息 例如:窗口的创建,激活,关闭,最大/最小化,移动等
WH_SYSMSGFILTER = 6系统级,截获系统范围内用户与控件交互的消息
WH_MOUSE = 7系统级或线程级,截获鼠标消息
WH_HARDWARE = 8系统级或线程级,截获非标准硬件(非鼠标,键盘)的消息
WH_DEBUG = 9系统级或线程级,在其它钩子调用前调用,用于调试钩子
WH_SHELL = 10系统级或线程级,截获发给外壳应用程序的消息
WH_FOREGROUNDIDLE = 11系统级或线程级,在程序前台线程空闲时调用
WH_CALLWNDPROCRET = 12系统级或线程级,截获目标窗口处理完的消息 在SendMessage被调用后发生
WH_KEYBOARD_LL = 13系统级,截获全局键盘消息
WH_MOUSE_LL = 14系统级,截获全局鼠标消息

2.lpfn指向钩子回调函数的指针。如果最后一个参数dwThreadId为0或者是其它进程创建的线程标识符,则lpfn参数必须指向DLL中的钩子回调函数,即HOOKPROC函数必须在DLL中实现。否则,lpfn 可以指向与当前进程相关联的代码中的钩子过程。

3.hmod包含由lpfn参数指向的钩子回调函数的DLL句柄。如果dwThreadId参数指定由当前进程创建线程,并且钩子回调函数位于当前进程关联的代码中,则hmod参数必须设置为NULL

4.dwThreadId与钩子程序关联的线程标识符(指定要HOOK的线程 ID)。如果此参数为0,则钩子过程与系统中所有线程相关联,即全局消息钩子


实现原理

通过SetWindowsHookExW函数安装一个用于过滤特定类型消息的钩子函数(钩子WH_GETMESSAGE可以立即被触发,而某些类型的钩子需要在处理指定类型的消息时才能被触发),当其它进程中产生了我们过滤的消息,就会调用HOOKPROC,如果发现目标DLL(HOOKPROC实现的DLL)尚未加载,就会使用KeUserModeCallback函数回调User32.dll__ClientLoadLibrary() 函数,由User32.dll把这个DLL加载到目标进程中(低级键盘和鼠标钩子的加载有所不同),从而实现DLL注入其它进程的目的。


代码及其实现过程

首先新建一个dll项目

image-20220224221831169

pch.h中声明这几个我们定义的函数都是裸函数,由我们自己平衡堆栈

extern "C" _declspec(dllexport) int SetHook();
extern "C" _declspec(dllexport) LRESULT GetMsgProc(int code, WPARAM wParam, LPARAM lParam);
extern "C" _declspec(dllexport) BOOL UnsetHook();

image-20220224222046446

pch.cpp里面写入三个函数并创建共享内存(进程通信的方法有很多,比如自定义消息、管道、dll共享节、共享内存等等,这里就用共享内存来实现进程通信)

#include "pch.h"
#include
#include
extern HMODULE g_hDllModule;
// 共享内存
#pragma data_seg("mydata")
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:mydata,RWS")
//钩子回调函数
LRESULT GetMsgProc(int code, WPARAM wParam, LPARAM lParam) {
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
// 设置钩子
BOOL SetHook() {
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllModule, 0);
if (NULL == g_hHook) {
return FALSE;
}
return TRUE;
}
//这里第二个参数是回调函数,那么我们还需要写一个回调函数的实现,这里就需要用到CallNextHookEx这个api,主要是第一个参数,这里传入钩子的句柄的话,就会把当前钩子传递给下一个钩子,若参数传入0则对钩子进行拦截
// 卸载钩子
BOOL UnsetHook() {
if (g_hHook) {
UnhookWindowsHookEx(g_hHook);//UnhookWindowsHookEx这个api是来卸载钩子的
}
return TRUE;
}

image-20220224222240772

dllmain.cpp设置DLL_PROCESS_ATTACH,然后编译生成Dll1.dll

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
HMODULE g_hDllModule = NULL;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
g_hDllModule = hModule;
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

image-20220224222424391

之后再创建一个控制台项目

image-20220224222618491

LoadLibrabryW加载dll,生成inject2.cpp文件

// inject2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
int main()
{
typedef BOOL(*typedef_SetGlobalHook)();
typedef BOOL(*typedef_UnsetGlobalHook)();
HMODULE hDll = NULL;
typedef_SetGlobalHook SetGlobalHook = NULL;
typedef_UnsetGlobalHook UnsetGlobalHook = NULL;
BOOL bRet = FALSE;
do
{
hDll = ::LoadLibraryW(TEXT("D:\\vs2017project\\Dll1\\Debug\\Dll1.dll"));
if (NULL == hDll)
{
printf("LoadLibrary Error[%d]\n", ::GetLastError());
break;
}
SetGlobalHook = (typedef_SetGlobalHook)::GetProcAddress(hDll, "SetHook");
if (NULL == SetGlobalHook)
{
printf("GetProcAddress Error[%d]\n", ::GetLastError());
break;
}
bRet = SetGlobalHook();
if (bRet)
{
printf("SetGlobalHook OK.\n");
}
else
{
printf("SetGlobalHook ERROR.\n");
}
system("pause");
UnsetGlobalHook = (typedef_UnsetGlobalHook)::GetProcAddress(hDll, "UnsetHook");
if (NULL == UnsetGlobalHook)
{
printf("GetProcAddress Error[%d]\n", ::GetLastError());
break;
}
UnsetGlobalHook();
printf("UnsetGlobalHook OK.\n");
} while (FALSE);
system("pause");
return 0;
}

执行测试

编译inject2.cpp生成inject2.exe并运行

image-20220224223314059

打开进程工具,搜索Dll1.dll是否加载,发现在大多数进程中都得到了加载

image-20220224223458548

尝试卸载钩子

image-20220224223607471

进程中的Dll1.dll已经被卸载

image-20220224223746445



推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Python中sys模块的功能及用法详解
    本文详细介绍了Python中sys模块的功能及用法,包括对解释器参数和功能的访问、命令行参数列表、字节顺序指示符、编译模块名称等。同时还介绍了sys模块中的新功能和call_tracing函数的用法。推荐学习《Python教程》以深入了解。 ... [详细]
  • 由于同源策略的限制,满足同源的脚本才可以获取资源。虽然这样有助于保障网络安全,但另一方面也限制了资源的使用。那么如何实现跨域呢,以下是实现跨域的一些方法。 ... [详细]
  • 前一天学习了视图按键事件的监听。首先新建了一个自定义的视图,在自定义视图中,重新编了其构造函数和onDraw()方法。之后将该视图用于应用程序,最后添加该视图的按键监听器,在监听器中对KeyEvent ... [详细]
  • java多线程获取线程返回结果
    我们在使用java多线程编写相关业务代码时,往往有这样一种情况,某个线程依赖于其他线程执行结果。也就是说,我们需要在一个线程中获取另一个线程的信息。可以分为两种情况,一种是轮询,一 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了利用AndroidCamera2的照相机api实现实时的图像采集与预览相关的知识,希望对你有一定的参考价值。&n ... [详细]
  • Iamworkingonaprojectwhichrequiresopentokandcallkitfornotifyingusers.However,theappli ... [详细]
  • 调用百度ocr的API,python简易版本
    https:www.jianshu.compe10dc43c38d01.注册百度云注册账号https:cloud.baidu.com?fromconsole管理应用https:co ... [详细]
  • HBase干货 | 如何优雅的通过Key与Value分离降低写放大难题?
    本文将为大家介绍为什么这样能够有效的降低写放大,然后聊聊几个keyvalue分离系统的结构,包括两篇影响比较广泛的学术论文,以及HBase在keyvalue ... [详细]
  • 我是Linux编程的新手,我正在尝试使用Tesseract和OpenCV在Ubuntu12.10上创建一个OCR应用程序.到目前为止,我已经在linux上设置了tesseract和 ... [详细]
author-avatar
北大青鸟西安
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有