Win7x64通过ObCallback过滤文件、命名管道创建和打开

测试了win7x64 、win8x64,可以正常过滤命名管道。

也可以通过替换npfs驱动的dispatch入口函数来做。

#include <ntifs.h>
#include <ntddk.h>

struct ThreadData
{
	ULONG ThreadId;
	int Priority;
};

#define  PRIORITY_BOOSTER_DEVICE 0X8000

#define IOCTL_PRIORITY_BOOSTER_SET_PRIORITY CTL_CODE(PRIORITY_BOOSTER_DEVICE, \
	0x800, METHOD_NEITHER, FILE_ANY_ACCESS)

typedef struct _OBJECT_TYPE_INITIALIZER
{
	UINT16       Length;
	union
	{
		UINT8        ObjectTypeFlags;
		struct
		{
			UINT8        CaseInsensitive : 1;
			UINT8        UnnamedObjectsOnly : 1;
			UINT8        UseDefaultObject : 1;
			UINT8        SecurityRequired : 1;
			UINT8        MaintainHandleCount : 1;
			UINT8        MaintainTypeList : 1;
			UINT8        SupportsObjectCallbacks : 1;
		};
	};
	ULONG32      ObjectTypeCode;
	ULONG32      InvalidAttributes;
	struct _GENERIC_MAPPING GenericMapping;
	ULONG32      ValidAccessMask;
	ULONG32      RetainAccess;
	enum _POOL_TYPE PoolType;
	ULONG32      DefaultPagedPoolCharge;
	ULONG32      DefaultNonPagedPoolCharge;
	PVOID        DumpProcedure;
	PVOID        OpenProcedure;
	PVOID         CloseProcedure;
	PVOID         DeleteProcedure;
	PVOID         ParseProcedure;
	PVOID        SecurityProcedure;
	PVOID         QueryNameProcedure;
	PVOID         OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_TYPE_TEMP
{
	struct _LIST_ENTRY TypeList;
	struct _UNICODE_STRING Name;
	VOID* DefaultObject;
	UINT8        Index;
	UINT8        _PADDING0_[0x3];
	ULONG32      TotalNumberOfObjects;
	ULONG32      TotalNumberOfHandles;
	ULONG32      HighWaterNumberOfObjects;
	ULONG32      HighWaterNumberOfHandles;
	UINT8        _PADDING1_[0x4];
	struct _OBJECT_TYPE_INITIALIZER TypeInfo;
	ULONG64 TypeLock;
	ULONG32      Key;
	UINT8        _PADDING2_[0x4];
	struct _LIST_ENTRY CallbackList;
}OBJECT_TYPE_TEMP, * POBJECT_TYPE_TEMP;

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;

// protitypes
void PriorityBoosterUnload(_In_ PDRIVER_OBJECT DriverObject);
NTSTATUS PriorityBoosterCreateClose(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp);
NTSTATUS PriorityBoosterDeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp);
HANDLE g_ObRegHandle = nullptr;

extern "C" NTSYSAPI PUCHAR NTAPI PsGetProcessImageFileName(PEPROCESS Process);


// DriverEntry
EXTERN_C_START NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
	UNREFERENCED_PARAMETER(RegistryPath);


	// 禁用签名校验
	PLDR_DATA_TABLE_ENTRY64 ldr;
	ldr = (PLDR_DATA_TABLE_ENTRY64)(DriverObject->DriverSection);
	ldr->Flags |= 0x20;


	DriverObject->DriverUnload = PriorityBoosterUnload;
	DriverObject->MajorFunction[IRP_MJ_CREATE] = PriorityBoosterCreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = PriorityBoosterCreateClose;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PriorityBoosterDeviceControl;

	UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\PriorityBooster");
	PDEVICE_OBJECT DeviceObject;
	NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Failed to create device (0x%08X)\n", status));
		return status;
	}

	UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\PriorityBooster");
	status = IoCreateSymbolicLink(&symLink, &devName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Failed to create symbolic link (0x%08X)\n", status));
		IoDeleteDevice(DeviceObject);
		return status;
	}
	return STATUS_SUCCESS;
}
EXTERN_C_END

void PriorityBoosterUnload(_In_ PDRIVER_OBJECT DriverObject)
{

	if (g_ObRegHandle)
	{
		ObUnRegisterCallbacks(g_ObRegHandle);
	}

	UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\PriorityBooster");
	// delete symbolic link
	IoDeleteSymbolicLink(&symLink);

	// delete device object
	IoDeleteDevice(DriverObject->DeviceObject);
}

_Use_decl_annotations_
NTSTATUS PriorityBoosterCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	UNREFERENCED_PARAMETER(DeviceObject);

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// callback routine
OB_PREOP_CALLBACK_STATUS obPreOperationCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	HANDLE pid = PsGetCurrentProcessId();
	do
	{
		// 过滤 system pid
		if ((ULONG)pid < 4)
		{
			break;
		}

		// invalid object type
		if (OperationInformation->ObjectType != *IoFileObjectType)
		{
			break;
		}

		// invalid filename pointer
		PFILE_OBJECT pFileObj = (PFILE_OBJECT)OperationInformation->Object;
		if (pFileObj->FileName.Buffer == NULL  || !MmIsAddressValid(pFileObj->FileName.Buffer)
			|| pFileObj->DeviceObject == NULL  || !MmIsAddressValid(pFileObj->DeviceObject)
			)
		{
			break;
		}

		// 过滤指定进程的文件操作事件
		PEPROCESS eProcess = NULL;
		status = PsLookupProcessByProcessId(pid, &eProcess);
		if (!NT_SUCCESS(status))
		{
			KdPrint(("Get PsLookupProcessByProcessId Failed\n")); break;
		}

		// 获取当前进程名
		PUCHAR pszProcessName = PsGetProcessImageFileName(eProcess);
		if (pszProcessName == NULL)
		{
			KdPrint(("Get PsGetProcessImageFileName Failed\n"));  break;
		}

		// 过滤当前进程非Server.exe或者Client.exe
		if (strstr((const char*)pszProcessName, "Server.exe") || strstr((const char*)pszProcessName, "Client.exe"))
		{
			if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
			{
				DbgPrint("[OB_OPERATION_HANDLE_CREATE]===>Target File Name:%wZ \n", &pFileObj->FileName);
			}

			if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
			{
				DbgPrint("[OB_OPERATION_HANDLE_DUPLICATE]===>Target File Name:%wZ \n", &pFileObj->FileName);
			}
		}
	} while (0);



	return OB_PREOP_SUCCESS;
}

// 安装、卸载 对象回调函数
_Use_decl_annotations_
NTSTATUS ObProtection(BOOLEAN IsEnable)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	// 安装对象回调
	if (IsEnable && g_ObRegHandle == nullptr)
	{
		OB_CALLBACK_REGISTRATION obCallbackReg = { 0 };
		OB_OPERATION_REGISTRATION obOperationReg = { 0 };

		// enable ObjectType
		POBJECT_TYPE_TEMP obType = (POBJECT_TYPE_TEMP)*IoFileObjectType;
		obType->TypeInfo.SupportsObjectCallbacks = 1;

		// init obCallbackReg members
		obCallbackReg.Version = ObGetFilterVersion();
		obCallbackReg.RegistrationContext = nullptr;
		RtlInitUnicodeString(&obCallbackReg.Altitude,L"321000");
		obCallbackReg.OperationRegistrationCount = 1;
		obCallbackReg.OperationRegistration = &obOperationReg;

		// init obOperationReg members
		obOperationReg.ObjectType = IoFileObjectType;
		obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
		obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&obPreOperationCall;

		// Start register
		status = ObRegisterCallbacks(&obCallbackReg, &g_ObRegHandle);
		return status;

	}
	// 卸载对象回调
	else
	{
		if (g_ObRegHandle)
		{
			ObUnRegisterCallbacks(g_ObRegHandle);
		}
	}

	return STATUS_SUCCESS;
}

_Use_decl_annotations_
NTSTATUS PriorityBoosterDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	UNREFERENCED_PARAMETER(DeviceObject);
	// get our IO_STACK_LOCATION
	auto stack = IoGetCurrentIrpStackLocation(Irp);
	auto status = STATUS_SUCCESS;

	switch (stack->Parameters.DeviceIoControl.IoControlCode)
	{
	case IOCTL_PRIORITY_BOOSTER_SET_PRIORITY:
	{
		// do the work
		if (stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ThreadData))
		{
			status = STATUS_BUFFER_TOO_SMALL;
			break;
		}

		auto data = (ThreadData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
		if (data == nullptr)
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		__try
		{
			// install object callback
			if (data->Priority > 0)
			{
				ObProtection(true);
			}
			// uninstall object callback
			else
			{
				ObProtection(false);
			}

		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			// something wrong with the buffer
			status = STATUS_ACCESS_VIOLATION;
		}
		break;
	}
	default:
		status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return status;
}


参考资料:

  • https://revers.engineering/superseding-driver-altitude-checks-on-windows/
  • https://www.unknowncheats.me/forum/anti-cheat-bypass/299235-driver-obregistercallbacks-fail.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值