阅读:1746回复:5
请教:怎样才能不把密文写到cache里?
仿照sfilter写的透明加解密驱动,对指定目录下的文件进行加解密。驱动加载起来后,拷贝一个文件到加密目录,新生成的文件能被加密,但再打开的时候看到的都是密文而不是明文。跟踪发现,在打开该新生成的文件的时候,没有收到IRP_MJ_READ的请求包。我认为可能是两种情况:1,IRP_MJ_READ被漏掉了,我觉得可能性比较小;2,处理IRP_MJ_WRITE的时候,密文被写到cache里去了,打开时直接从cache读的数据。但我的IRP_MJ_WRITE是参考tooflat牛的写的,而且只处理了IRP_NOCACHE、IRP_PAGING_IO和IRP_SYNCHRONOUS_PAGING_IO,理应不会错的。前两天一个大牛说可能是动态加载的缘故,我试过用静态加载,依然是这个样子。
这个问题困扰我好几天了,百思不得其解中,还请知情的大牛指点,万分感谢! 附:IRP_MJ_WRITE的相关处理代码: NTSTATUS SfWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PSfFILTER_DEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension; PFILE_OBJECT FileObject = IrpSp->FileObject; PFILE_CONTEXT FileContext; PFILE_CONTEXT TempContext; KEVENT WaitEvent; PVOID WriteBuffer = NULL; PVOID MyBuffer = NULL; ULONG Length = 0; PRC4_KEY CryptKey; BOOLEAN EncryptOnWrite; PAGED_CODE(); if (IS_MY_DEVICE_OBJECT(DeviceObject)) { // We only care about volume filter device object, other write request will pass through if (NULL == DevExt->StorageStackDeviceObject) { goto _ReturnAddress2; } // only IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO will be processed if (0 == (Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) { goto _ReturnAddress2; } // try to find opened entry in the table TempContext = ExAllocateFromPagedLookasideList(&gFileContextLookasideList); if (NULL == TempContext) { DbgPrint("[%s] [%u] ExAllocateFromPagedLookasideList() failed, memory exhausted!\n", __FILE__, __LINE__); goto _ReturnAddress2; } TempContext->FsContext = FileObject->FsContext; ExAcquireFastMutex(&DevExt->FsContextTableMutex); FileContext = RtlLookupElementGenericTable(&DevExt->FsContextTable, TempContext); ExReleaseFastMutex(&DevExt->FsContextTableMutex); ExFreeToPagedLookasideList(&gFileContextLookasideList, TempContext); if (NULL == FileContext) // not in the generic table, skip it { goto _ReturnAddress2; } if (IsFileNeedCrypt(DeviceObject, Irp, FileContext) == FALSE) // not in the specified directory { goto _ReturnAddress2; } // check decrypt flag when reading KeWaitForSingleObject(&FileContext->Event, Executive, KernelMode, FALSE, NULL); EncryptOnWrite = FileContext->EncryptOnWrite; KeSetEvent(&FileContext->Event, IO_NO_INCREMENT, FALSE); if (EncryptOnWrite == FALSE) { goto _ReturnAddress2; } Length = IrpSp->Parameters.Write.Length; DbgPrint("[%s] [%u] Try to write %u bytes from 0x%08X of file %s! FO=0x%08X\n", __FILE__, __LINE__, Length, IrpSp->Parameters.Write.ByteOffset.LowPart, FileContext->FullName.RealName, FileObject); // try encrypt data before write it CryptKey = ExAllocateFromNPagedLookasideList(&gCryptKeyLookasideList); if (NULL == CryptKey) { DbgPrint("[%s] [%u] ExAllocateFromNPagedLookasideList() failed, memory exhausted!\n", __FILE__, __LINE__); Status = STATUS_INSUFFICIENT_RESOURCES; goto _ReturnAddress1; } // allocate temporal buffer MyBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, SfFS_POOL_TAG); if (NULL == MyBuffer) { ExFreeToNPagedLookasideList(&gCryptKeyLookasideList, CryptKey); DbgPrint("[%s] [%u] ExAllocatePoolWithTag() failed, memory exhausted!\n", __FILE__, __LINE__); Status = STATUS_INSUFFICIENT_RESOURCES; goto _ReturnAddress1; } WriteBuffer = (Irp->MdlAddress) ? MmGetSystemAddressForMdl(Irp->MdlAddress) : Irp->UserBuffer; ASSERT(WriteBuffer); memcpy(CryptKey, gpCryptKey, sizeof(RC4_KEY)); memcpy(MyBuffer, WriteBuffer, Length); RC4(CryptKey, Length, (const PUCHAR)MyBuffer, (PUCHAR)WriteBuffer); ExFreePoolWithTag(MyBuffer, SfFS_POOL_TAG); ExFreeToNPagedLookasideList(&gCryptKeyLookasideList, CryptKey); // 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, SfWriteCompletion, &WaitEvent, TRUE, TRUE, TRUE); // Call the next driver in the stack. Status = IoCallDriver(DevExt->AttachedToDeviceObject, Irp); // Wait for the completion routine to be called if (STATUS_PENDING == Status) { ASSERT(STATUS_SUCCESS == KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL)); } // Verify the IoCompleteRequest was called ASSERT(KeReadStateEvent(&WaitEvent) != 0 || !NT_SUCCESS(Irp->IoStatus.Status)); // We don't care about failed requests if (!NT_SUCCESS(Irp->IoStatus.Status) || Irp->IoStatus.Status == STATUS_REPARSE) { DbgPrint("[%s] [%u] Write %u bytes from 0x%08X of file %s failed!\n", __FILE__, __LINE__, Irp->IoStatus.Information, IrpSp->Parameters.Write.ByteOffset.LowPart, FileContext->FullName.RealName); goto _ReturnAddress1; } DbgPrint("[%s] [%u] Write %u bytes from 0x%08X of file %s succeed! FO=0x%08X\n", __FILE__, __LINE__, Irp->IoStatus.Information, IrpSp->Parameters.Write.ByteOffset.LowPart, FileContext->FullName.RealName, FileObject); _ReturnAddress1: Status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; _ReturnAddress2: // Save the Status and continue processing the IRP IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->AttachedToDeviceObject, Irp); } if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) { DbgPrint("[%s] [%u] I(%wZ) received a request for %s!\n", __FILE__, __LINE__, &DEVICE_NAME, IRP_MJ_STRINGS[IrpSp->MajorFunction]); // Reset the Status & information of IRP Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } // Wrong device object, come here seems to be impossible Irp->IoStatus.Status = STATUS_INVALID_HANDLE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_HANDLE; } NTSTATUS SfWriteCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PKEVENT Event = Context; UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Irp); ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject)); KeSetEvent(Event, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; } |
|
最新喜欢:linshi... |
驱动小牛
|
沙发#
发布于:2007-03-21 10:32
fastio
|
|
板凳#
发布于:2007-03-21 10:43
在SfCreate中加这句话,觉得不是Sfwrite和SfRead没有处理好,而是SfCreate中没有处理好,Sfwrite和SfRead是被动的,SfCreate才是主动的
if(FileCtxPtr2->EncryptFlagExist && NewElement) { LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject); } |
|
地板#
发布于:2007-03-21 10:50
请把SfIssueReadWriteIrpSynchronously函数的Irp->Flags |= IrpFlags;改为
if (MajorFunction==IRP_MJ_READ) Irp->Flags = IRP_NOCACHE | IRP_READ_OPERATION; else Irp->Flags = IRP_NOCACHE | IRP_WRITE_OPERATION; 试试看。 |
|
|
地下室#
发布于:2007-03-21 12:24
我想我明白怎么回事了。我仔细检查了一下,tooflat大牛原来的代码里,对于SfWrite的处理,是先备份原来的Mdl/SystemBuffer/UserBuffer,然后自己分配新的Mdl和buffer,进行加密的。我原来不理解是为什么,所以图简单直接在原来的缓冲区上加密了。现在看来,cache与IRP传入的缓冲区肯定存在某种对应关系,所以,为了不影响cache里的内容,必须自己另外分配缓冲区进行处理。刚才试了一下,果然再打开文件就OK了。这个问题,说到底是不理解cache manager的工作原理,现在虽然解决了,还是留有疑问的,比如,FileSystem和CacheManager到底是怎么交互的,文件内存映射的实现机理,FileObject->SectionObjectPointer里的DataSectionObject和ImageSectionObject到底是什么?还请知晓的大牛提点一二。
总之,多谢各位的帮助。 |
|
5楼#
发布于:2007-03-21 12:58
你需要看顶上的那本书,用了三章讲述 cache 管理部分,权威牛书.如果你已经有了,请仔细看看
|
|
|