阅读:2446回复:4
请帮我一下.文件过滤驱动中的怪问题
我弄了一个文件过滤驱动,监视一个指定的目录,如果这个目录中,有数据发生了更改(写),就记录下来.
方法是:建立一个同名的目录,把当前改变的文件的内容,记录在这个同名目录下的同名文件中 我做出来后,测试复制,改写后保存,都是正常的. 现在遇上二个问题: 1、新建一个文件时(比如:新建excel文件,ACCESS文件),驱动拦截不到写操作。有点怪 2、当一个RAR文件,解压到当前目录时,发生错误。 我是用的SFILTER的源码进行改写的。增加了处理IRP_MJ_WRITE 第二个问题发生错误时,提示磁盘已满。我一段一段代码排除后,发现,是新建目录这段代码有问题,去掉后,就不会出错。反之,只有这一段代码时,也会出错。现发上这段代码。请各位高手指点一下。谢谢。。 第一个问题,我猜想可能是新建文件方法有点特别,请各位帮我一下。谢谢 _inline NTSTATUS MyCreateDirectory(UNICODE_STRING DirectoryName) { HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; UNICODE_STRING DirName; WCHAR Dirbuf[260]; NTSTATUS Status; RtlInitEmptyUnicodeString(&DirName,Dirbuf,260); RtlCopyUnicodeString(&DirName,&DirectoryName); InitializeObjectAttributes(&ObjectAttributes, &DirName, OBJ_KERNEL_HANDLE, NULL, NULL ); Status = ZwCreateFile(&FileHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_DIRECTORY_FILE +FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); ZwClose(FileHandle); return Status ; } _inline BOOLEAN MyCreate(UNICODE_STRING filename)///创建一个目录,可以创建多层, { NTSTATUS Status; UNICODE_STRING m_dir; WCHAR m_dir_buffer[260]; ULONG m_start; USHORT m_end=filename.Length/2; RtlInitEmptyUnicodeString(&m_dir,m_dir_buffer,260); Status=MyCreateDirectory(filename); if(Status==STATUS_SUCCESS) return TRUE; RtlCopyUnicodeString(&m_dir,&filename); for(m_start=7;m_start<m_end;m_start++) { if(filename.Buffer[m_start]=='\\') { m_dir.Length=(USHORT)m_start*2; m_dir.Buffer[(USHORT)m_start]=UNICODE_NULL; Status=MyCreateDirectory(m_dir); RtlCopyUnicodeString(&m_dir,&filename); } } Status=MyCreateDirectory(filename); if(Status==STATUS_SUCCESS) return TRUE; else return FALSE; } _inline NTSTATUS SaveFile (UNICODE_STRING filename,LARGE_INTEGER offset, ULONG length,PVOID m_buffer) { HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; NTSTATUS Status; UNICODE_STRING m_save_filename,m_temp,m_filename; WCHAR m_file_buffer[260]; WCHAR m_file_name[260]; PVOID m_save_buffer; FILE_END_OF_FILE_INFORMATION file_eof; if(KeGetCurrentIrql() != PASSIVE_LEVEL) { DbgPrint("Irp is not PASSIVE_LEVEL\n"); return FALSE; } RtlInitEmptyUnicodeString(&m_save_filename,m_file_buffer,260); RtlInitUnicodeString(&m_temp,L"\\??\\C:"); RtlCopyUnicodeString(&m_save_filename,&m_temp); RtlAppendUnicodeStringToString(&m_save_filename,&filename); MyCreate(m_save_filename);/////只要不要这一句,就不会出错。当然,也无法实现记录了 //////////创建当前显示文件格式 swprintf(m_file_name,L"\\%I64u+%d",offset.QuadPart,length); RtlInitUnicodeString(&m_filename,m_file_name); RtlAppendUnicodeStringToString(&m_save_filename,&m_filename); m_save_buffer=ExAllocatePoolWithTag(NonPagedPool,length,SF_POOL_TAG); RtlZeroMemory(m_save_buffer,length); RtlCopyMemory(m_save_buffer, m_buffer,length); InitializeObjectAttributes(&ObjectAttributes, &m_save_filename, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL ); Status = ZwCreateFile(&FileHandle, FILE_WRITE_DATA | SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (!NT_SUCCESS(Status)) { DbgPrint("open file %ws is error:%x\r\n",m_save_filename.Buffer,Status); ExFreePool(m_save_buffer); return Status; } file_eof.EndOfFile.QuadPart =(LONGLONG)length; Status = ZwSetInformationFile(FileHandle, &IoStatus, &file_eof, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation ); if (!NT_SUCCESS(Status)) { ExFreePool(m_save_buffer); ZwClose(FileHandle); return Status; } Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, &IoStatus, m_save_buffer, length, NULL, NULL ); ZwClose(FileHandle); ExFreePool(m_save_buffer); if (!NT_SUCCESS(Status)) { DbgPrint("save is :%x \r\n",Status); } return Status; } NTSTATUS SfWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; // PDEVICE_EXTENSION deviceExtension; // PDEVICE_OBJECT attachedDevice; UNICODE_STRING dosname; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = irpSp->FileObject; WCHAR nameBuf[260]; UNICODE_STRING name ; LARGE_INTEGER m_createlen; ULONG len; PVOID mdl; PUCHAR temp; PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension; 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_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); if (!DevExt->StorageStackDeviceObject||(!FileObject)) { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->AttachedToDeviceObject, Irp); } if (NT_SUCCESS(SfVolumeDeviceNameToDosName(&DevExt->DeviceName, &dosname))) { } else { IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } ///如果不是所监视盘 if(dosname.Buffer[0]!=LOCKDISK1&&dosname.Buffer[0]!=LOCKDISK2) { ExFreePool(dosname.Buffer); IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } ExFreePool(dosname.Buffer); RtlInitEmptyUnicodeString(&name,nameBuf,260); if(!SfDissectFileName(DeviceObject,Irp,&name))///取文件名 { IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } if(name.Buffer[1]=='$')//放过系统文件 { IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->AttachedToDeviceObject, Irp); } if(irpSp->Parameters.Write.Length!=0&&Irp->MdlAddress) { mdl = MmGetSystemAddressForMdl( Irp->MdlAddress );//得到写的缓冲区 if(mdl) {// KEVENT waitEvent; ////////复制出来保存一份,后面用 temp=ExAllocatePoolWithTag(NonPagedPool,irpSp->Parameters.Write.Length,SF_POOL_TAG); RtlZeroMemory(temp,irpSp->Parameters.Write.Length); RtlCopyMemory(temp, mdl,irpSp->Parameters.Write.Length); KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine( Irp, SfWriteCompletion, &waitEvent, TRUE, TRUE, TRUE ); m_createlen.QuadPart=irpSp->Parameters.Write.ByteOffset.QuadPart; status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject-> DeviceExtension)->AttachedToDeviceObject, Irp ); if (STATUS_PENDING == status) { KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); } if (Irp->IoStatus.Status==0) { len=Irp->IoStatus.Information; SaveFile(name,m_createlen,len,temp);/// //////把当前改变的内容保存下来 } else { DbgPrint("write file is error ,getlasterror is:%x\r\n" , Irp->IoStatus.Status); } ExFreePool(temp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return Irp->IoStatus.Status; } } IoSkipCurrentIrpStackLocation( Irp ); return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); } 程序在其它情况下,是正常的,就是在RAR解压时,和新建文件时,不正常。请各位高手帮我一下。谢谢 |
|
最新喜欢:![]() |
沙发#
发布于:2008-01-02 08:34
Office系列是重命名操作的。有可能先写到临时文件时,再重命名过去。你检查一下。
|
|
|
板凳#
发布于:2008-01-02 09:15
嗯.谢谢...那么第二个问题呢.那个RAR解压时,如果说新建文件夹(驱动中),就会出现磁盘已满的错误
是不是因为有缓冲区的原因... 请问一下,常说的刷新缓冲区的方法是怎么回事呀.谢谢..请各位指点一下. |
|
地板#
发布于:2008-01-02 10:29
第二个问题:一般像office或rar都使用了临时文件,可能这个临时文件在当前目录下(你的加密路径下)
此时这个临时文件被加密。 就会报磁盘已满(你过滤一下临时文件看看) 至于清cache正在研究。。。 |
|
|
地下室#
发布于:2008-01-02 17:07
呵,谢谢.不过,我没有加密路径,我只是把这些改写过的内容显示出来而已...
想不明白为什么..在显示中,如果说我不创建目录(在其它盘创建一个同名的目录),就不会出错了. 怪呀..麻烦你帮我看一下,是不是我创建目录的代码有错. |
|