当前位置: 首页 > news >正文

Windows内核事件通知机制

Windows内核事件通知机制

Windows内核中提供了一组接口,让我们可以针对某一事件注册通知例程,当这个事件发生的时候,我们注册的通知例程就会执行。

进程创建/退出通知

// 注册进程创建通知回调NTSTATUSPsSetCreateProcessNotifyRoutine(_In_ PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,// 通知例程指针_In_ BOOLEAN Remove// 为false则注册例程,为true则移除通知例程);// 回调函数原型typedefVOID(*PCREATE_PROCESS_NOTIFY_ROUTINE)(_In_ HANDLE ParentId,// 父进程ID_In_ HANDLE ProcessId,// 被创建的进程的ID_In_ BOOLEAN Create// 这个参数为TRUE表示当前是创建进程的通知,为FALSE表示当前是进程结束的通知);// 扩展版本(Windows Vista+)NTSTATUSPsSetCreateProcessNotifyRoutineEx(_In_ PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine,_In_ BOOLEAN Remove);

通过调用PsSetCreateProcessNotifyRoutine为进程创建和退出注册NotifyRoutine回调例程。

**回调例程是在目标进程的第一个线程运行前被调用的。**根据微软文档:

“For a new process, the CreateProcessNotifyEx routine is called after the initial thread is created, but before the thread begins running.”

所以我们可以在回调中阻止进程的创建。

PsSetCreateProcessNotifyRoutineEx

该函数的第一个参数是类型为PCREATE_PROCESS_NOTIFY_ROUTINE_EX回调函数指针,定义如下:

/// PCREATE_PROCESS_NOTIFY_ROUTINE_EX/// <summary>/// 进程创建的通知回调/// </summary>/// <param name="pEprocess">进程对象指针</param>/// <param name="hProcessId">进程ID</param>/// <param name="pCreateInfo">进程相关信息</param>voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);

下面看看示例代码:

简单示例代码

这份代码来自谭文老师的《Windows内核编程》,回调例程中只是简单地输出进程的信息。

/* * 进程创建或者结束 * PsSetCreateProcessNotifyRoutine: * param1: 回调函数指针 * param2: 创建还是注销回调 * * 回调是哪条线程执行的: * 创建:哪条线程创建的进程,就在哪条线程的上下文中执行回调 * 销毁:哪条线程是进程最后一个退出的,就在哪条线程中执行回调 */#include<ntddk.h>#include<windef.h>voidDriverUnload(PDRIVER_OBJECT pDriverObj);/// <summary>/// 进程创建的通知回调/// </summary>/// <param name="pEprocess">进程对象指针</param>/// <param name="hProcessId">进程ID</param>/// <param name="pCreateInfo">进程相关信息</param>voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);staticboolsg_bSuccReg=false;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);NTSTATUS status=STATUS_SUCCESS;do{pDriverObj->DriverUnload=DriverUnload;// 创建通知回调status=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,false);if(!NT_SUCCESS(status)){sg_bSuccReg=false;break;}sg_bSuccReg=true;}while(false);returnstatus;}voidDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);if(sg_bSuccReg){// 传递true表明注销回调PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,true);sg_bSuccReg=false;}}voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo){HANDLE hCurrentThreadID=PsGetCurrentThreadId();if(pCreateInfo==nullptr)// 进程结束为nullptr,进程创建时为非nullptr{DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[Destroy] ThreadID: 0x%X, ProcessID: 0x%X\n",(DWORD)hCurrentThreadID,(DWORD)hProcessId);return;}// 进程创建// HANDLE hParentProcessID = pCreateInfo->CreatingThreadId.UniqueProcess;// HANDLE hParentThreadID = pCreateInfo->CreatingThreadId.UniqueThread;DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[Create] ThreadID: 0x%X, ProcessID: 0x%X, ProcessName: %wZ\n",(DWORD)hCurrentThreadID,(DWORD)hProcessId,pCreateInfo->ImageFileName);return;}

通过回调例程阻止进程创建

要阻止进程创建,我们可以把回调例程中CreateInfo参数中的CreationStatus设置为STATUS_ACCESS_DENIED,并返回,这样就阻止进程的创建了。下面列举了可以使用的错误状态码:

  • STATUS_ACCESS_DENIED- 拒绝访问
  • STATUS_UNSUCCESSFUL- 操作不成功
  • STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY- 策略禁用且不弹窗

#include<ntddk.h>#include<windef.h>// 这个函数貌似没有文档化。该函数的作用是获取EPROCESS中ImageFileNameEXTERN_C UCHAR*PsGetProcessImageFileName(PEPROCESS Process);voidDriverUnload(PDRIVER_OBJECT pDriverObj);voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);staticboolsg_bSuccReg=false;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);NTSTATUS status=STATUS_SUCCESS;do{pDriverObj->DriverUnload=DriverUnload;// 创建通知回调status=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,false);if(!NT_SUCCESS(status)){sg_bSuccReg=false;break;}sg_bSuccReg=true;}while(false);returnstatus;}voidDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);if(sg_bSuccReg){// 传递true表明注销回调PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,true);sg_bSuccReg=false;}}voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo){HANDLE hCurrentThreadID=PsGetCurrentThreadId();if(pCreateInfo==nullptr)// 进程结束为nullptr,进程创建时为非nullptr{DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[Destroy] ThreadID: 0x%X, ProcessID: 0x%X\n",(DWORD)hCurrentThreadID,(DWORD)hProcessId);return;}// 进程创建,我们阻止notepad运行DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[Create] ThreadID: 0x%X, ProcessID: 0x%X, ProcessName: %wZ\n",(DWORD)hCurrentThreadID,(DWORD)hProcessId,pCreateInfo->ImageFileName);// 我们要获取的是EPROCESS中的ImageFileName// pCreateInfo->ImageFileName是完整的路径PUCHAR processName=PsGetProcessImageFileName(pEprocess);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"ImageFileName: %s\n",processName);if(processName!=nullptr&&_stricmp((PCHAR)processName,"notepad.exe")==0){// 通过设置这个标志,阻止notepad.exe运行pCreateInfo->CreationStatus=STATUS_ACCESS_DENIED;}return;}

线程创建/退出通知

// 注册线程创建通知回调NTSTATUSPsSetCreateThreadNotifyRoutine(_In_ PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine);// 回调函数原型typedefVOID(*PCREATE_THREAD_NOTIFY_ROUTINE)(_In_ HANDLE ProcessId,_In_ HANDLE ThreadId,_In_ BOOLEAN Create);

回调例程是在线程运行前被调用的。

模块加载通知

// 注册模块加载通知回调NTSTATUSPsSetLoadImageNotifyRoutine(_In_ PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);// 回调函数原型typedefVOID(*PLOAD_IMAGE_NOTIFY_ROUTINE)(_In_opt_ PUNICODE_STRING FullImageName,_In_ HANDLE ProcessId,_In_ PIMAGE_INFO ImageInfo);// 注销回调NTSTATUSPsRemoveLoadImageNotifyRoutine([in]PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);

这里的回调例程是在模块被加载完成后执行的。

示例代码

#include<ntddk.h>#include<windef.h>VOIDDriverUnload(PDRIVER_OBJECT pDriverObj);VOIDLoadImageNotifyRoutine(PUNICODE_STRING fullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo);staticboolsg_bSuccReg=false;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){NTSTATUS status=STATUS_SUCCESS;do{pDriverObj->DriverUnload=DriverUnload;status=PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine);if(!NT_SUCCESS(status)){break;}sg_bSuccReg=true;}while(false);returnstatus;}VOIDDriverUnload(PDRIVER_OBJECT pDriverObj){if(sg_bSuccReg){PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine);sg_bSuccReg=false;}return;}// 这是单向通知,没有卸载事件通知回调VOIDLoadImageNotifyRoutine(PUNICODE_STRING fullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo){if(!fullImageName||!ImageInfo){return;}if(ImageInfo->ExtendedInfoPresent){PIMAGE_INFO_EX pInfo=CONTAINING_RECORD(ImageInfo,IMAGE_INFO_EX,ImageInfo);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"ModLoad Name: %wZ, ProcessID: 0x%X, FileObj: 0x%X, ImageBase: 0x%X",fullImageName,(DWORD)ProcessId,pInfo->FileObject,pInfo->ImageInfo.ImageBase);}return;}

注册表操作通知

// 注册注册表操作通知回调NTSTATUSCmRegisterCallback(_In_ PEX_CALLBACK_FUNCTION Function,_In_opt_ PVOID Context,_Out_ PLARGE_INTEGER Cookie);// 扩展版本NTSTATUSCmRegisterCallbackEx(_In_ PEX_CALLBACK_FUNCTION Function,_In_ PCUNICODE_STRING Altitude,_In_ PVOID Driver,_In_opt_ PVOID Context,_Out_ PLARGE_INTEGER Cookie,_Reserved_ PVOID Reserved);// 回调函数原型NTSTATUSRegistryCallback(_In_opt_ PVOID CallbackContext,_In_opt_ PVOID Argument1,// REG_NOTIFY_CLASS_In_opt_ PVOID Argument2// 操作信息结构体);
http://www.zskr.cn/news/1487979.html

相关文章:

  • 海口首奢侈品包包回收市场真实评测:六家平台深度对比,选添价收奢侈品回收最稳妥 - 薛定谔的梨花猫
  • 轻松绕过Windows 11限制:Rufus启动盘制作全攻略
  • 磨毛机远程监控运维管理系统方案
  • Adobe Downloader:解决macOS用户获取Adobe软件的三大痛点
  • 2026年山西医院商用净水设备选择参考推荐,山西净水工程/净水设备/直饮净水系统,商用净水设备源头厂家哪家靠谱 - 品牌推荐师
  • 从协议打通到RAG工程化:北泰智能全栈自研智慧档案系统架构深度拆解
  • 企业级智能自动化平台:Campus-imaotai茅台预约系统架构解析与工程实践
  • 终极i茅台自动预约系统:告别繁琐手动操作,实现智能预约新体验
  • Pose-Search:如何用AI人体姿态识别技术3分钟找到任何动作图片?
  • 如何快速获取智慧教育平台电子课本:三步解锁教材数字化管理秘诀
  • 污水处理设备监控与用电监测物联网系统方案
  • 基于MC68HC908MR32的三相电机驱动与数字PFC集成方案详解
  • 如何在10分钟内启动Jetson-Nano-Ubuntu-20-image:从下载到开机的快速入门
  • 百达翡丽出手多比价!哈尔滨实时行情,正规门店计价透明 - 讯息早知道
  • Kirikiri游戏资源处理终极指南:快速免费的解密与打包方案
  • 重庆名表回收综合实力排名 2026:六大平台实测,添价收稳居榜首 - 薛定谔的梨花猫
  • 2026年6月山西医院商用净水设备推荐,靠谱之选,山西净水工程/全屋净水系统/净水器,商用净水设备公司哪家靠谱 - 品牌推荐师
  • 如何为FF14国际服注入中文界面?开源汉化工具完全解析
  • Czkawka完全指南:彻底解决磁盘空间不足的终极方案
  • 高速SDRAM布局实战:从信号完整性原理到MPC106时钟补偿设计
  • VRM4U终极指南:5个步骤在UE5中完美导入VRM角色模型
  • go2rtc深度解析:从协议翻译器到边缘计算视频流中枢的技术实践
  • 源代码论文分享|线上教学平台项目资料,适合毕设/课设参考!
  • 如何构建私有照片管理系统:Lychee自托管部署全攻略
  • 2026可以文生PPT以及生图片的ai推荐:全场景选型指南 - 资讯速览
  • Joplin快捷键终极指南:200+效率操作完全解析
  • 如何在3分钟内免费将Figma界面完全汉化?FigmaCN完整中文翻译指南
  • 终极指南:如何用BiliDownload快速获取无水印B站视频
  • 2026重庆月嫂培训学校怎么选?资深从业者实地体验复盘 - 奔跑123
  • 息肉分割刷点秘籍:深入拆解Polyp-PVT中的三个关键模块(CFM/CIM/SAM)