技术原理
安全软件,反作弊软件经常会有自保护策略,其中的一种常用策略是使用ObRegisterCallbacks()
注册进程对象操作回调,指定回调函数为PreOperationCallback()
,在回调函数中对创建要保护进程句柄的操作进行拦截,并且取消句柄的终止进程权限,以此达到防止进程被终止的目的。
源码展示
以下代码基于上述方法实现了一个针对”cmd.exe”的保护驱动(测试时需要管理员运行bcdedit /set testsigning on,开启测试模式)
#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;
}
驱动入口函数
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;
}
保护效果展示