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 参考链接
- Magnesium Object Manager Sandbox, A More Effective Sandbox Method for Windows 7
- MSDN: Filtering Registry Calls
- Filter Manager Support for Minifilter Drivers
- MSDN: REG_NOTIFY_CLASS enumeration
- CodeMachine: Kernel Callback Functions
- OSR: Kernel Mode Extensions Driver
- WDK Samples: Registry Logging
- https://blog.csdn.net/whatday/article/details/52623878
- https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/handling-notifications