驱动开发:内核中的文件回调

无论在用户层还是内核层,操作文件的流程基本一致,除了在API函数上的区别(用户层调用用户层API,内核层调用内核API)以外其他基本一致,先讲解一下文件系统执行的流程。

以NTFS文件系统为例:假设我们要读取文件,他们最终都会被转换为IRP(I/O Request Package)请求,该请求会被分发到 NTFS.sys 驱动中的 IRP_MJ_READ 分发函数里,NTFS.sys 驱动经过处理后,继续将IRP请求传递给CLASSPNP.sys磁盘类驱动的 IRP_MJ_READ 分发函数,磁盘类驱动处理完毕后,又把 IRP 传给磁盘ATAPI.SYS小端口驱动的 IRP_MJ_SCSI 分发函数中,依靠 HAL.DLL 发送相关的硬件中断请求,而硬件中断则负责完成实际的磁盘寻址,此时数据就真的从硬盘里读取了出来,然后再按照相反的方向把数据返回到调用者。

简单的保护文件

代码实现了Windows内核模式驱动程序,其主要功能是在加载时打开或创建名为“C:\Dbgview.exe”的文件,并在卸载时关闭该文件句柄。此驱动程序还使用DbgPrint函数输出调试消息。虽然代码表明它在进行某种保护操作,但需要更多上下文信息才能确定其详细目的和功能。

#include <ntddk.h>

HANDLE FileHandle = NULL;
VOID UnDriver(PDRIVER_OBJECT driver)
{
	if (FileHandle != NULL)
	{
		DbgPrint("保护已关闭...");
		ZwClose(FileHandle);
	}
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	IO_STATUS_BLOCK OldStatus;
	
	OBJECT_ATTRIBUTES Object_Attach;
	UNICODE_STRING Old_Ufile_Name = RTL_CONSTANT_STRING(L"\\??\\C:\\Dbgview.exe");
	InitializeObjectAttributes(&Object_Attach, &Old_Ufile_Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
	ZwCreateFile(&FileHandle, GENERIC_READ, &Object_Attach, &OldStatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, 
		FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
	DbgPrint("保护已启动..");
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

内核中删除文件

普通的内核删除文件,不是强制删除。这段代码的主要功能是在加载时删除指定文件 "c://lyshark.log"。当驱动程序卸载时,它会调用 UnDriver 函数,尽管在这个示例中 UnDriver 函数没有实际操作。请注意,在实际应用中,内核模式驱动程序需要更多的安全和错误处理来确保文件操作的成功和安全性。

#include <ntddk.h>
#include <windef.h>

void ZwDeleteFileFolder(WCHAR *FileName)
{
	NTSTATUS Status;
	OBJECT_ATTRIBUTES ObjectAttr;
	UNICODE_STRING UniFileName;
	// 把WCHAR*转化为 UNICODE_STRING
	RtlInitUnicodeString(&UniFileName, FileName);
	InitializeObjectAttributes(&ObjectAttr,&UniFileName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);
	Status = ZwDeleteFile(&ObjectAttr);
}

VOID UnDriver(PDRIVER_OBJECT driver){}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	ZwDeleteFileFolder("c://lyshark.log");
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}


对象回调监控文件访问

#include <ntddk.h>
#include <string.h>

PVOID obHandle;
typedef struct _OBJECT_TYPE_INITIALIZER
{
	/*0x000*/     UINT16       Length;
	union
	{
		/*0x002*/         UINT8        ObjectTypeFlags;
		struct
		{
			/*0x002*/             UINT8        CaseInsensitive : 1;
			/*0x002*/             UINT8        UnnamedObjectsOnly : 1;
			/*0x002*/             UINT8        UseDefaultObject : 1;
			/*0x002*/             UINT8        SecurityRequired : 1;
			/*0x002*/             UINT8        MaintainHandleCount : 1;
			/*0x002*/             UINT8        MaintainTypeList : 1;
			/*0x002*/             UINT8        SupportsObjectCallbacks : 1;
		};
	};
	/*0x004*/     ULONG32      ObjectTypeCode;
	/*0x008*/     ULONG32      InvalidAttributes;
	/*0x00C*/     struct _GENERIC_MAPPING GenericMapping;
	/*0x01C*/     ULONG32      ValidAccessMask;
	/*0x020*/     ULONG32      RetainAccess;
	/*0x024*/     enum _POOL_TYPE PoolType;
	/*0x028*/     ULONG32      DefaultPagedPoolCharge;
	/*0x02C*/     ULONG32      DefaultNonPagedPoolCharge;
	/*0x030*/     PVOID DumpProcedure;
	/*0x038*/     PVOID OpenProcedure;
	/*0x040*/     PVOID CloseProcedure;
	/*0x048*/     PVOID DeleteProcedure;
	/*0x050*/     PVOID ParseProcedure;
	/*0x058*/     PVOID SecurityProcedure;
	/*0x060*/     PVOID QueryNameProcedure;
	/*0x068*/     PVOID OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

typedef struct _EX_PUSH_LOCK                 // 7 elements, 0x8 bytes (sizeof)
{
	union                                    // 3 elements, 0x8 bytes (sizeof)
	{
		struct                               // 5 elements, 0x8 bytes (sizeof)
		{
			/*0x000*/             UINT64       Locked : 1;         // 0 BitPosition
			/*0x000*/             UINT64       Waiting : 1;        // 1 BitPosition
			/*0x000*/             UINT64       Waking : 1;         // 2 BitPosition
			/*0x000*/             UINT64       MultipleShared : 1; // 3 BitPosition
			/*0x000*/             UINT64       Shared : 60;        // 4 BitPosition
		};
		/*0x000*/         UINT64       Value;
		/*0x000*/         VOID*        Ptr;
	};
}EX_PUSH_LOCK, *PEX_PUSH_LOCK;

typedef struct _MY_OBJECT_TYPE
{
	/*0x000*/     struct  _LIST_ENTRY TypeList;
	/*0x010*/     struct  _UNICODE_STRING Name;
	/*0x020*/     VOID*   DefaultObject;
	/*0x028*/     UINT8   Index;
	/*0x029*/     UINT8   _PADDING0_[0x3];
	/*0x02C*/     ULONG32 TotalNumberOfObjects;
	/*0x030*/     ULONG32 TotalNumberOfHandles;
	/*0x034*/     ULONG32 HighWaterNumberOfObjects;
	/*0x038*/     ULONG32 HighWaterNumberOfHandles;
	/*0x03C*/     UINT8   _PADDING1_[0x4];
	/*0x040*/     struct _OBJECT_TYPE_INITIALIZER TypeInfo;
	/*0x0B0*/     struct _EX_PUSH_LOCK TypeLock;
	/*0x0B8*/     ULONG32      Key;
	/*0x0BC*/     UINT8        _PADDING2_[0x4];
	/*0x0C0*/     struct _LIST_ENTRY CallbackList;
}MY_OBJECT_TYPE, *PMY_OBJECT_TYPE;


// 要监控文件,首先要文件对象支持对象回调
VOID EnableObType(POBJECT_TYPE ObjectType)
{
	PMY_OBJECT_TYPE myobtype = (PMY_OBJECT_TYPE)ObjectType;
	myobtype->TypeInfo.SupportsObjectCallbacks = 1;
}

OB_PREOP_CALLBACK_STATUS preFileCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
	UNICODE_STRING DosName;
	PFILE_OBJECT fileo = OperationInformation->Object;
	HANDLE CurrentProcessId = PsGetCurrentProcessId();
	UNREFERENCED_PARAMETER(RegistrationContext);

	if (OperationInformation->ObjectType != *IoFileObjectType) { return OB_PREOP_SUCCESS; }
	//过滤无效指针
	if (fileo->FileName.Buffer == NULL ||
		!MmIsAddressValid(fileo->FileName.Buffer) ||
		fileo->DeviceObject == NULL ||
		!MmIsAddressValid(fileo->DeviceObject))
		return OB_PREOP_SUCCESS;

	// 此处可添加过滤规则,过滤掉无效文件名
	if (!_wcsicmp(fileo->FileName.Buffer, L"\\Endpoint") ||
		!_wcsicmp(fileo->FileName.Buffer, L"?") ||
		!_wcsicmp(fileo->FileName.Buffer, L"\\.\\.") ||
		!_wcsicmp(fileo->FileName.Buffer, L"\\"))
		return OB_PREOP_SUCCESS;

	if (wcsstr(_wcslwr(fileo->FileName.Buffer), L".exe")) // 如果包含有exe文件,则触发
	{
		DbgPrint("当前ID= %ld ---> 路径= %wZ", (ULONG64)CurrentProcessId, &fileo->FileName);
	}
	return OB_PREOP_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
	UNREFERENCED_PARAMETER(driver);
	ObUnRegisterCallbacks(obHandle);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	OB_CALLBACK_REGISTRATION obReg;
	OB_OPERATION_REGISTRATION opReg;

	EnableObType(*IoFileObjectType);
	memset(&obReg, 0, sizeof(obReg));
	obReg.Version = ObGetFilterVersion();
	obReg.OperationRegistrationCount = 1;
	obReg.RegistrationContext = NULL;
	RtlInitUnicodeString(&obReg.Altitude, L"321000");
	obReg.OperationRegistration = &opReg;
	memset(&opReg, 0, sizeof(opReg));
	opReg.ObjectType = IoFileObjectType;
	opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
	opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preFileCallBack;
	status = ObRegisterCallbacks(&obReg, &obHandle);
	
	if (!NT_SUCCESS(status))
		status = STATUS_UNSUCCESSFUL;
	Driver->DriverUnload = UnDriver;
	return status;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微软技术分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值