Windows系统通用回调

Windows系统通用回调 本文将针对Windows操作系统所提供系统回调操作做逐一分析,以了解每个回调所能达成什么样的功能及效果。比如部分回调只是用于通知,我们只能通过此回调来了解某一类型事件的发生,只能做审计,拦截动作需要通过其它途径实现;也有回调可以实现即时拦截,通过回调即可阻止恶意程序的攻击企图。 Windows系统在内核及应用层均有提供回调机制,下面分为两部分作介绍:

1 内核回调

内核回调机制 OS版本 功能描述 备注
PsSetCreateProcessNotifyRoutine WIN2K 只是进程创建及退出通知
PsSetCreateProcessNotifyRoutineEx VISTA SP1/SRV2008 可通过返回值阻止进程创建
PsSetCreateProcessNotifyRoutineEx2 WIN10 1703 可接收到WSL/PICO进程创建及退出通知;可阻止进程创建
PsSetCreateThreadNotifyRoutine (PsRemoveCreateThreadNotifyRoutine) WIN2K 线程创建及退出通知 创建时的context为创建者,可用以判断是不是远程线程
PsSetCreateThreadNotifyRoutineEx (PsRemoveCreateThreadNotifyRoutine) WIN10 线程创建及退出通知 创建时的context为新线程环境
PsSetLoadImageNotifyRoutine (PsRemoveLoadImageNotifyRoutine) WIN2K 模块加载通知:支持驱动及应用层DLL加载通知 无模块卸载通知
PsSetLoadImageNotifyRoutineEx (PsRemoveLoadImageNotifyRoutine) WIN10 1709 模块加载通知:支持驱动及应用层DLL加载通知 无模块卸载通知
IoRegisterBootDriverCallback (IoUnRegisterBootDriverCallback) WIN8 Boot-Start驱动加载通知,可拦截,但拦截的后果即BSOD 加载顺序问题;ELAM驱动最早加载,需要特殊签名
SeRegisterImageVerificationCallback (SeUnregisterImageVerificationCallback) WIN8.1 ? 驱动加载回调,可以验证驱动签名信息 函数未公开,目前Windows Defender会使用
ObRegisterCallbacks (ObUnRegisterCallbacks) VISTA SP1 SRV2008 针对进程及线程对象句柄的创建提供前置及后置回调,可修改句柄权限,如针对进程对象无VM映射权限。子进程继承句柄不会通知 WIN7系统可监控文件句柄的创建,需要修改未公开的系统结构(ObjectType->SupportsObjectCallbacks),WIN8后PG会监控。WIN10系统增加了桌面对象的监控支持
CmRegisterCallback (CmUnRegisterCallback) XP 注册表操作回调,可修改、转向或拦截原访问请求 XP/SRV2003/VISTA行为有差异
CmRegisterCallbackEx (CmUnRegisterCallback) VISTA 注册表操作回调,可修改、转向或拦截原访问请求
ExRegisterCallback
-- \Callback\SetSystemTime WIN2K 系统时钟修改回调
-- \Callback\PowerState WIN2K 电源状态改变回调(AC/DC,电源策略,待机或关机) 早于Power Manager的IRP_SET_POWER请求
-- \Callback\ProcessorAdd VISTA 动态增加新CPU事件通知
KeRegisterBoundCallback (KeDeregisterBoundCallback) WIN10 用以捕获应用层边界检测异常,可用于应用层HOOK
Standard Event Objects for VM : 所有 主要用于监控内存状态
-- \KernelObjects\HighMemoryCondition
-- \KernelObjects\LowMemoryCondition
-- \KernelObjects\HighPagedPoolCondition
-- \KernelObjects\LowPagedPoolCondition
-- \KernelObjects\HighNonPagedPoolCondition
-- \KernelObjects\LowNonPagedPoolCondition
-- \KernelObjects\LowCommitCondition
-- \KernelObjects\HighCommitCondition
-- \KernelObjects\MaximumCommitCondition
KeRegisterBugCheckCallback (KeDeregisterBugCheckCallback) WIN2K 系统出错准备蓝屏时的回调通知
KeRegisterBugCheckReasonCallback (KeDeregisterBugCheckReasonCallback) XP SP1 SRV2003 蓝屏后DUMP生成通知,可写入额外1-PAGE信息
FsRtlRegisterFileSystemFilterCallbacks XP 文件系统或过滤驱动回调,一般由I/o Manager,VM及CM发起
IoRegisterFsRegistrationChange (IoUnregisterFsRegistrationChange) 所有 文件系统注册事件通知回调 WIN2K: 已注册文件系统驱动不再通知;XP: 均会通知
IoRegisterFsRegistrationChangeEx (IoUnregisterFsRegistrationChange) WIN2K SP4 文件系统注册事件通知回调,忽略RAW设备 同IoRegisterFsRegistrationChange
IoRegisterFsRegistrationChangeMountAware (IoUnregisterFsRegistrationChange) WIN7 文件系统注册事件通知回调,忽略RAW设备 会额外处理与挂载/Mount的竞争问题
TmEnableCallbacks VISTA 文件事务操作回调
IoRegisterContainerNotification (IoUnregisterContainerNotification) WIN7 会话/Session改变通知,如新用户登录或登出,功能类似于用户层的WTSRegisterSessionNotification
KeRegisterProcessorChangeCallback (KeDeregisterProcessorChangeCallback) WIN2K 动态CPU添加事件回调 有Pre和Post处理
KeRegisterNmiCallback (KeDeregisterNmiCallback) SRV2003 发生不可屏蔽中断时的回调通知
IoRegisterShutdownNotification (IoUnregisterShutdownNotification) WIN2K IRP_MJ_SHUTDOWN请求回调
IoRegisterLastChanceShutdownNotification (IoUnregisterShutdownNotification) WIN2K IRP_MJ_SHUTDOWN请求回调 调用时机晚,在文件系统处理完毕之后
PoRegisterPowerSettingCallback (PoUnregisterPowerSettingCallback) VISTA 电源管理事件响应回调
IoRegisterPlugPlayNotification (IoUnregisterPlugPlayNotification[Ex]) WIN2K PNP事件回调(设备热插拔)
IoWMISetNotificationCallback XP WMI事件回调
DbgSetDebugPrintCallback 未公开 VISTA 捕获内核打印事件(DbgPrint)
IoRegisterPriorityCallback (IoUnregisterPriorityCallback) 未公开 WIN7 SP1 ? I/O 请求优先级调整
PoRegisterCoalescingCallback (PoUnregisterCoalescingCallback) 未公开 WIN8.1 CM和文件系统相关:在系统空闲的时候实施cache的聚合刷新
PsSetLegoNotifyRoutine 未公开 XP 类似TLS,可以实现线程终结时的回调通知

2 应用层回调

应用层回调 OS 功能 备注
LdrRegisterDllNotification (LdrUnregisterDllNotification) VISTA 可接收进程内DLL模块加载及卸载事件,不可拦截
ProcessInstrumentationCallback WIN7 可在程序每次Ring 0至3切换后收到通知,在系统服务调用结束时刻 需要进程注入后主动调用NtSetInformationProcess,需要SeDebugPrivilege等
RegisterServiceCtrlHandler(Ex) XP 在应用层服务中接收系统事件:设备热插拔、用户登录、电源管理等
RegisterDeviceNotification 所有 GUI程序获取硬件改变通知
RegNotifyChangeKeyValue WIN2K 监控注册表指定键的子键及值的改变
ReadDirectoryChange 所有 监控指定目录中的文件及子目录的变化
AddSecureMemoryCacheCallback (RemoveSecureMemoryCacheCallback) VISTA SP1 可监控Secure类型的共享内存的释放
LdrSetDllManifestProber 未公开 XP 可收到DLL模块加载事件,可用于拦截
LdrInitShimEngineDynamic 未公开 WIN7 可接收Shim Engine通知,可接管DLL加载等 调用时机有要求,需要R3 HOOK; 不同Windows版本如WIN7及8.1差别较大
RtlSetThreadPoolStartFunc 未公开 WIN2K 设置线程初始化及退出函数,kernel32内部使用

3 通用回调的限制

Windows系统虽然提供了回调接口,但因为性能等各种因素的原因还会限定回调的数量:

  • CmRegisterCallback限制为最多100个,无高度号设置,后注册的回调可能收不到请求
  • PsSetLoadImageNotifyRoutine限制为最多8个,64位系统共64个
  • PsSetCreateProcessNotifyRoutine限制为最多8个
  • PsSetCreateThreadNotifyRoutine限制为最多8个 不少驱动安装为了防止注册失败的情况选择了尽早启动并完成相关回调的注册,也有一些工具如PcHunter会通过DKOM方式进行动态扩展。 另外不同的OS版本的支持限制,在上表中也有说明,如Vista之后的Windows系统才开始支持注册表事务操作,这部分在使用中也要注意,Ob Callback也有类似的问题。

4 参考链接

  1. Magnesium Object Manager Sandbox, A More Effective Sandbox Method for Windows 7
  2. MSDN: Filtering Registry Calls
  3. Filter Manager Support for Minifilter Drivers
  4. MSDN: REG_NOTIFY_CLASS enumeration
  5. CodeMachine: Kernel Callback Functions
  6. OSR: Kernel Mode Extensions Driver
  7. WDK Samples: Registry Logging
  8. https://blog.csdn.net/whatday/article/details/52623878
  9. https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/handling-notifications