技术原理
安全软件,反作弊软件经常会有自保护策略,其中的一种常用策略是使用ObRegisterCallbacks()
注册进程对象操作回调,指定回调函数为PreOperationCallback()
,在回调函数中对创建要保护进程句柄的操作进行拦截,并且取消句柄的终止进程权限,以此达到防止进程被终止的目的。
源码展示
以下代码基于上述方法实现了一个针对”cmd.exe”的保护驱动(测试时需要管理员运行bcdedit /set testsigning on,开启测试模式)
#include <ntddk.h>#define PROCESS_TERMINATE 0x0001DRIVER_INITIALIZE DriverEntry;NTKERNELAPI UCHAR* PsGetProcessImageFileName(__in PEPROCESS Process);PVOID RegistrationHandle = NULL;OB_PREOP_CALLBACK_STATUS PreOperationCallback(_In_ PVOID RegistrationContext,_In_ POB_PRE_OPERATION_INFORMATION OperationInformation) {UNREFERENCED_PARAMETER(RegistrationContext);// filter by process name "cmd.exe"PUCHAR name = PsGetProcessImageFileName((PEPROCESS)OperationInformation->Object);if (strcmp((const char*)name, "cmd.exe") != 0) {return OB_PREOP_SUCCESS;}// filter operation "OB_OPERATION_HANDLE_CREATE", and remove "PROCESS_TERMINATE"if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) {KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"ProcessProtect: callback remove [%s] PROCESS_TERMINATE\n", name));OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;}return OB_PREOP_SUCCESS;}VOID OnUnload(_In_ PDRIVER_OBJECT DriverObject) {UNREFERENCED_PARAMETER(DriverObject);// unregister callbacksif (RegistrationHandle != NULL) {ObUnRegisterCallbacks(RegistrationHandle);RegistrationHandle = NULL;}KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: unload driver\n"));}NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath) {OB_OPERATION_REGISTRATION OperationRegistrations = { 0 };OB_CALLBACK_REGISTRATION ObRegistration = { 0 };UNICODE_STRING Altitude = { 0 };NTSTATUS Status = STATUS_SUCCESS;UNREFERENCED_PARAMETER(RegistryPath);KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: driver entry\n"));// register unload functionDriverObject->DriverUnload = OnUnload;// setup the ObRegistration callsOperationRegistrations.ObjectType = PsProcessType;OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE;OperationRegistrations.PreOperation = PreOperationCallback;RtlInitUnicodeString(&Altitude, L"1000");ObRegistration.Version = OB_FLT_REGISTRATION_VERSION;ObRegistration.OperationRegistrationCount = 1;ObRegistration.Altitude = Altitude;ObRegistration.RegistrationContext = NULL;ObRegistration.OperationRegistration = &OperationRegistrations;Status = ObRegisterCallbacks(&ObRegistration, &RegistrationHandle);if (!NT_SUCCESS(Status)) {KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"ProcessProtect: ObRegisterCallbacks failed status 0x%x\n", Status));return Status;}return STATUS_SUCCESS;}#include <ntddk.h> #define PROCESS_TERMINATE 0x0001 DRIVER_INITIALIZE DriverEntry; NTKERNELAPI UCHAR* PsGetProcessImageFileName(__in PEPROCESS Process); PVOID RegistrationHandle = NULL; OB_PREOP_CALLBACK_STATUS PreOperationCallback( _In_ PVOID RegistrationContext, _In_ POB_PRE_OPERATION_INFORMATION OperationInformation ) { UNREFERENCED_PARAMETER(RegistrationContext); // filter by process name "cmd.exe" PUCHAR name = PsGetProcessImageFileName((PEPROCESS)OperationInformation->Object); if (strcmp((const char*)name, "cmd.exe") != 0) { return OB_PREOP_SUCCESS; } // filter operation "OB_OPERATION_HANDLE_CREATE", and remove "PROCESS_TERMINATE" if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: callback remove [%s] PROCESS_TERMINATE\n", name)); OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE; } return OB_PREOP_SUCCESS; } VOID OnUnload(_In_ PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); // unregister callbacks if (RegistrationHandle != NULL) { ObUnRegisterCallbacks(RegistrationHandle); RegistrationHandle = NULL; } KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: unload driver\n")); } NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { OB_OPERATION_REGISTRATION OperationRegistrations = { 0 }; OB_CALLBACK_REGISTRATION ObRegistration = { 0 }; UNICODE_STRING Altitude = { 0 }; NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(RegistryPath); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: driver entry\n")); // register unload function DriverObject->DriverUnload = OnUnload; // setup the ObRegistration calls OperationRegistrations.ObjectType = PsProcessType; OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE; OperationRegistrations.PreOperation = PreOperationCallback; RtlInitUnicodeString(&Altitude, L"1000"); ObRegistration.Version = OB_FLT_REGISTRATION_VERSION; ObRegistration.OperationRegistrationCount = 1; ObRegistration.Altitude = Altitude; ObRegistration.RegistrationContext = NULL; ObRegistration.OperationRegistration = &OperationRegistrations; Status = ObRegisterCallbacks(&ObRegistration, &RegistrationHandle); if (!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: ObRegisterCallbacks failed status 0x%x\n", Status)); return Status; } return STATUS_SUCCESS; }#include <ntddk.h> #define PROCESS_TERMINATE 0x0001 DRIVER_INITIALIZE DriverEntry; NTKERNELAPI UCHAR* PsGetProcessImageFileName(__in PEPROCESS Process); PVOID RegistrationHandle = NULL; OB_PREOP_CALLBACK_STATUS PreOperationCallback( _In_ PVOID RegistrationContext, _In_ POB_PRE_OPERATION_INFORMATION OperationInformation ) { UNREFERENCED_PARAMETER(RegistrationContext); // filter by process name "cmd.exe" PUCHAR name = PsGetProcessImageFileName((PEPROCESS)OperationInformation->Object); if (strcmp((const char*)name, "cmd.exe") != 0) { return OB_PREOP_SUCCESS; } // filter operation "OB_OPERATION_HANDLE_CREATE", and remove "PROCESS_TERMINATE" if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: callback remove [%s] PROCESS_TERMINATE\n", name)); OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE; } return OB_PREOP_SUCCESS; } VOID OnUnload(_In_ PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); // unregister callbacks if (RegistrationHandle != NULL) { ObUnRegisterCallbacks(RegistrationHandle); RegistrationHandle = NULL; } KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: unload driver\n")); } NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { OB_OPERATION_REGISTRATION OperationRegistrations = { 0 }; OB_CALLBACK_REGISTRATION ObRegistration = { 0 }; UNICODE_STRING Altitude = { 0 }; NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(RegistryPath); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: driver entry\n")); // register unload function DriverObject->DriverUnload = OnUnload; // setup the ObRegistration calls OperationRegistrations.ObjectType = PsProcessType; OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE; OperationRegistrations.PreOperation = PreOperationCallback; RtlInitUnicodeString(&Altitude, L"1000"); ObRegistration.Version = OB_FLT_REGISTRATION_VERSION; ObRegistration.OperationRegistrationCount = 1; ObRegistration.Altitude = Altitude; ObRegistration.RegistrationContext = NULL; ObRegistration.OperationRegistration = &OperationRegistrations; Status = ObRegisterCallbacks(&ObRegistration, &RegistrationHandle); if (!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ProcessProtect: ObRegisterCallbacks failed status 0x%x\n", Status)); return Status; } return STATUS_SUCCESS; }
核心代码
回调函数实现
OB_PREOP_CALLBACK_STATUS PreOperationCallback(_In_ PVOID RegistrationContext,_In_ POB_PRE_OPERATION_INFORMATION OperationInformation) {// 获取进程名称PUCHAR name = PsGetProcessImageFileName((PEPROCESS)OperationInformation->Object);// 仅处理cmd.exe进程if (strcmp((const char*)name, "cmd.exe") != 0) {return OB_PREOP_SUCCESS;}// 移除进程终止权限if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) {OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;}return OB_PREOP_SUCCESS;}OB_PREOP_CALLBACK_STATUS PreOperationCallback( _In_ PVOID RegistrationContext, _In_ POB_PRE_OPERATION_INFORMATION OperationInformation ) { // 获取进程名称 PUCHAR name = PsGetProcessImageFileName( (PEPROCESS)OperationInformation->Object ); // 仅处理cmd.exe进程 if (strcmp((const char*)name, "cmd.exe") != 0) { return OB_PREOP_SUCCESS; } // 移除进程终止权限 if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { OperationInformation->Parameters->CreateHandleInformation .DesiredAccess &= ~PROCESS_TERMINATE; } return OB_PREOP_SUCCESS; }OB_PREOP_CALLBACK_STATUS PreOperationCallback( _In_ PVOID RegistrationContext, _In_ POB_PRE_OPERATION_INFORMATION OperationInformation ) { // 获取进程名称 PUCHAR name = PsGetProcessImageFileName( (PEPROCESS)OperationInformation->Object ); // 仅处理cmd.exe进程 if (strcmp((const char*)name, "cmd.exe") != 0) { return OB_PREOP_SUCCESS; } // 移除进程终止权限 if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { OperationInformation->Parameters->CreateHandleInformation .DesiredAccess &= ~PROCESS_TERMINATE; } return OB_PREOP_SUCCESS; }
驱动入口函数
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath) {// 注册卸载函数DriverObject->DriverUnload = OnUnload;// 配置对象回调注册信息OB_OPERATION_REGISTRATION OperationRegistrations = { 0 };OperationRegistrations.ObjectType = PsProcessType;OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE;OperationRegistrations.PreOperation = PreOperationCallback;// 执行回调注册ObRegisterCallbacks(&ObRegistration, &RegistrationHandle);return STATUS_SUCCESS;}NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { // 注册卸载函数 DriverObject->DriverUnload = OnUnload; // 配置对象回调注册信息 OB_OPERATION_REGISTRATION OperationRegistrations = { 0 }; OperationRegistrations.ObjectType = PsProcessType; OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE; OperationRegistrations.PreOperation = PreOperationCallback; // 执行回调注册 ObRegisterCallbacks(&ObRegistration, &RegistrationHandle); return STATUS_SUCCESS; }NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { // 注册卸载函数 DriverObject->DriverUnload = OnUnload; // 配置对象回调注册信息 OB_OPERATION_REGISTRATION OperationRegistrations = { 0 }; OperationRegistrations.ObjectType = PsProcessType; OperationRegistrations.Operations = OB_OPERATION_HANDLE_CREATE; OperationRegistrations.PreOperation = PreOperationCallback; // 执行回调注册 ObRegisterCallbacks(&ObRegistration, &RegistrationHandle); return STATUS_SUCCESS; }
保护效果展示