阅读:3765回复:15
请教:透明加解密驱动无法解密
各位路过的大牛大侠帮忙看一下,我参考toolfat大牛的sfilter做的透明加解密过滤驱动,现在加密没有问题,写入磁盘的是加密过的数据,但解密时却遇到麻烦。比如拷贝一个文件到加密目录,新生成的文件被正确加密了,但再打开时看到的都是密文,而不是明文;在加密目录下新建一个文件,也是这个样子。除非重起机器,重新加载驱动,再打开加密目录下的文件,看到的才是明文。一直不解其中原因,不知道是哪里错了,请各位知道原因的指点一二。
主要代码如下: NTSTATUS SfRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PSFILTER_DEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension; PFILE_OBJECT FileObject = IrpSp->FileObject; PFILE_CONTEXT FileContext; PFILE_CONTEXT TempContext; BOOLEAN DecryptOnRead; PAGED_CODE(); if (IS_MY_DEVICE_OBJECT(DeviceObject)) { // We only care about volume filter device object, other create request will pass through if (NULL == DevExt->StorageStackDeviceObject) { goto _ReturnAddress; } // 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 _ReturnAddress; } // 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 _ReturnAddress; } 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 _ReturnAddress; } if (IsFileNeedCrypt(DeviceObject, Irp, FileContext) == FALSE) // not in the specified directory { goto _ReturnAddress; } // check decrypt flag when reading KeWaitForSingleObject(&FileContext->Event, Executive, KernelMode, FALSE, NULL); DecryptOnRead = FileContext->DecryptOnRead; KeSetEvent(&FileContext->Event, IO_NO_INCREMENT, FALSE); if (DecryptOnRead == FALSE) { goto _ReturnAddress; } DbgPrint("[%s] [%u] Try to read %u bytes from 0x%08X of file %s! FO=0x%08X\n", __FILE__, __LINE__, IrpSp->Parameters.Read.Length, IrpSp->Parameters.Read.ByteOffset.LowPart, FileContext->FullName.RealName, FileObject); // 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, SfReadCompletion, NULL, TRUE, TRUE, TRUE); // Call the next driver in the stack. Status = IoCallDriver(DevExt->AttachedToDeviceObject, Irp); DbgPrint("[%s] [%u] Read %u bytes from 0x%08X of file %s succeed! FO=0x%08X\n", __FILE__, __LINE__, Irp->IoStatus.Information, IrpSp->Parameters.Read.ByteOffset.LowPart, FileContext->FullName.RealName, FileObject); return Status; _ReturnAddress: 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 SfReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PVOID ReadBuffer; PVOID MyBuffer = NULL; ULONG Length = 0; PRC4_KEY CryptKey; UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Context); ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject)); Length = IrpSp->Parameters.Read.Length; ReadBuffer = (Irp->MdlAddress) ? MmGetSystemAddressForMdl(Irp->MdlAddress) : Irp->UserBuffer; ASSERT(ReadBuffer); // try to decrypt it CryptKey = ExAllocateFromNPagedLookasideList(&gCryptKeyLookasideList); if (NULL == CryptKey) { DbgPrint("[%s] [%u] ExAllocateFromNPagedLookasideList() failed, memory exhausted!\n", __FILE__, __LINE__); return STATUS_INSUFFICIENT_RESOURCES; } Length = Irp->IoStatus.Information; // allocate temporal buffer MyBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, SF_POOL_TAG); if (NULL == MyBuffer) { ExFreeToNPagedLookasideList(&gCryptKeyLookasideList, CryptKey); DbgPrint("[%s] [%u] ExAllocatePoolWithTag() failed, memory exhausted!\n", __FILE__, __LINE__); return STATUS_INSUFFICIENT_RESOURCES; } memcpy(CryptKey, gpCryptKey, sizeof(RC4_KEY)); memcpy(MyBuffer, ReadBuffer, Length); RC4(CryptKey, Length, (const PUCHAR)MyBuffer, (PUCHAR)ReadBuffer); ExFreePoolWithTag(MyBuffer, SF_POOL_TAG); ExFreeToNPagedLookasideList(&gCryptKeyLookasideList, CryptKey); return STATUS_SUCCESS; } |
|
沙发#
发布于:2007-03-16 22:05
I think the problem may be in your MJ_WRITE routine. File cache is filled with encrypted data.
|
|
板凳#
发布于:2007-03-18 17:16
May be
|
|
|
地板#
发布于:2007-03-19 08:30
那请帮助看一下,我写的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 create 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; } |
|
地下室#
发布于:2007-03-19 09:13
必须静态安装好后才行,动态的不行.
|
|
|
5楼#
发布于:2007-03-19 16:45
引用第4楼wowocock于2007-03-19 09:13发表的“”: 继续请教,使用sfilter.inf修改后进行静态安装,结果重起后在DriverEntry()里的IoCreateDevice()出错,错误码STATUS_OBJECT_NAME_COLLISION,请问是什么原因啊?如何修改避免? |
|
6楼#
发布于:2007-04-06 21:30
请问你加密文件结尾怎么判断的呢??
|
|
7楼#
发布于:2007-04-08 21:47
我也遇到相同问题,哪位大牛能在给些建议啊
|
|
|
8楼#
发布于:2007-05-19 16:40
楼主用的是什么加密算法?
|
|
|
9楼#
发布于:2007-06-04 15:56
RC4加密算法是等长加密吗?
|
|
|
10楼#
发布于:2007-06-07 11:18
问题出在写函数中.
|
|
|
11楼#
发布于:2007-06-07 11:25
具体问题是WriteBuffer 所指向的区域的数据.
1.在加密之前它是明文. 2.向下写入硬盘后,WriteBuffer 所指的区域还必须恢复为明文,而不能为 密文. 3.否则,出现楼主的问题. 一句话Irp->Mdladdres or Irp->Userbuffer所指向的数据在加密之后要 进行还原为明文!!! |
|
|
12楼#
发布于:2007-06-07 11:27
在
// Wait for the completion routine to be called if (STATUS_PENDING == Status) { ASSERT(STATUS_SUCCESS == KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL)); } 之后加入还原的处理即可,当然一开如必须开一个buffer保存以前的明文. |
|
|
13楼#
发布于:2007-12-29 16:28
InitializeObjectAttributes的时候,要设置OBJ_OPENIF属性就可以了。
|
|
|
14楼#
发布于:2008-04-23 10:20
感谢jl2004,我也有同样的问题。 解决了
|
|
15楼#
发布于:2010-11-07 22:57
请问你是怎么解决的?
|
|