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

📄 sfilter.c

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

Copyright (c) 1989-1993  Microsoft Corporation

Module Name:

	sfilter.c

Abstract:

	This module contains the code that implements the general purpose sample
	file system filter driver.

	As of the Windows XP SP1 IFS Kit version of this sample and later, this
	sample can be built for each build environment released with the IFS Kit
	with no additional modifications.  To provide this capability, additional
	compile-time logic was added -- see the '#if WINVER' locations.  Comments
	tagged with the 'VERSION NOTE' header have also been added as appropriate to
	describe how the logic must change between versions.

	If this sample is built in the Windows XP environment or later, it will run
	on Windows 2000 or later.  This is done by dynamically loading the routines
	that are only available on Windows XP or later and making run-time decisions
	to determine what code to execute.  Comments tagged with 'MULTIVERISON NOTE'
	mark the locations where such logic has been added.

Environment:

	Kernel mode

--*/

#include "ntifs.h"
#include "ntdddisk.h"

// 
// Enable these warnings in the code.
// 

#pragma warning(error:4100)	// Unreferenced formal parameter
#pragma warning(error:4101)	// Unreferenced local variable

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
// 
//				 Macro and Structure Definitions
// 
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /

// 
// VERSION NOTE:
// 
// The following useful macros are defined in NTIFS.H in Windows XP and later.
// We will define them locally if we are building for the Windows 2000 
// environment.
// 

#if WINVER == 0x0500

// 
// These macros are used to test, set and clear flags respectively
// 

#ifndef FlagOn
#define FlagOn(_F, _SF)			((_F) & (_SF))
#endif

#ifndef BooleanFlagOn
#define BooleanFlagOn(F, SF)	((BOOLEAN) (((F) & (SF)) != 0))
#endif

#ifndef SetFlag
#define SetFlag(_F, _SF)		((_F) |= (_SF))
#endif

#ifndef ClearFlag
#define ClearFlag(_F, _SF)		((_F) &= ~(_SF))
#endif

#define RtlInitEmptyUnicodeString(_ucStr, _buf, _bufSize) \
	((_ucStr)->Buffer = (_buf), \
	 (_ucStr)->Length = 0, \
	 (_ucStr)->MaximumLength = (USHORT)(_bufSize))

#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif

#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif

// 
// We want ASSERT defined as an expression, which was fixed after Windows 2000
// 

#ifdef ASSERT
#undef ASSERT
#if DBG
#define ASSERT(exp) \
	((!(exp)) ? \
		(RtlAssert(#exp, __FILE__, __LINE__, NULL),FALSE) : \
		TRUE)
#else
#define ASSERT(exp) ((void) 0)
#endif
#endif		

#define ExFreePoolWithTag(a, b) ExFreePool((a))

#endif /* WINVER == 0x0500 */

#ifndef Add2Ptr
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
#endif

// 
// Buffer size for local names on the stack
// 

#define MAX_DEVNAME_LENGTH				64
#define MAX_PATH						512

#define ENCRYPT_BIT_SIZE				(128 * 8)

#define SF_ENCRYPT_INFO_DIR				L"System Encrypt Information"
#define SF_ENCRYPT_INFOR_DIR_LENGTH		26

#define RULE_FILE_NAME					L"\\SystemRoot\\xefs.dat"

#if DBG
#define DEBUG_VOLUME						L'G'
#endif

typedef struct _FILE_CONTEXT
{
	PVOID FsContext;
	ULONG RefCount;
	BOOLEAN DecryptOnRead;
	BOOLEAN EncryptOnWrite;
	BOOLEAN EncryptFlagExist; // if encrypt flag file exists, then the file is encrypted
	BOOLEAN NeedEncrypt;
	KEVENT Event;
	WCHAR Name[MAX_PATH];
	UCHAR EncryptExtData[ENCRYPT_BIT_SIZE / sizeof(UCHAR)];
	
} FILE_CONTEXT, *PFILE_CONTEXT;

// 
// Device extension definition for our driver.  Note that the same extension
// is used for the following types of device objects:
//	- File system device object we attach to
//	- Mounted volume device objects we attach to
// 
typedef struct _SFILTER_DEVICE_EXTENSION
{
	// 
	// Pointer to the file system device object we are attached to
	// 
	PDEVICE_OBJECT AttachedToDeviceObject;

	// 
	// Pointer to the real (disk) device object that is associated with
	// the file system device object we are attached to
	// 
	PDEVICE_OBJECT StorageStackDeviceObject;

	// 
	// Name for this device.  If attached to a Volume Device Object it is the
	// name of the physical disk drive.  If attached to a Control Device
	// Object it is the name of the Control Device Object.
	// 
	UNICODE_STRING DeviceName;

	// 
	// Buffer used to hold the above unicode strings
	// 
	WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];

	WCHAR DriveLetter;

	RTL_GENERIC_TABLE FsCtxTable;
	FAST_MUTEX FsCtxTableMutex;
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;

// 
// This structure contains the information we need to pass to the completion
// processing for FSCTRLs.
// 
typedef struct _FSCTRL_COMPLETION_CONTEXT
{
	// 
	// The workitem that will be initialized with our context and 
	// worker routine if this completion processing needs to be completed
	// in a worker thread.
	// 
	WORK_QUEUE_ITEM WorkItem;

	// 
	// The device object to which this device is currently directed.
	// 
	PDEVICE_OBJECT DeviceObject;

	// 
	// The IRP for this FSCTRL operation.
	// 
	PIRP Irp;

	// 
	// For mount operations, the new device object that we have allocated
	// and partially initialized that we will attach to the mounted volume
	// if the mount is successful.
	// 
	PDEVICE_OBJECT NewDeviceObject;
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;

typedef struct _POST_CREATE_WORKER_CONTEXT
{
	WORK_QUEUE_ITEM WorkItem;
	KEVENT Event;
	PDEVICE_OBJECT DeviceObject;
	PFILE_OBJECT FileObject;
	PFILE_CONTEXT FileContext;
	BOOLEAN NewElement;
} POST_CREATE_WORKER_CONTEXT, *PPOST_CREATE_WORKER_CONTEXT;

typedef struct _READ_WRITE_COMPLETION_CONTEXT
{
	PMDL OldMdl;
	PVOID OldUserBuffer;
	PVOID OldSystemBuffer;
	
	PVOID OldBuffer;
	PVOID MyBuffer;
	ULONG Length;
} READ_WRITE_COMPLETION_CONTEXT, *PREAD_WRITE_COMPLETION_CONTEXT;

typedef struct _POST_SET_INFORMATION_WORKER_CONTEXT
{
	WORK_QUEUE_ITEM WorkItem;
	KEVENT Event;
	PDEVICE_OBJECT DeviceObject;
	PFILE_OBJECT FileObject;
	PFILE_CONTEXT FileContext;
	PWCHAR FileName;
	PWCHAR TargetFileName;
	BOOLEAN Delete;
} POST_SET_INFORMATION_WORKER_CONTEXT, *PPOST_SET_INFORMATION_WORKER_CONTEXT;

#define POLICY_NONE			0x0
#define POLICY_ENCRYPT		0x1
#define POLICY_END			0xFFFFFFFF

typedef struct _RULE
{
	ULONG Policy;
	WCHAR Pattern[MAX_PATH];
} RULE, *PRULE;

// 
// Macro to test if this is my device object
// 
#define IS_MY_DEVICE_OBJECT(_devObj) \
	(((_devObj) != NULL) && \
	 ((_devObj)->DriverObject == gSFilterDriverObject) && \
	  ((_devObj)->DeviceExtension != NULL))

// 
// Macro to test if this is my control device object
// 
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
	(((_devObj) == gSFilterControlDeviceObject) ? \
			(ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && \
					((_devObj)->DeviceExtension == NULL)), TRUE) : \
			FALSE)

// 
// Macro to test for device types we want to attach to
// 
#define IS_DESIRED_DEVICE_TYPE(_type) \
	(((_type) == FILE_DEVICE_DISK_FILE_SYSTEM) || \
	 ((_type) == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || \
	 ((_type) == FILE_DEVICE_NETWORK_FILE_SYSTEM))

// 
// Macro to test if FAST_IO_DISPATCH handling routine is valid
// 
#define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \
	(((_FastIoDispatchPtr) != NULL) && \
	 (((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
			(FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \
	 ((_FastIoDispatchPtr)->_FieldName != NULL))


#if WINVER >= 0x0501
// 
// MULTIVERSION NOTE:
// 
// If built in the Windows XP environment or later, we will dynamically import
// the function pointers for routines that were not supported on Windows 2000
// so that we can build a driver that will run, with modified logic, on 
// Windows 2000 or later.
// 
// Below are the prototypes for the function pointers that we need to 
// dynamically import because not all OS versions support these routines.
// 

typedef
NTSTATUS
(* PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS)(
	IN PDRIVER_OBJECT DriverObject,
	IN PFS_FILTER_CALLBACKS Callbacks
	);

typedef
NTSTATUS
(* PSF_ENUMERATE_DEVICE_OBJECT_LIST)(
	IN PDRIVER_OBJECT DriverObject,
	IN PDEVICE_OBJECT *DeviceObjectList,
	IN ULONG DeviceObjectListSize,
	OUT PULONG ActualNumberDeviceObjects
	);

typedef
NTSTATUS
(* PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE)(
	IN PDEVICE_OBJECT SourceDevice,
	IN PDEVICE_OBJECT TargetDevice,
	OUT PDEVICE_OBJECT *AttachedToDeviceObject
	);

typedef	
PDEVICE_OBJECT
(* PSF_GET_LOWER_DEVICE_OBJECT)(
	IN PDEVICE_OBJECT DeviceObject
	);

typedef
PDEVICE_OBJECT
(* PSF_GET_DEVICE_ATTACHMENT_BASE_REF)(
	IN PDEVICE_OBJECT DeviceObject
	);

typedef
NTSTATUS
(* PSF_GET_DISK_DEVICE_OBJECT)(
	IN PDEVICE_OBJECT FileSystemDeviceObject,
	OUT PDEVICE_OBJECT *DiskDeviceObject
	);

typedef
PDEVICE_OBJECT
(* PSF_GET_ATTACHED_DEVICE_REFERENCE)(
	IN PDEVICE_OBJECT DeviceObject
	);

typedef
NTSTATUS
(* PSF_GET_VERSION)(
	IN OUT PRTL_OSVERSIONINFOW VersionInformation
	);

typedef struct _SF_DYNAMIC_FUNCTION_POINTERS
{
	// 
	// The following routines should all be available on Windows XP (5.1) and
	// later.
	// 
	PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS RegisterFileSystemFilterCallbacks;
	PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE AttachDeviceToDeviceStackSafe;
	PSF_ENUMERATE_DEVICE_OBJECT_LIST EnumerateDeviceObjectList;
	PSF_GET_LOWER_DEVICE_OBJECT GetLowerDeviceObject;
	PSF_GET_DEVICE_ATTACHMENT_BASE_REF GetDeviceAttachmentBaseRef;
	PSF_GET_DISK_DEVICE_OBJECT GetDiskDeviceObject;
	PSF_GET_ATTACHED_DEVICE_REFERENCE GetAttachedDeviceReference;
	PSF_GET_VERSION GetVersion;
} SF_DYNAMIC_FUNCTION_POINTERS, *PSF_DYNAMIC_FUNCTION_POINTERS;

SF_DYNAMIC_FUNCTION_POINTERS gSfDynamicFunctions = {NULL};

// 
// MULTIVERSION NOTE: For this version of the driver, we need to know the
// current OS version while we are running to make decisions regarding what
// logic to use when the logic cannot be the same for all platforms.  We
// will look up the OS version in DriverEntry and store the values
// in these global variables.
// 
ULONG gSfOsMajorVersion = 0;
ULONG gSfOsMinorVersion = 0;

// 
// Here is what the major and minor versions should be for the various OS versions:
// 
// OS Name								 MajorVersion	MinorVersion
// ---------------------------------------------------------------------
// Windows 2000							 5				 0
// Windows XP							 5				 1
// Windows Server 2003					 5				 2
// 

#define IS_WINDOWS2000() \
	((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 0))

#define IS_WINDOWSXP() \
	((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 1))

#define IS_WINDOWSXP_OR_LATER() \
	(((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 1)) || \
	 (gSfOsMajorVersion > 5))

#define IS_WINDOWSSRV2003_OR_LATER() \
	(((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 2)) || \
	 (gSfOsMajorVersion > 5))

#endif


// 
// TAG identifying memory SFilter allocates
// 

#define SFLT_POOL_TAG			'tlFS'

// 
// This structure and these routines are used to retrieve the name of a file
// object.  To prevent allocating memory every time we get a name this
// structure contains a small buffer (which should handle 90+% of all names).
// If we do overflow this buffer we will allocate a buffer big enough
// for the name.
// 

typedef struct _GET_NAME_CONTROL
{
	PCHAR allocatedBuffer;
	CHAR smallBuffer[256];
} GET_NAME_CONTROL, *PGET_NAME_CONTROL;


PUNICODE_STRING
SfGetFileName(
	IN PFILE_OBJECT FileObject,
	IN NTSTATUS CreateStatus,
	IN OUT PGET_NAME_CONTROL NameControl
	);

VOID
SfGetFileNameCleanup(
	IN OUT PGET_NAME_CONTROL NameControl
	);

// 
// Macros for SFilter DbgPrint levels.
// 
#define SF_LOG_PRINT(_dbgLevel, _string)				  \
	(FlagOn(SfDebug,(_dbgLevel)) ?						  \
		DbgPrint _string  :								 \
		((void)0))

// 
// Delay values for KeDelayExecutionThread()
// (Values are negative to represent relative time)
// 
#define DELAY_ONE_MICROSECOND	(-10)
#define DELAY_ONE_MILLISECOND	(DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND		(DELAY_ONE_MILLISECOND*1000)


// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
// 
//					Global variables
// 
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /

// 
// Holds pointer to the driver object for this driver
// 
PDRIVER_OBJECT gSFilterDriverObject = NULL;

// 
// Holds pointer to the device object that represents this driver and is used
// by external programs to access this driver.  This is also known as the
// "control device object".
// 
PDEVICE_OBJECT gSFilterControlDeviceObject = NULL;

// 
// This lock is used to synchronize our attaching to a given device object.
// This lock fixes a race condition where we could accidently attach to the
// same device object more then once.  This race condition only occurs if
// a volume is being mounted at the same time as this filter is being loaded.
// This problem will never occur if this filter is loaded at boot time before
// any file systems are loaded.
// 
// This lock is used to atomically test if we are already attached to a given
// device object and if not, do the attach.
// 

⌨️ 快捷键说明

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