Windows对象句柄回调 (Object Handle Callbacks)

Windows对象句柄回调 (Object Handle Callbacks)

对象句柄回调直接介入Windows对象管理器的工作流程,它允许我们在其它进程对进程、线程、桌面对象进行操作的前后执行自定义的回调函数。

关键函数

对象句柄回调的关键函数是ObRegisterCallbacks:

cpp 复制代码
NTSTATUS ObRegisterCallbacks(
  [in]  POB_CALLBACK_REGISTRATION CallbackRegistration, // 指向 OB_CALLBACK_REGISTRATION 结构体
  [out] PVOID                    *RegistrationHandle    // 返回的注册句柄,用于卸载
);

OB_CALLBACK_REGISTRATION结构体

这是注册信息的"根"结构,包含了所有注册的总体信息。

cpp 复制代码
typedef struct _OB_CALLBACK_REGISTRATION {
    USHORT Version;                     // 必须设置为 OB_FLT_REGISTRATION_VERSION
    USHORT OperationRegistrationCount;  // 下面 OperationRegistration 数组的元素个数
    UNICODE_STRING Altitude;            // 驱动程序的"高度",用于确定回调的优先级
    PVOID RegistrationContext;          // 驱动定义的上下文,会传递给回调函数
    POB_OPERATION_REGISTRATION OperationRegistration; // 指向一个结构体数组
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;

Altitude 字段:这是一个关键的Unicode字符串,它决定了当多个驱动同时注册回调时,你的回调函数被调用的顺序。数值越高,优先级也越高,其 PreOperation 回调会更早被调用,PostOperation 回调会更晚被调用。

OB_OPERATION_REGISTRATION结构体

这个结构体用于指定你要监控的具体对象类型、操作类型以及对应的回调函数。

cpp 复制代码
typedef struct _OB_OPERATION_REGISTRATION {
    POBJECT_TYPE *ObjectType;           // 对象类型: PsProcessType 或 PsThreadType 等
    OB_OPERATION Operations;            // 操作类型: OB_OPERATION_HANDLE_CREATE 或 DUPLICATE
    POB_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进程被关闭:

cpp 复制代码
/*
* 这份代码用于测试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_STATUS ObPreCallback(
	PVOID RegistrationContext,
	POB_PRE_OPERATION_INFORMATION OperationInformation
);

void DriverUnload(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 NTSTATUS DriverEntry(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);

		return status;
	}
	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
		"ObRegisterCallbacks successfully\n");

	return STATUS_SUCCESS;
}

OB_PREOP_CALLBACK_STATUS ObPreCallback(
	PVOID RegistrationContext,
	POB_PRE_OPERATION_INFORMATION OperationInformation
)
{
	// 只对进程对象感兴趣,虽然注册的时候指定了类型,这里是为了确保安全
	if (OperationInformation->ObjectType != *PsProcessType)
	{
		return OB_PREOP_SUCCESS;
	}

	PEPROCESS targetProcess = (PEPROCESS)OperationInformation->Object;
	if (!targetProcess)
	{
		return OB_PREOP_SUCCESS;
	}

	PCHAR processName = (PCHAR)PsGetProcessImageFileName(targetProcess);
	if (!processName)
	{
		return OB_PREOP_SUCCESS;
	}

	// 检查是否为notepad.exe
	if (_stricmp(processName, "notepad.exe") != 0)
	{
		return OB_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; // 清空权限

				return OB_PREOP_SUCCESS;
			}
		}
	}

	return OB_PREOP_SUCCESS;
}

为了避免运行驱动时出现权限不足的报错,我们需要在项目属性中的链接器选项页面中,添加/INTEGRITYCHECK:

相关推荐
阿昭L1 个月前
Windows内核事件通知机制
windows·windows内核
阿昭L1 个月前
通过KiSystemServiceUser获取SSDT基址
逆向工程·windows内核·ssdt
阿昭L2 个月前
Windows键盘过滤
windows·驱动开发·windows内核·过滤驱动
阿昭L2 个月前
通过cr3读写进程内存
保护模式·windows内核
阿昭L2 个月前
调试CreateProcess
windows·进程·逆向工程·windows内核
阿昭L3 个月前
调试Windows11启动过程
windows·uefi·windows内核
LittleFishC4 个月前
08_长调用与短调用
c语言·汇编·逆向·windows内核
阿昭L4 个月前
NT驱动程序和WDM驱动程序
驱动开发·windows内核
阿昭L4 个月前
Windows内核驱动重要知识
windows·windows内核