PDEVICE_OBJECT IoAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice );
------------ SourceDevice ------------ <-----AttachedDevice Filter2Device ------------ Filter1Device ------------ TargetDevice
IoAttachDevice() IoAttachDeviceToDeviceStackSafe(2000 SP4以及XP以上) IoAttachDeviceToDeviceStack()
!devobj 查看设备对象信息 !drvobj 查看驱动对象信息 !devstack 查看设备栈 !devnode 0 1 系统设备树
Filemon //不常见 不能动态监控移动设备 Sfilter //走在被淘汰的路上 Minifilter //未来主流 Filespy //不常见
Sfilter总体流程:
fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool, sizeof( FAST_IO_DISPATCH ), SFLT_POOL_TAG_FASTIO ); if (!fastIoDispatch) { IoDeleteDevice( gSFilterControlDeviceObject ); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) ); fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH ); fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible; fastIoDispatch->FastIoRead = SfFastIoRead; fastIoDispatch->FastIoWrite = SfFastIoWrite; fastIoDispatch->FastIoQueryBasicInfo = SfFastIoQueryBasicInfo; fastIoDispatch->FastIoQueryStandardInfo = SfFastIoQueryStandardInfo; fastIoDispatch->FastIoLock = SfFastIoLock; fastIoDispatch->FastIoUnlockSingle = SfFastIoUnlockSingle; fastIoDispatch->FastIoUnlockAll = SfFastIoUnlockAll; fastIoDispatch->FastIoUnlockAllByKey = SfFastIoUnlockAllByKey; fastIoDispatch->FastIoDeviceControl = SfFastIoDeviceControl; fastIoDispatch->FastIoDetachDevice = SfFastIoDetachDevice; fastIoDispatch->FastIoQueryNetworkOpenInfo = SfFastIoQueryNetworkOpenInfo; fastIoDispatch->MdlRead = SfFastIoMdlRead; fastIoDispatch->MdlReadComplete = SfFastIoMdlReadComplete; fastIoDispatch->PrepareMdlWrite = SfFastIoPrepareMdlWrite; fastIoDispatch->MdlWriteComplete = SfFastIoMdlWriteComplete; fastIoDispatch->FastIoReadCompressed = SfFastIoReadCompressed; fastIoDispatch->FastIoWriteCompressed = SfFastIoWriteCompressed; fastIoDispatch->MdlReadCompleteCompressed = SfFastIoMdlReadCompleteCompressed; fastIoDispatch->MdlWriteCompleteCompressed = SfFastIoMdlWriteCompleteCompressed; fastIoDispatch->FastIoQueryOpen = SfFastIoQueryOpen; DriverObject->FastIoDispatch = fastIoDispatch;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = SfPassThrough;//通用分发函数 下发IRP 私用IoSkip 和 IoCallDriver } // // We will use SfCreate for all the create operations // DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate; //DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate; //DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;//注意这个 当我们下面绑定了文件系统设备,我们就会收到这个IRP 在这个IRP处理函数中 我们就可以//绑定了卷设备对象了 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;
gSFilterDriverObject = DriverObject;
ExInitializeFastMutex( &gSfilterAttachLock ); // // Initialize the lookaside list for name buffering. This is used in // several places to avoid having a large name buffer on the stack. It is // also needed by the name lookup routines (NLxxx). // ExInitializePagedLookasideList( &gSfNameBufferLookasideList, NULL, NULL, 0, SFILTER_LOOKASIDE_SIZE, SFLT_POOL_TAG_NAME_BUFFER, 0 );
中创建,如果创建失败就在
"\\FileSystem\\SFilterDrv"
中创建
与NTMod不同的是 NTmodel中我们创建对象的时候对象是UNKNOW_DEVICE 这里我们创建的是磁盘文件系统设备RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters\\SFilterDrv" ); status = IoCreateDevice( DriverObject, 0, //has no device extension &nameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &gSFilterControlDeviceObject );//保存下来 后面判断是发给我们的驱动的还是发给文件系统的 if (status == STATUS_OBJECT_PATH_NOT_FOUND) { // // This must be a version of the OS that doesn't have the Filters // path in its namespace. This was added in Windows XP. // // We will try just putting our control device object in the // \FileSystem portion of the object name space. // RtlInitUnicodeString( &nameString, L"\\FileSystem\\SFilterDrv" ); status = IoCreateDevice( DriverObject, 0, //has no device extension &nameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &gSFilterControlDeviceObject ); if (!NT_SUCCESS( status )) { KdPrint( ("SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status )); return status; } } else if (!NT_SUCCESS( status )) { KdPrint(( "SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status )); return status; }
gSFilterControlDeviceObject->Flags |= DO_BUFFERED_IO; //gSFilterControlDeviceObject是我们保存的我们驱动的对象
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = SfPassThrough; } // // We will use SfCreate for all the create operations // //还有其他的 比如读写 改 删 /* FilterCreate(创建) FilterRead(一般不拦,加解密处理) FilterWrite(修改,加解密处理) FilterSetInfo(删,重命名) FilterClose(一般不拦) FilterClean(写关闭等) 等 */ DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate; //DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate; //DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate; ////注意这个 当我们下面绑定了文件系统设备,我们就会收到这个IRP 在这个IRP处理函数中 我们就可以//绑定了卷设备对象了 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;//卷设备绑定 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;
fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool, sizeof( FAST_IO_DISPATCH ), SFLT_POOL_TAG_FASTIO ); if (!fastIoDispatch) { IoDeleteDevice( gSFilterControlDeviceObject ); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) ); fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH ); fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible; fastIoDispatch->FastIoRead = SfFastIoRead; fastIoDispatch->FastIoWrite = SfFastIoWrite; fastIoDispatch->FastIoQueryBasicInfo = SfFastIoQueryBasicInfo; fastIoDispatch->FastIoQueryStandardInfo = SfFastIoQueryStandardInfo; fastIoDispatch->FastIoLock = SfFastIoLock; fastIoDispatch->FastIoUnlockSingle = SfFastIoUnlockSingle; fastIoDispatch->FastIoUnlockAll = SfFastIoUnlockAll; fastIoDispatch->FastIoUnlockAllByKey = SfFastIoUnlockAllByKey; fastIoDispatch->FastIoDeviceControl = SfFastIoDeviceControl; fastIoDispatch->FastIoDetachDevice = SfFastIoDetachDevice; fastIoDispatch->FastIoQueryNetworkOpenInfo = SfFastIoQueryNetworkOpenInfo; fastIoDispatch->MdlRead = SfFastIoMdlRead; fastIoDispatch->MdlReadComplete = SfFastIoMdlReadComplete; fastIoDispatch->PrepareMdlWrite = SfFastIoPrepareMdlWrite; fastIoDispatch->MdlWriteComplete = SfFastIoMdlWriteComplete; fastIoDispatch->FastIoReadCompressed = SfFastIoReadCompressed; fastIoDispatch->FastIoWriteCompressed = SfFastIoWriteCompressed; fastIoDispatch->MdlReadCompleteCompressed = SfFastIoMdlReadCompleteCompressed; fastIoDispatch->MdlWriteCompleteCompressed = SfFastIoMdlWriteCompleteCompressed; fastIoDispatch->FastIoQueryOpen = SfFastIoQueryOpen; DriverObject->FastIoDispatch = fastIoDispatch;
FS_FILTER_CALLBACKS fsFilterCallbacks; if (NULL != gSfDynamicFunctions.RegisterFileSystemFilterCallbacks) { // // Setup the callbacks for the operations we receive through // the FsFilter interface. // // NOTE: You only need to register for those routines you really // need to handle. SFilter is registering for all routines // simply to give an example of how it is done. // fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS ); fsFilterCallbacks.PreAcquireForSectionSynchronization = SfPreFsFilterPassThrough; fsFilterCallbacks.PostAcquireForSectionSynchronization = SfPostFsFilterPassThrough; fsFilterCallbacks.PreReleaseForSectionSynchronization = SfPreFsFilterPassThrough; fsFilterCallbacks.PostReleaseForSectionSynchronization = SfPostFsFilterPassThrough; fsFilterCallbacks.PreAcquireForCcFlush = SfPreFsFilterPassThrough; fsFilterCallbacks.PostAcquireForCcFlush = SfPostFsFilterPassThrough; fsFilterCallbacks.PreReleaseForCcFlush = SfPreFsFilterPassThrough; fsFilterCallbacks.PostReleaseForCcFlush = SfPostFsFilterPassThrough; fsFilterCallbacks.PreAcquireForModifiedPageWriter = SfPreFsFilterPassThrough; fsFilterCallbacks.PostAcquireForModifiedPageWriter = SfPostFsFilterPassThrough; fsFilterCallbacks.PreReleaseForModifiedPageWriter = SfPreFsFilterPassThrough; fsFilterCallbacks.PostReleaseForModifiedPageWriter = SfPostFsFilterPassThrough; status = (gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)( DriverObject, &fsFilterCallbacks ); if (!NT_SUCCESS( status )) { DriverObject->FastIoDispatch = NULL; ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG_FASTIO ); IoDeleteDevice( gSFilterControlDeviceObject ); return status; } }
status = IoRegisterFsRegistrationChange( DriverObject, SfFsNotification );//在里面绑定文件系统设备,也是卷设备绑定的前提条件 if (!NT_SUCCESS( status )) { KdPrint(( "SFilter!DriverEntry: Error registering FS change notification, status=%08x\n", status )); DriverObject->FastIoDispatch = NULL; ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG_FASTIO ); IoDeleteDevice( gSFilterControlDeviceObject ); return status; }
/* IoGetDeviceObjectPointer函数的功能是: 它从下层的设备对象名称来获得下层设备指针。该函数造成了对下层设备对象以及下层设备对象所对应的文件对象的引用。 如果本层驱动在卸载之前对下层的设备对象的引用还没有消除,则下层驱动的卸载会被停止。因此必须要消除对下层设备对象的引用。 但是程序一般不会直接对下层设备对象的引用减少。因此只要减少对文件对象的引用就可以减少文件对象和设备对象两个对象的引用。 事实上,IoGetDeviceObjectPointer返回的并不是下层设备对象的指针,而是该设备堆栈中顶层的设备对象的指针。 IoGetDeviceObjectPointer函数的调用必须在 IRQL=PASSIVE_LEVEL的级别上运行。 */ { PDEVICE_OBJECT rawDeviceObject; PFILE_OBJECT fileObject; // // Attach to RawDisk device // RtlInitUnicodeString( &nameString, L"\\Device\\RawDisk" ); status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject ); if (NT_SUCCESS( status )) { SfFsNotification( rawDeviceObject, TRUE );//绑定RawDisk 激活这个设备 然后被我们捕捉到,绑定过滤设备 ObDereferenceObject( fileObject ); } // // Attach to the RawCdRom device // RtlInitUnicodeString( &nameString, L"\\Device\\RawCdRom" ); status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject ); if (NT_SUCCESS( status )) { SfFsNotification( rawDeviceObject, TRUE );//同上 ObDereferenceObject( fileObject ); } } // // Clear the initializing flag on the control device object since we // have now successfully initialized everything. // ClearFlag( gSFilterControlDeviceObject->Flags, DO_DEVICE_INITIALIZING ); DbgPrint("Sfilter installed\n"); return STATUS_SUCCESS; }
{ PNAME_CONTROL devName; PAGED_CODE(); // // Display the names of all the file system we are notified of // devName = NLGetAndAllocateObjectName( DeviceObject, &gSfNameBufferLookasideList ); if (devName == NULL) { SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES, ("SFilter!SfFsNotification: Not attaching to %p, insufficient resources.\n", DeviceObject) ); return; } SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES, ("SFilter!SfFsNotification: %s %p \"%wZ\" (%s)\n", (FsActive) ? "Activating file system " : "Deactivating file system", DeviceObject, &devName->Name, GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) ); // // Handle attaching/detaching from the given file system. // if (FsActive) { SfAttachToFileSystemDevice( DeviceObject, devName ); } else { SfDetachFromFileSystemDevice( DeviceObject ); } // // We're done with name (SfAttachToFileSystemDevice copies the name to // the device extension) so free it. // NLFreeNameControl( devName, &gSfNameBufferLookasideList ); }
这个绑定了文件设备对象,这时我们就可以收到IRP_MJ_FILE_SYSTEM_CONTROL IRP 在这个例程里我们就可以实现对卷的绑定
(注意 这里必须绑定了文件设备后才能收到哦)
看下IRP_MJ_FILE_SYSTEM_CONTROL的例程switch (irpSp->MinorFunction) { case IRP_MN_MOUNT_VOLUME://设备在Mount的时候,我们就要进行绑定了 return SfFsControlMountVolume( DeviceObject, Irp ); case IRP_MN_LOAD_FILE_SYSTEM: return SfFsControlLoadFileSystem( DeviceObject, Irp ); case IRP_MN_USER_FS_REQUEST: { switch (irpSp->Parameters.FileSystemControl.FsControlCode) { case FSCTL_DISMOUNT_VOLUME: { PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension; SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES, ("SFilter!SfFsControl: Dismounting volume %p \"%wZ\"\n", devExt->NLExtHeader.AttachedToDeviceObject, &devExt->NLExtHeader.DeviceName) ); break; } } break; } } // // Pass all other file system control requests through. // IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject, Irp ); }
NTSTATUS SfCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This function filters create/open operations. It simply establishes an I/O completion routine to be invoked if the operation was successful. Arguments: DeviceObject - Pointer to the target device object of the create/open. Irp - Pointer to the I/O Request Packet that represents the operation. Return Value: The function value is the status of the call to the file system's entry point. --*/ { NTSTATUS status; PNAME_CONTROL fileName = NULL; PSFILTER_DEVICE_EXTENSION devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension); PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); BOOLEAN cacheName; 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.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; //return STATUS_SUCCESS; } ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); // // If debugging is enabled, do the processing required to see the packet // upon its completion. Otherwise, let the request go with no further // processing. // if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION | SFDEBUG_GET_CREATE_NAMES| SFDEBUG_DISPLAY_CREATE_NAMES )) { // // We don't want to get filenames, display filenames, or // call our completion routine. Don't put us on the stack // and call the next driver. // //如果是Deug 就不显示 直接下发 IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject, Irp ); } //如果要显示一下信息 if (FlagOn( SfDebug, SFDEBUG_GET_CREATE_NAMES | SFDEBUG_DISPLAY_CREATE_NAMES ) && !FlagOn(devExt->Flags,SFDEVFL_DISABLE_VOLUME)) { // // Debugging specifies that we need to get the filename // NAME_LOOKUP_FLAGS LookupFlags = 0x00000000; // // If DosName has been set, indicate via flags that we // want to use it when getting the full file name. // if (devExt->NLExtHeader.DosName.Length != 0) { SetFlag( LookupFlags, NLFL_USE_DOS_DEVICE_NAME ); } // // Indicate we are in pre-create // SetFlag( LookupFlags, NLFL_IN_CREATE ); if (FlagOn( irpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID )) { // // The file is being opened by ID, not file name. // SetFlag( LookupFlags, NLFL_OPEN_BY_ID ); } if (FlagOn( irpSp->Flags, SL_OPEN_TARGET_DIRECTORY )) { // // The file's parent directory should be opened // SetFlag( LookupFlags, NLFL_OPEN_TARGET_DIR ); } // // Retrieve the file name. Note that in SFilter we don't do any name // caching. // //申请存储数据的空间 status = NLAllocateNameControl( &fileName, &gSfNameBufferLookasideList ); if (NT_SUCCESS( status )) { // // We are okay not checking the return value here because // the GetFullPathName function will set the Unicode String // length to 0. So either way, in an error it will print an empty string // //拿到文件的全路径 status = NLGetFullPathName( irpSp->FileObject, fileName, &devExt->NLExtHeader, LookupFlags, &gSfNameBufferLookasideList, &cacheName ); } } //往下发 if (FlagOn( SfDebug, SFDEBUG_DISPLAY_CREATE_NAMES | SFDEBUG_DO_CREATE_COMPLETION ) && !FlagOn(devExt->Flags,SFDEVFL_DISABLE_VOLUME)) { // // Debugging flags indicate we must do completion. // Note that to display file names we must do completion // because we don't know IoStatus.Status and IoStatus.Information // until post-create. // KEVENT waitEvent; // // Initialize an event to wait for the completion routine to occur // KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); // // Copy the stack and set our Completion routine // 设置完成例程 IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine( Irp, SfCreateCompletion, &waitEvent, TRUE, TRUE, TRUE ); // // Call the next driver in the stack. // status = IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, Irp ); // // Wait for the completion routine to be called // if (STATUS_PENDING == status) { NTSTATUS localStatus = KeWaitForSingleObject( &waitEvent, Executive, KernelMode, FALSE, NULL ); ASSERT(STATUS_SUCCESS == localStatus); } // // Verify the IoCompleteRequest was called // ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status)); // // If debugging indicates we should display file names, do it. // //打印信息 if (irpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID) { SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES, ("SFilter!SfCreate: OPENED fo=%p %08x:%08x %wZ (FID)\n", irpSp->FileObject, Irp->IoStatus.Status, Irp->IoStatus.Information, &fileName->Name) ); } else { SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES, ("SFilter!SfCreate: OPENED fo=%p st=%08x:%08x %wZ\n", irpSp->FileObject, Irp->IoStatus.Status, Irp->IoStatus.Information, &fileName->Name) ); } // // Release the name control structure if we have // if (fileName != NULL) { NLFreeNameControl( fileName, &gSfNameBufferLookasideList ); } // // Save the status and continue processing the IRP // status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } else { // // Free the name control if we have one // if (fileName != NULL) { NLFreeNameControl( fileName, &gSfNameBufferLookasideList ); } // // Debugging flags indicate we did not want to display the file name // or call completion routine. // (ie SFDEBUG_GET_CREATE_NAMES && !SFDEBUG_DO_CREATE_COMPLETION) // IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject, Irp ); } }
NTSTATUS CommonDispatch( PDEVICE_OBJECT DeviceObject, PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; }
NTSTATUS SfPassThrough ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION pIrp = IoGetCurrentIrpStackLocation( Irp ); ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject )); ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); if (!IS_MY_DEVICE_OBJECT(DeviceObject) || IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { NTSTATUS status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject, Irp ); }
FilterCreate(创建) FilterRead(一般不拦,加解密处理) FilterWrite(修改,加解密处理) FilterSetInfo(删,重命名) FilterClose(一般不拦) FilterClean(写关闭等)等
#define IS_MY_DEVICE_OBJECT(_devObj) \ (((_devObj) != NULL) && \ ((_devObj)->DriverObject == gSFilterDriverObject) && \ ((_devObj)->DeviceExtension != NULL)) #define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \ (((_devObj) == gSFilterControlDeviceObject) ? \ (ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && \ ((_devObj)->DeviceExtension == NULL)), TRUE) : \ FALSE) #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))
NTSTATUS FilterXXX(PDEVICE_OBJECT DeviceObject, PIRP pIrp)//过滤设备 { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInfomation = 0; IO_STACK_LOCATION* lpIrpStack = IoGetCurrentIrpStackLocation(pIrp); if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))//控制设备 { //如果需要与R3交互,这里必须返回成功 pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = ulInfomation; IoCompleteRequest(lpIrp, IO_NO_INCREMENT); } else if (!IS_MY_DEVICE_OBJECT(DeviceObject)) { //非法参数 pIrp->IoStatus.Status = Status = STATUS_INVALID_PARAMETER; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } else { //这里才是我们要过滤的操作 IoSkipCurrentIrpStackLocation( pIrp ); Status = IoCallDriver(((PSFILTER_DEVICE_EXTENSION)->DeviceExtension)DeviceObject->NLExtHeader.AttachedToDeviceObject, pIrp); } return Status; }
GroupOrder:"FSFilter Activity Monitor“ L\\FileSystem\\SFilterDrv DeviceObjectFlags |= DO_BUFFERED_IO
Irp->RequestorMode == KernelMode本进程的
FilterDeviceIoctrl中 PsGetCurrentProcessId()系统进程的
DriverEntry里:PsGetCurrentProcessId()文件夹
ulOptions = IrpStack->Parameters.Create.Options ; FlagOn(IrpStack->FileObject->Flags, FO_VOLUME_OPEN) || FlagOn(ulOptions, FILE_DIRECTORY_FILE) || FlagOn(IrpStack->Flags, SL_OPEN_PAGING_FILE)分页IO
(Irp->Flags & IRP_PAGING_IO) || (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO) KeGetCurrentIrql() > APC_LEVEL如何放?
IoSkipCurrentIrpStackLocation( lpIrp ); IoCallDriver();
NTSTATUS sfSetInformation(PDEVICE_OBJECT lpDevice, PIRP lpIrp) { NTSTATUS Status = STATUS_SUCCESS; ULONG ulInfomation = 0; UNICODE_STRING ustrRule = {0}; PLIST_ENTRY CurrentList = NULL; USER_RESULT R3UserResult = User_Pass; PNAME_CONTROL lpNameControl = NULL; BOOLEAN bSkipped = FALSE; BOOLEAN bNeedPostOp = FALSE; BOOLEAN bRename = FALSE; IO_STACK_LOCATION *lpIrpStack = IoGetCurrentIrpStackLocation(lpIrp); PFILE_OBJECT lpFileObject = lpIrpStack->FileObject; PTWOWAY pTwoWay = NULL; WCHAR *szOper = NULL; if (IS_MY_CONTROL_DEVICE_OBJECT(lpDevice)) { lpIrp->IoStatus.Status = Status; lpIrp->IoStatus.Information = ulInfomation; IoCompleteRequest(lpIrp, IO_NO_INCREMENT); return Status; } else if (!IS_MY_DEVICE_OBJECT(lpDevice)) { lpIrp->IoStatus.Status = Status = STATUS_INVALID_PARAMETER; lpIrp->IoStatus.Information = 0; IoCompleteRequest(lpIrp, IO_NO_INCREMENT); return Status; } else { PSFILTER_DEVICE_EXTENSION lpDevExt = (PSFILTER_DEVICE_EXTENSION)(lpDevice->DeviceExtension); if (PsGetCurrentProcessId() == g_hSystemProcID) { bSkipped = TRUE; goto _EXIT; } //从HASH表中获得文件名 pTwoWay = Find((DWORD)lpFileObject, g_pHashTable); if (pTwoWay == NULL) { bSkipped = TRUE; goto _EXIT; } lpNameControl = pTwoWay->data.lpNameControl; if (lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation || lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation || lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation || lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation) { switch (lpIrpStack->Parameters.SetFile.FileInformationClass) { case FileAllocationInformation: case FileEndOfFileInformation: szOper = L"设置大小"; bSkipped = TRUE; goto _EXIT; // break; case FileRenameInformation: szOper = L"重命名"; break; case FileBasicInformation: szOper = L"设置基础信息"; bSkipped = TRUE; goto _EXIT; //break; case FileDispositionInformation: bNeedPostOp = TRUE; szOper = L"删除"; break; } } else { // 允许 bSkipped = TRUE; goto _EXIT; } RtlInitUnicodeString(&ustrRule, L"C:\\WINDOWS\\SYSTEM32\\*\\*.SYS"); if (!IsPatternMatch(&ustrRule, &lpNameControl->Name, TRUE)) { bSkipped = TRUE; goto _EXIT; } if (lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation) { //重命名的目标路径? } R3UserResult = hipsGetResultFromUser(szOper, lpNameControl->Name.Buffer, NULL, User_DefaultNon); if (R3UserResult == User_Block) { // 禁止 lpIrp->IoStatus.Information = 0; lpIrp->IoStatus.Status = STATUS_ACCESS_DENIED; IoCompleteRequest(lpIrp, IO_NO_INCREMENT); Status = STATUS_ACCESS_DENIED; bSkipped = FALSE; goto _EXIT; } bSkipped = TRUE; } _EXIT: if (bSkipped) { KEVENT waitEvent; IoCopyCurrentIrpStackLocationToNext(lpIrp); KeInitializeEvent(&waitEvent, NotificationEvent, FALSE); IoSetCompletionRoutine(lpIrp, SetFilterCompletion, &waitEvent, TRUE, TRUE, TRUE); Status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)lpDevice->DeviceExtension)->NLExtHeader.AttachedToDeviceObject, lpIrp); if (Status == STATUS_PENDING) { Status = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); } Status = lpIrp->IoStatus.Status; IoCompleteRequest(lpIrp, IO_NO_INCREMENT); } return Status; }