X64下利用ObRegisterCallbacks注册对象回调实现进程保护

在X86下,保护进程可以直接利用驱动HOOK SSDT表实现对进程的保护,但到了X64之后,微软了为了保护内核不被随意修改,保护系统的稳定和安全,对驱动增加了两点限制,一是必须有数字签名的驱动才能加载,二是加了PATCHGUARD保护内核,如果发现内核被修改就会直接蓝屏,因此SSDT HOOK不再是很好的方法,但微软同样为了系统安全,增加了一个对象回调函数的接口,利用该回调可以实现对对象请求的过滤保护自身的进程,目前大部分X64下的安全软件保护机制都是基于该方法。
注:由于MmVerifyCallbackFunction,没有数字签名的驱动在注册回调函数时会一直返回失败,因此在加载驱动时要先过MmVerifyCallbackFunction


下面是关于实现保护记事本进程不被结束的代码:
 


//obCallback.h
#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
#include <ntifs.h>

#ifdef __cplusplus
}
#endif 


#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
#define PROCESS_TERMINATE         0x0001  
#define PROCESS_VM_OPERATION      0x0008  
#define PROCESS_VM_READ           0x0010  
#define PROCESS_VM_WRITE          0x0020 

typedef struct _DEVICE_EXTENSION {
	PDEVICE_OBJECT pDevice;
	UNICODE_STRING ustrDeviceName;	//设备名称
	UNICODE_STRING ustrSymLinkName;	//符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;  //设备扩展信息结构体


typedef struct _LDR_DATA_TABLE_ENTRY64
{
	LIST_ENTRY64    InLoadOrderLinks;
	LIST_ENTRY64    InMemoryOrderLinks;
	LIST_ENTRY64    InInitializationOrderLinks;
	PVOID            DllBase;
	PVOID            EntryPoint;
	ULONG            SizeOfImage;
	UNICODE_STRING    FullDllName;
	UNICODE_STRING     BaseDllName;
	ULONG            Flags;
	USHORT            LoadCount;
	USHORT            TlsIndex;
	PVOID            SectionPointer;
	ULONG            CheckSum;
	PVOID            LoadedImports;
	PVOID            EntryPointActivationContext;
	PVOID            PatchInformation;
	LIST_ENTRY64    ForwarderLinks;
	LIST_ENTRY64    ServiceTagLinks;
	LIST_ENTRY64    StaticLinks;
	PVOID            ContextInformation;
	ULONG64            OriginalBase;
	LARGE_INTEGER    LoadTime;
} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;


NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDrvObj); //创建设备例程
void UnloadDriver(IN PDRIVER_OBJECT pDrvObj); //驱动卸载函数

NTSTATUS ProtectProcess(); //进程保护
OB_PREOP_CALLBACK_STATUS MyCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation); //回调函数
char* GetProcessNameByProcessID(HANDLE pid); //取进程名


//obCallback.cpp

#include "obCallback.h"

#ifdef __cplusplus
extern "C"
{
#endif
	UCHAR *PsGetProcessImageFileName(PEPROCESS EProcess);
#ifdef __cplusplus
}
#endif

BOOLEAN pre = FALSE;
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverOb, IN PUNICODE_STRING pRegistryPath)
{
	KdPrint(("开始加载驱动"));
	NTSTATUS status = 0;
	pDriverOb->DriverUnload = UnloadDriver;

	status = CreateDevice(pDriverOb);
	KdPrint(("驱动加载完成1"));

	PLDR_DATA_TABLE_ENTRY64 ldrDataTable;
	ldrDataTable = (PLDR_DATA_TABLE_ENTRY64)pDriverOb->DriverSection;
	ldrDataTable->Flags |= 0x20;  //过MmVerifyCallbackFunction

	status = ProtectProcess(); //实现对象回调
	if (NT_SUCCESS(status))
	{
		KdPrint(("注册回调函数成功"));
		pre = TRUE;
	}
	else
		KdPrint(("注册回调函数失败"));
	return status;
}



PVOID obHandle;  //存储回调句柄

NTSTATUS ProtectProcess()
{

	OB_CALLBACK_REGISTRATION obReg;
	OB_OPERATION_REGISTRATION opReg;

	memset(&obReg, 0, sizeof(obReg));
	obReg.Version = ObGetFilterVersion();
	obReg.OperationRegistrationCount = 1;
	obReg.RegistrationContext = NULL;
	RtlInitUnicodeString(&obReg.Altitude, L"321000");

	memset(&opReg, 0, sizeof(opReg)); //初始化结构体变量

	opReg.ObjectType = PsProcessType;
	opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;

	opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&MyCallback);  //注册回调函数指针

	obReg.OperationRegistration = &opReg; //注意这一条语句
	return ObRegisterCallbacks(&obReg, &obHandle); //注册回调函数
}

OB_PREOP_CALLBACK_STATUS MyCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
	HANDLE pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
	char szProcName[16] = { 0 };
	UNREFERENCED_PARAMETER(RegistrationContext);
	strcpy(szProcName, GetProcessNameByProcessID(pid));
	
	if (!_stricmp(szProcName, "notepad.exe"))
	{
		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
		{
			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
			{
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
			}
			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION)
			{
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_OPERATION;
			}
			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_READ) == PROCESS_VM_READ)
			{
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_READ;
			}
			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
			{
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
			}
		}
	}
	return OB_PREOP_SUCCESS;
}

char* GetProcessNameByProcessID(HANDLE pid)
{
	NTSTATUS status;
	PEPROCESS EProcess = NULL;
	status = PsLookupProcessByProcessId(pid, &EProcess);

	if (!NT_SUCCESS(status))
	{
		return FALSE;
	}
	ObDereferenceObject(EProcess);
	return (char*)PsGetProcessImageFileName(EProcess);
}



NTSTATUS CreateDevice(
	IN PDRIVER_OBJECT	pDriverObject)  //初始化设备对象 返回初始化状态
{
	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	PDEVICE_EXTENSION pDevExt;

	//创建设备名称
	UNICODE_STRING devName;
	RtlInitUnicodeString(&devName, L"\\Device\\ObCALL");

	//创建设备
	status = IoCreateDevice(pDriverObject,
		sizeof(DEVICE_EXTENSION),
		&(UNICODE_STRING)devName,
		FILE_DEVICE_UNKNOWN,
		0, TRUE,
		&pDevObj);
	if (!NT_SUCCESS(status))
		return status;

	pDevObj->Flags |= DO_BUFFERED_IO;
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	pDevExt->pDevice = pDevObj;
	pDevExt->ustrDeviceName = devName;
	//创建符号链接
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName, L"\\??\\Object");
	pDevExt->ustrSymLinkName = symLinkName;
	status = IoCreateSymbolicLink(&symLinkName, &devName);
	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDevObj);
		return status;
	}
	return STATUS_SUCCESS;
}


void UnloadDriver(IN PDRIVER_OBJECT pDriverObject) //驱动程序的卸载操作
{
	PDEVICE_OBJECT	pNextObj;
	KdPrint(("Enter DriverUnload\n"));
	if (pre)  //如果注册回调函数成功则删除回调
		ObUnRegisterCallbacks(obHandle);
	KdPrint(("已删除回调"));
	pNextObj = pDriverObject->DeviceObject;
	while (pNextObj != NULL)
	{
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
			pNextObj->DeviceExtension;

		//删除符号链接
		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);
		pNextObj = pNextObj->NextDevice;
		IoDeleteDevice(pDevExt->pDevice);
	}
	KdPrint(("驱动被卸载!"));
}

 

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值