Windows对象句柄回调 (Object Handle Callbacks)
对象句柄回调直接介入Windows对象管理器的工作流程,它允许我们在其它进程对进程、线程、桌面对象进行操作的前后执行自定义的回调函数。
关键函数
对象句柄回调的关键函数是ObRegisterCallbacks:
NTSTATUSObRegisterCallbacks([in]POB_CALLBACK_REGISTRATION CallbackRegistration,// 指向 OB_CALLBACK_REGISTRATION 结构体[out]PVOID*RegistrationHandle// 返回的注册句柄,用于卸载);OB_CALLBACK_REGISTRATION结构体
这是注册信息的“根”结构,包含了所有注册的总体信息。
typedefstruct_OB_CALLBACK_REGISTRATION{USHORT Version;// 必须设置为 OB_FLT_REGISTRATION_VERSIONUSHORT OperationRegistrationCount;// 下面 OperationRegistration 数组的元素个数UNICODE_STRING Altitude;// 驱动程序的“高度”,用于确定回调的优先级PVOID RegistrationContext;// 驱动定义的上下文,会传递给回调函数POB_OPERATION_REGISTRATION OperationRegistration;// 指向一个结构体数组}OB_CALLBACK_REGISTRATION,*POB_CALLBACK_REGISTRATION;Altitude 字段:这是一个关键的Unicode字符串,它决定了当多个驱动同时注册回调时,你的回调函数被调用的顺序。数值越高,优先级也越高,其 PreOperation 回调会更早被调用,PostOperation 回调会更晚被调用。
OB_OPERATION_REGISTRATION结构体
这个结构体用于指定你要监控的具体对象类型、操作类型以及对应的回调函数。
typedefstruct_OB_OPERATION_REGISTRATION{POBJECT_TYPE*ObjectType;// 对象类型: PsProcessType 或 PsThreadType 等OB_OPERATION Operations;// 操作类型: OB_OPERATION_HANDLE_CREATE 或 DUPLICATEPOB_PRE_OPERATION_CALLBACK PreOperation;// 操作前回调函数指针POB_POST_OPERATION_CALLBACK PostOperation;// 操作后回调函数指针}OB_OPERATION_REGISTRATION,*POB_OPERATION_REGISTRATION;- ObjectType:指定要监控的对象类型,通常是 PsProcessType(进程)或 PsThreadType(线程)。
- Operations:指定要拦截的操作,可以是 OB_OPERATION_HANDLE_CREATE(创建句柄)或 OB_OPERATION_HANDLE_DUPLICATE(复制句柄)。
示例代码
下面这份代码用于防止notepad.exe进程被关闭:
/* * 这份代码用于测试ObRegisterCallbacks内核回调函数 * * 该份代码的作用是避免notepad.exe被终止 */#include<wdm.h>#include<ntstrsafe.h>EXTERN_C NTKERNELAPI UCHAR*PsGetProcessImageFileName(IN PEPROCESS Process);// 保存ObRegisterCallbacks返回的注册句柄,卸载时需要PVOID g_registrationHandle=nullptr;// 该函数在每一次进程句柄创建或者复制之前被调用OB_PREOP_CALLBACK_STATUSObPreCallback(PVOID RegistrationContext,POB_PRE_OPERATION_INFORMATION OperationInformation);voidDriverUnload(PDRIVER_OBJECT pDrvObj){// 注册成功,需要卸载if(g_registrationHandle!=nullptr){ObUnRegisterCallbacks(g_registrationHandle);g_registrationHandle=nullptr;DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[ObCallback] Callback unregistered.\n");}DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Uninstall driver\n");}EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDrvObj,PUNICODE_STRING pRegPath){pDrvObj->DriverUnload=DriverUnload;// 定义操作注册结构,告诉系统我们要监控什么对象和什么操作OB_OPERATION_REGISTRATION opReg={0};opReg.ObjectType=PsProcessType;opReg.Operations=OB_OPERATION_HANDLE_CREATE;opReg.PreOperation=ObPreCallback;opReg.PostOperation=nullptr;// 定义回调注册结构OB_CALLBACK_REGISTRATION cbReg={0};cbReg.Version=OB_FLT_REGISTRATION_VERSION;cbReg.OperationRegistrationCount=1;RtlInitUnicodeString(&cbReg.Altitude,L"600000");cbReg.RegistrationContext=nullptr;cbReg.OperationRegistration=&opReg;// 注册回调NTSTATUS status=ObRegisterCallbacks(&cbReg,&g_registrationHandle);if(!NT_SUCCESS(status)){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"ObRegisterCallbacks failed with status 0x%X\n",status);returnstatus;}DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"ObRegisterCallbacks successfully\n");returnSTATUS_SUCCESS;}OB_PREOP_CALLBACK_STATUSObPreCallback(PVOID RegistrationContext,POB_PRE_OPERATION_INFORMATION OperationInformation){// 只对进程对象感兴趣,虽然注册的时候指定了类型,这里是为了确保安全if(OperationInformation->ObjectType!=*PsProcessType){returnOB_PREOP_SUCCESS;}PEPROCESS targetProcess=(PEPROCESS)OperationInformation->Object;if(!targetProcess){returnOB_PREOP_SUCCESS;}PCHAR processName=(PCHAR)PsGetProcessImageFileName(targetProcess);if(!processName){returnOB_PREOP_SUCCESS;}// 检查是否为notepad.exeif(_stricmp(processName,"notepad.exe")!=0){returnOB_PREOP_SUCCESS;}// 检查操作类型if(OperationInformation->Operation==OB_OPERATION_HANDLE_CREATE||OperationInformation->Operation==OB_OPERATION_HANDLE_DUPLICATE){// 检查请求的访问掩码中包含的权限是否包含终止权限ACCESS_MASK desireAccess=OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;// 只检查创建句柄,大部分终止操作是通过OpenProcess产生if(OperationInformation->Operation==OB_OPERATION_HANDLE_CREATE){ACCESS_MASK desire=OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;if(desire&0x0001){// 拒绝该操作,返回访问被拒绝DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[ObCallback] Blocked attempt to open notepad.exe \ with TERMINATE access.\n");OperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;// 清空权限returnOB_PREOP_SUCCESS;}}}returnOB_PREOP_SUCCESS;}为了避免运行驱动时出现权限不足的报错,我们需要在项目属性中的链接器选项页面中,添加/INTEGRITYCHECK: