0. TL; DR
本文分享一个有意思的项目 pi-defender[1](Process Injection Defender)。其在内核层阻断所有可能的进程注入,并通过签名和白名单来很大程度减少误杀。
搜索发现该技巧早有人提出,本文仅借此项目进行分析。
1. 处理流程
该项目的核心是通过 ObRegisterCallbacks[2] 注册 pre-callback 来拦截所有的 OB_OPERATION_HANDLE_CREATE
和 OB_OPERATION_HANDLE_DUPLICATE
操作,并在满足拦截条件时去掉进程句柄的 PROCESS_VM_WRITE
和 PROCESS_VM_OPERATION
权限。
ObRegisterCallbacks
是注册内核回调的函数,其回调可拦截进程句柄 / 线程句柄
的创建 / 克隆
,回调类型可以是操作发生前和发生后。注册回调的相关代码在 K_ObCallback.cpp[3]:
ObOperationRegistrations[0].ObjectType = PsProcessType;
ObOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_CREATE;
ObOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_DUPLICATE;
ObOperationRegistrations[0].PreOperation = _PreObCallback;
ObOperationRegistrations[0].PostOperation = NULL;
ObRegistration.Version = OB_FLT_REGISTRATION_VERSION;
ObRegistration.OperationRegistrationCount = NumberOfOperations;
ObRegistration.Altitude = szAltitude;
ObRegistration.RegistrationContext = NULL;
ObRegistration.OperationRegistration = ObOperationRegistrations;
ObRegisterCallbacks(&ObRegistration, &globalDriverData.pObCallback);
README 中的总流程图:
流程中几个关键点的文字描述是:
1.只拦截 ring3 的进程句柄操作。2.只拦截获取其它进程句柄操作。3.只拦截权限含有 PROCESS_VM_WRITE | PROCESS_VM_OPERATION
的句柄操作。4.不拦截白名单进程,白名单通过注册表配置。5.不拦截有可信签名的文件。
2. 拦截效果和绕过
ObRegisterCallbacks
的回调拦截 ring3 所有的进程句柄创建(包括 OpenProcess
、CreateProcess
和 DuplicateHandle
),然后去除 PROCESS_VM_WRITE | PROCESS_VM_OPERATION
,无这两个权限的句柄无法分配内存、写内存。
而所有进程注入手法中,无论是注入 Shellcode、镂空 PE、RDI,都绕不开写数据到目标进程内存空间。
不考虑内核层操作,从正面绕过很难,作者只想到一些通过侧面利用校验流程绕过的方法。
1.添加注册表白名单,pi-defender 中没有对注册表的保护。2.通过白加黑上线,利用合法签名程序。
References
[1]
pi-defender: https://github.com/PI-Defender/pi-defender[2]
ObRegisterCallbacks: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-obregistercallbacks[3]
K_ObCallback.cpp: https://github.com/PI-Defender/pi-defender/blob/main/Sources/PI-Defender/K_ObCallback.cpp
原文始发于微信公众号(0x4d5a):借助内核回调阻断 Windows 进程注入