测试了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