当前位置: 首页 > 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.jsqmd.com/news/976259/

相关文章:

  • OpenCore Legacy Patcher完整指南:让老旧Mac焕发新生的终极解决方案
  • Matrox Genesis 63039620241采集卡
  • agent cli跳过确认
  • AntiDupl.NET:告别重复图片困扰,智能清理你的数字相册
  • MuleSoft企业级AI编排:LLM与业务系统深度融合实践
  • OpenAI Codex 扩到全工作流:AI 编程不再只是写代码
  • CairoSVG错误处理与调试:解决常见SVG转换问题的完整指南
  • 海口首奢侈品包包回收市场真实评测:六家平台深度对比,选添价收奢侈品回收最稳妥 - 薛定谔的梨花猫
  • 轻松绕过Windows 11限制:Rufus启动盘制作全攻略
  • 碧蓝航线智能挂机助手:3步配置解放双手的终极自动化脚本
  • Scrcpy Mask开发指南:如何为项目贡献代码和扩展功能的完整教程
  • 2026年 镇江公考/考公/公务员/省考/事业编/事业单位培训机构推荐榜单:本地高分口碑与实战技巧深度解析 - 企业推荐官【官方】
  • Windows系统优化神器:5分钟掌握Win11Debloat的终极瘦身方案
  • Adobe Downloader:解决macOS用户获取Adobe软件的三大痛点
  • 磨毛机远程监控运维管理系统方案
  • C#写的JT/T 808车载终端仿真工具,带地图可视化和全指令模拟
  • Windows终极优化指南:WinUtil一键解决系统臃肿和软件管理难题
  • 2026年山西医院商用净水设备选择参考推荐,山西净水工程/净水设备/直饮净水系统,商用净水设备源头厂家哪家靠谱 - 品牌推荐师
  • 小米平板5变身Windows工作站:完整ARM64驱动包安装指南
  • 如何快速掌握LosslessCut无损视频剪辑:新手也能轻松上手的终极指南
  • 从协议打通到RAG工程化:北泰智能全栈自研智慧档案系统架构深度拆解
  • 3步掌握Buzz字幕智能优化:告别碎片化,实现专业级字幕控制
  • Pose-Search:如何用AI人体姿态识别技术3分钟找到任何动作图片?
  • 2026东莞会计培训怎么选?择校全攻略,东莞本土会计培训机构深度解析 - 左岸花开Acorn
  • 2026海口奢侈品包包回收实测测评|本地正规回收平台添价收包包回收深度对比攻略 - 薛定谔的梨花猫
  • PHP内存管理与垃圾回收机制
  • 终极i茅台自动预约系统:告别繁琐手动操作,实现智能预约新体验
  • 企业级智能自动化平台:Campus-imaotai茅台预约系统架构解析与工程实践
  • 山西医院商用净水设备怎么挑?2026年6月实用推荐,家用直饮净水/全屋净水方案/净水维修服务,商用净水设备直销厂家有哪些 - 品牌推荐师
  • 鸣潮自动化助手:如何让游戏自己玩自己,解放你的双手与时间