⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfilter.c

📁 网程络过滤驱动,可以截获网络封包!对其进行分析拦截!
💻 C
📖 第 1 页 / 共 5 页
字号:

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
// 
//				IRP Handling Routines
// 
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /


NTSTATUS
SfPassThrough(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
/*++

Routine Description:

	This routine is the main dispatch routine for the general purpose file
	system driver.  It simply passes requests onto the next driver in the
	stack, which is presumably a disk file system.

Arguments:

	DeviceObject - Pointer to the device object for this driver.

	Irp - Pointer to the request packet representing the I/O request.

Return Value:

	The function value is the status of the operation.

Note:

	A note to file system filter implementers:  
		This routine actually "passes" through the request by taking this
		driver out of the IRP stack.  If the driver would like to pass the
		I/O request through, but then also see the result, then rather than
		taking itself out of the loop it could keep itself in by copying the
		caller's parameters to the next stack location and then set its own
		completion routine.  

		Hence, instead of calling:
	
			IoSkipCurrentIrpStackLocation(Irp);

		You could instead call:

			IoCopyCurrentIrpStackLocationToNext(Irp);
			IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);


		This example actually NULLs out the caller's I/O completion routine, but
		this driver could set its own completion routine so that it would be
		notified when the request was completed (see SfCreate for an example of
		this).

--*/
{
	// 
	// Sfilter doesn't allow handles to its control device object to be created,
	// therefore, no other operation should be able to come through.
	// 
	ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
	ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));

	// 
	// Get this driver out of the driver stack and get to the next driver as
	// quickly as possible.
	// 
	IoSkipCurrentIrpStackLocation(Irp);
	
	// 
	// Call the appropriate file system driver with the request.
	// 
	return IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp);
}


VOID
SfDisplayCreateFileName(
	IN PIRP Irp
	)
/*++

Routine Description:

	This function is called from SfCreate and will display the name of the
	file being created.  This is in a subroutine so that the local name buffer
	on the stack (in nameControl) is not on the stack when we call down to
	the file system for normal operations.

Arguments:

	Irp - Pointer to the I/O Request Packet that represents the operation.

Return Value:

	None.

--*/
{
	PIO_STACK_LOCATION IrpSp;
	PUNICODE_STRING Name;
	GET_NAME_CONTROL NameControl;

	// 
	// Get current IRP stack
	// 
	IrpSp = IoGetCurrentIrpStackLocation(Irp);

	// 
	// Get the Name of this file object
	// 
	Name = SfGetFileName(IrpSp->FileObject, 
		Irp->IoStatus.Status, 
		&NameControl);
	DbgPrint(Name);
	// 
	// Display the Name
	// 
	if (IrpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID) {
		
		SF_LOG_PRINT(SFDEBUG_DISPLAY_CREATE_NAMES,
					  ("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ (FID)\n", 
						Irp->IoStatus.Status,
						Irp->IoStatus.Information,
						Name));

	} else {

		SF_LOG_PRINT(SFDEBUG_DISPLAY_CREATE_NAMES,
					  ("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ\n", 
						Irp->IoStatus.Status,
						Irp->IoStatus.Information,
						Name));
	}

	// 
	// Cleanup from getting the Name
	// 
	SfGetFileNameCleanup(&NameControl);
}


NTSTATUS
SfCreate(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
	PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT FileObject = IrpSp->FileObject;
	PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
	PWSTR FileName = NULL;
	NTSTATUS Status = STATUS_SUCCESS;
	POST_CREATE_WORKER_CONTEXT WorkerCtx;

	PAGED_CODE();

	// 
	// If this is for our control device object, don't allow it to be opened.
	// 
	if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
	{
		// 
		// Sfilter doesn't allow for any communication through its control
		// device object, therefore it fails all requests to open a handle
		// to its control device object.
		// 
		// See the FileSpy sample for an example of how to allow creates to 
		// the filter's control device object and manage communication via
		// that handle.
		// 
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		return STATUS_INVALID_DEVICE_REQUEST;
	}

	ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));

	// 
	// We only care about volume filter device object
	// 
	if (!DevExt->StorageStackDeviceObject)
	{
		IoSkipCurrentIrpStackLocation(Irp);
		return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
	}

	// 
	// Open Volume Device directly
	// 
	if ((FileObject->FileName.Length == 0) && !RelatedFileObject)
	{
		IoSkipCurrentIrpStackLocation(Irp);
		return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
	}

#if DBG
	if (DevExt->DriveLetter != DEBUG_VOLUME)
	{
		IoSkipCurrentIrpStackLocation(Irp);
		return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
	}
#endif

	do
	{
		// 
		// If the file is opened by id, then we can't get file name directly,
		// But if this case happened, the FsContext must be in GenericTable already.
		// So we just update the RefCount, that's enough
		// 
		if (!(IrpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID))
		{
			FileName = ExAllocateFromPagedLookasideList(&gFileNameLookAsideList);
			if (!FileName)
			{
				KdPrint(("sfilter!SfCreate: ExAllocatePoolWithTag failed\n"));

				Status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			if (!SfDissectFileName(DeviceObject, Irp, FileName))
			{
				KdPrint(("sfilter!SfCreate: SfDissectFileName failed\n"));
				
				Status = STATUS_INVALID_PARAMETER;
				break;
			}

			if (0 == _wcsnicmp(&FileName[3], SF_ENCRYPT_INFO_DIR, SF_ENCRYPT_INFOR_DIR_LENGTH))
			{
				// 
				// We deny all create request to our encrypt info dir except kernel mode
				// 
				if (KernelMode == Irp->RequestorMode)
				{
					ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);

					IoSkipCurrentIrpStackLocation(Irp);
					return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
				}
				else
				{
					Status = STATUS_NO_SUCH_FILE;
					break;
				}
			}
			else
			{
				if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
				{
					//
					// We don't care about directories
					//
					ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);

					IoSkipCurrentIrpStackLocation(Irp);
					return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
				}
			}
		}
		else
		{
			if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
			{
				//
				// We don't care about directories
				//
				IoSkipCurrentIrpStackLocation(Irp);
				return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
			}
		}
		
		Status = SfForwardIrpSyncronously(DevExt->AttachedToDeviceObject, Irp);
		if (NT_SUCCESS(Status) && (STATUS_REPARSE != Status))
		{
			FILE_CONTEXT FileCtx;
			PFILE_CONTEXT FileCtxPtr = NULL;
			BOOLEAN NewElement = FALSE;

			FileCtx.FsContext = FileObject->FsContext;

			ExAcquireFastMutex(&DevExt->FsCtxTableMutex);

			FileCtxPtr = RtlLookupElementGenericTable(&DevExt->FsCtxTable, &FileCtx);
			if (FileCtxPtr)
				++FileCtxPtr->RefCount;
			else
			{
				FileCtxPtr = RtlInsertElementGenericTable(
					&DevExt->FsCtxTable,
					&FileCtx,
					sizeof(FILE_CONTEXT),
					&NewElement
					);

				FileCtxPtr->RefCount = 1;

				ASSERT(FileName);
				wcscpy(FileCtxPtr->Name, FileName);

				KeInitializeEvent(&FileCtxPtr->Event, SynchronizationEvent, TRUE);
			}

			ExReleaseFastMutex(&DevExt->FsCtxTableMutex);

			ExInitializeWorkItem(&WorkerCtx.WorkItem, SfPostCreateWorker, &WorkerCtx);
			WorkerCtx.DeviceObject = DeviceObject;
			WorkerCtx.FileObject = FileObject;
			KeInitializeEvent(&WorkerCtx.Event, NotificationEvent, FALSE);
			WorkerCtx.FileContext = FileCtxPtr;
			WorkerCtx.NewElement = NewElement;
				
			if (KeGetCurrentIrql() == PASSIVE_LEVEL)
				SfPostCreateWorker(&WorkerCtx);
			else
			{
				ExQueueWorkItem(&WorkerCtx.WorkItem, DelayedWorkQueue);
				KeWaitForSingleObject(&WorkerCtx.Event, Executive, KernelMode, FALSE, NULL);
			}
		}
	} while (FALSE);

	if (FileName)
		ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);

	Irp->IoStatus.Status = Status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return Status;
}

VOID
SfPostCreateWorker(
	IN PVOID Context
	)
{
	PPOST_CREATE_WORKER_CONTEXT WorkerCtx = Context;
	PDEVICE_OBJECT DeviceObject = WorkerCtx->DeviceObject;
	PFILE_OBJECT FileObject = WorkerCtx->FileObject;
	PFILE_CONTEXT FileCtxPtr = WorkerCtx->FileContext;
	BOOLEAN NewElement = WorkerCtx->NewElement;
	BOOLEAN IsEncryptFlagExist = FALSE;
	BOOLEAN IsNeedEncrypt = FALSE;
	NTSTATUS Status = STATUS_SUCCESS;

	KdPrint(("sfilter!SfPostCreateWorker: FileName = %ws\n", FileCtxPtr->Name));

	//
	// we need handle file synchronously
	//
	KeWaitForSingleObject(&FileCtxPtr->Event, Executive, KernelMode, FALSE, NULL);
	
	if (NewElement)
	{
		Status = SfIsEncryptFlagExist(DeviceObject, FileCtxPtr->Name, &IsEncryptFlagExist, FileCtxPtr->EncryptExtData, sizeof(FileCtxPtr->EncryptExtData));
		if (!NT_SUCCESS(Status))
			KdPrint(("sfilter!SfCreate: SfIsEncryptFlagExist failed, return %x\n", Status));
		
		Status = SfIsFileNeedEncrypt(DeviceObject, FileCtxPtr->Name, &IsNeedEncrypt);
		if (!NT_SUCCESS(Status))
			KdPrint(("sfilter!SfCreate: SfIsFileNeedEncrypt failed, return %x\n", Status));
	
		FileCtxPtr->EncryptFlagExist = IsEncryptFlagExist;
		FileCtxPtr->NeedEncrypt = IsNeedEncrypt;
	}
	else
	{
		IsEncryptFlagExist = FileCtxPtr->EncryptFlagExist;
		IsNeedEncrypt = FileCtxPtr->NeedEncrypt;

		ASSERT(IsEncryptFlagExist == IsNeedEncrypt);
	}
	
	if ((!IsNeedEncrypt && IsEncryptFlagExist) || (IsNeedEncrypt && !IsEncryptFlagExist))
	{
		if (!IsNeedEncrypt && IsEncryptFlagExist)
		{
			FileCtxPtr->DecryptOnRead = TRUE;
			FileCtxPtr->EncryptOnWrite = FALSE;
			
			KdPrint(("sfilter!SfPostCreateWorker: Decrypt %ws\n", FileCtxPtr->Name));
			Status = SfEncryptDecryptFileByFileObject(DeviceObject, FileObject);
			if (NT_SUCCESS(Status))
			{
				FileCtxPtr->DecryptOnRead = FALSE;
				FileCtxPtr->EncryptOnWrite = FALSE;
	
				Status = SfSetFileEncrypted(DeviceObject, FileCtxPtr->Name, FALSE, NULL, 0);
				if (NT_SUCCESS(Status))
					FileCtxPtr->EncryptFlagExist = FALSE;
				else
					KdPrint(("sfilter!SfCreate: SfSetFileEncrypted(%ws, FALSE) failed, return %x\n", FileCtxPtr->Name, Status));
			}
			else
			{
				KdPrint(("sfilter!SfCreate: SfEncryptDecryptFileByFileObject failed, return %x\n", Status));
	
				FileCtxPtr->DecryptOnRead = TRUE;
				FileCtxPtr->EncryptOnWrite = TRUE;
			}
		}
		else
		{
			FileCtxPtr->DecryptOnRead = FALSE;
			FileCtxPtr->EncryptOnWrite = TRUE;

			KdPrint(("sfilter!SfPostCreateWorker: Encrypt %ws\n", FileCtxPtr->Name));
			Status = SfEncryptDecryptFileByFileObject(DeviceObject, FileObject);
			if (NT_SUCCESS(Status))
			{
				FileCtxPtr->DecryptOnRead = TRUE;
				FileCtxPtr->EncryptOnWrite = TRUE;
	
				Status = SfSetFileEncrypted(DeviceObject, FileCtxPtr->Name, TRUE, FileCtxPtr->EncryptExtData, sizeof(FileCtxPtr->EncryptExtData));
				if (NT_SUCCESS(Status))
					FileCtxPtr->EncryptFlagExist = TRUE;
				else
					KdPrint(("sfilter!SfCreate: SfSetFileEncrypted(%ws, TRUE) failed, return %x\n", FileCtxPtr->Name, Status));
			}
			else
			{
				KdPrint(("sfilter!SfCreate: SfEncryptDecryptFileByFileObject failed, return %x\n", Status));
	
				FileCtxPtr->DecryptOnRead = FALSE;
				FileCtxPtr->EncryptOnWrite = FALSE;
			}											
		}
	}
	else
	{
		if (IsNeedEncrypt && IsEncryptFlagExist)
		{
			FileCtxPtr->DecryptOnRead = TRUE;
			FileCtxPtr->EncryptOnWrite = TRUE;
		}
		else
		{
			FileCtxPtr->DecryptOnRead = FALSE;
			FileCtxPtr->EncryptOnWrite = FALSE;
		}
	}
	
	KeSetEvent(&FileCtxPtr->Event, IO_NO_INCREMENT, FALSE);

	KeSetEvent(&WorkerCtx->Event, IO_NO_INCREMENT, FALSE);
}

NTSTATUS
SfCleanupClose(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
	PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT FileObject = IrpSp->FileObject;

	PAGED_CODE();

	// 
	// Sfilter doesn't allow handles to its control device object to be created,
	// therefore, no other operation should be able to come through.
	//  
	ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
	ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));

#if DBG
	if (DevExt->DriveLetter != DEBUG_VOLUME)
	{
		IoSkipCurrentIrpStackLocation(Irp);
		return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
	}
#endif
	
	// 
	// We only care about volume filter device object
	// 
	if (DevExt->StorageStackDeviceObject && (IrpSp->MajorFunction == IRP_MJ_CLOSE))
	{
		FILE_CONTEXT FileCtx;
		PFILE_CONTEXT FileCtxPtr = NULL;

		if (((FileObject->Flags & FO_STREAM_FILE) == FO_STREAM_FILE) ||
			(FileObject->Sectio

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -