youngwinter
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分363分
  • 威望39点
  • 贡献值0点
  • 好评度38点
  • 原创分0分
  • 专家分0分
阅读:1746回复:5

请教:怎样才能不把密文写到cache里?

楼主#
更多 发布于:2007-03-20 21:11
  仿照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;
}

最新喜欢:

linshierlinshi...
yandong_8212
驱动小牛
驱动小牛
  • 注册日期2006-07-28
  • 最后登录2011-02-11
  • 粉丝0
  • 关注0
  • 积分1046分
  • 威望464点
  • 贡献值1点
  • 好评度173点
  • 原创分0分
  • 专家分1分
沙发#
发布于:2007-03-21 10:32
fastio
商务MSN:YanDong_8212@163.com
lsxredrain
驱动中牛
驱动中牛
  • 注册日期2006-08-31
  • 最后登录2008-10-18
  • 粉丝1
  • 关注0
  • 积分540分
  • 威望421点
  • 贡献值1点
  • 好评度420点
  • 原创分4分
  • 专家分0分
板凳#
发布于:2007-03-21 10:43
在SfCreate中加这句话,觉得不是Sfwrite和SfRead没有处理好,而是SfCreate中没有处理好,Sfwrite和SfRead是被动的,SfCreate才是主动的
 if(FileCtxPtr2->EncryptFlagExist && NewElement)
{
            LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject);
 }
JTIGER163
驱动牛犊
驱动牛犊
  • 注册日期2006-12-29
  • 最后登录2008-05-26
  • 粉丝0
  • 关注0
  • 积分240分
  • 威望25点
  • 贡献值0点
  • 好评度24点
  • 原创分0分
  • 专家分0分
地板#
发布于: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;
试试看。
驱网无线,快乐无限
youngwinter
驱动牛犊
驱动牛犊
  • 注册日期2004-08-23
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分363分
  • 威望39点
  • 贡献值0点
  • 好评度38点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-03-21 12:24
我想我明白怎么回事了。我仔细检查了一下,tooflat大牛原来的代码里,对于SfWrite的处理,是先备份原来的Mdl/SystemBuffer/UserBuffer,然后自己分配新的Mdl和buffer,进行加密的。我原来不理解是为什么,所以图简单直接在原来的缓冲区上加密了。现在看来,cache与IRP传入的缓冲区肯定存在某种对应关系,所以,为了不影响cache里的内容,必须自己另外分配缓冲区进行处理。刚才试了一下,果然再打开文件就OK了。这个问题,说到底是不理解cache manager的工作原理,现在虽然解决了,还是留有疑问的,比如,FileSystem和CacheManager到底是怎么交互的,文件内存映射的实现机理,FileObject->SectionObjectPointer里的DataSectionObject和ImageSectionObject到底是什么?还请知晓的大牛提点一二。
总之,多谢各位的帮助。
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
5楼#
发布于:2007-03-21 12:58
你需要看顶上的那本书,用了三章讲述 cache 管理部分,权威牛书.如果你已经有了,请仔细看看
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
游客

返回顶部