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 VistaNTSTATUSPsSetCreateProcessNotifyRoutineEx(_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 namepEprocess进程对象指针/param/// param namehProcessId进程ID/param/// param namepCreateInfo进程相关信息/paramvoidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);下面看看示例代码简单示例代码这份代码来自谭文老师的《Windows内核编程》回调例程中只是简单地输出进程的信息。/* * 进程创建或者结束 * PsSetCreateProcessNotifyRoutine: * param1: 回调函数指针 * param2: 创建还是注销回调 * * 回调是哪条线程执行的 * 创建哪条线程创建的进程就在哪条线程的上下文中执行回调 * 销毁哪条线程是进程最后一个退出的就在哪条线程中执行回调 */#includentddk.h#includewindef.hvoidDriverUnload(PDRIVER_OBJECT pDriverObj);/// summary/// 进程创建的通知回调/// /summary/// param namepEprocess进程对象指针/param/// param namehProcessId进程ID/param/// param namepCreateInfo进程相关信息/paramvoidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);staticboolsg_bSuccRegfalse;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);NTSTATUS statusSTATUS_SUCCESS;do{pDriverObj-DriverUnloadDriverUnload;// 创建通知回调statusPsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,false);if(!NT_SUCCESS(status)){sg_bSuccRegfalse;break;}sg_bSuccRegtrue;}while(false);returnstatus;}voidDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);if(sg_bSuccReg){// 传递true表明注销回调PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,true);sg_bSuccRegfalse;}}voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo){HANDLE hCurrentThreadIDPsGetCurrentThreadId();if(pCreateInfonullptr)// 进程结束为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- 策略禁用且不弹窗#includentddk.h#includewindef.h// 这个函数貌似没有文档化。该函数的作用是获取EPROCESS中ImageFileNameEXTERN_C UCHAR*PsGetProcessImageFileName(PEPROCESS Process);voidDriverUnload(PDRIVER_OBJECT pDriverObj);voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo);staticboolsg_bSuccRegfalse;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);NTSTATUS statusSTATUS_SUCCESS;do{pDriverObj-DriverUnloadDriverUnload;// 创建通知回调statusPsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,false);if(!NT_SUCCESS(status)){sg_bSuccRegfalse;break;}sg_bSuccRegtrue;}while(false);returnstatus;}voidDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);if(sg_bSuccReg){// 传递true表明注销回调PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,true);sg_bSuccRegfalse;}}voidCreateProcessNotifyEx(PEPROCESS pEprocess,HANDLE hProcessId,PPS_CREATE_NOTIFY_INFO pCreateInfo){HANDLE hCurrentThreadIDPsGetCurrentThreadId();if(pCreateInfonullptr)// 进程结束为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 processNamePsGetProcessImageFileName(pEprocess);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,ImageFileName: %s\n,processName);if(processName!nullptr_stricmp((PCHAR)processName,notepad.exe)0){// 通过设置这个标志阻止notepad.exe运行pCreateInfo-CreationStatusSTATUS_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);这里的回调例程是在模块被加载完成后执行的。示例代码#includentddk.h#includewindef.hVOIDDriverUnload(PDRIVER_OBJECT pDriverObj);VOIDLoadImageNotifyRoutine(PUNICODE_STRING fullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo);staticboolsg_bSuccRegfalse;EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){NTSTATUS statusSTATUS_SUCCESS;do{pDriverObj-DriverUnloadDriverUnload;statusPsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine);if(!NT_SUCCESS(status)){break;}sg_bSuccRegtrue;}while(false);returnstatus;}VOIDDriverUnload(PDRIVER_OBJECT pDriverObj){if(sg_bSuccReg){PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine);sg_bSuccRegfalse;}return;}// 这是单向通知没有卸载事件通知回调VOIDLoadImageNotifyRoutine(PUNICODE_STRING fullImageName,HANDLE ProcessId,PIMAGE_INFO ImageInfo){if(!fullImageName||!ImageInfo){return;}if(ImageInfo-ExtendedInfoPresent){PIMAGE_INFO_EX pInfoCONTAINING_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// 操作信息结构体);