sc_wolf
驱动小牛
驱动小牛
  • 注册日期2006-09-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分35分
  • 威望278点
  • 贡献值1点
  • 好评度150点
  • 原创分0分
  • 专家分0分
阅读:2446回复:4

请帮我一下.文件过滤驱动中的怪问题

楼主#
更多 发布于:2008-01-01 22:03
我弄了一个文件过滤驱动,监视一个指定的目录,如果这个目录中,有数据发生了更改(写),就记录下来.
方法是:建立一个同名的目录,把当前改变的文件的内容,记录在这个同名目录下的同名文件中

我做出来后,测试复制,改写后保存,都是正常的.

现在遇上二个问题:
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解压时,和新建文件时,不正常。请各位高手帮我一下。谢谢

最新喜欢:

cnmv6cnmv6
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2008-01-02 08:34
Office系列是重命名操作的。有可能先写到临时文件时,再重命名过去。你检查一下。
驱网无线,快乐无限
sc_wolf
驱动小牛
驱动小牛
  • 注册日期2006-09-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分35分
  • 威望278点
  • 贡献值1点
  • 好评度150点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-01-02 09:15
嗯.谢谢...那么第二个问题呢.那个RAR解压时,如果说新建文件夹(驱动中),就会出现磁盘已满的错误

是不是因为有缓冲区的原因...

请问一下,常说的刷新缓冲区的方法是怎么回事呀.谢谢..请各位指点一下.
abc13271552
驱动小牛
驱动小牛
  • 注册日期2007-08-13
  • 最后登录2023-12-05
  • 粉丝0
  • 关注0
  • 积分34分
  • 威望552点
  • 贡献值0点
  • 好评度160点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2008-01-02 10:29
第二个问题:一般像office或rar都使用了临时文件,可能这个临时文件在当前目录下(你的加密路径下)
此时这个临时文件被加密。 就会报磁盘已满(你过滤一下临时文件看看)

至于清cache正在研究。。。
驱网无线,快乐无限
sc_wolf
驱动小牛
驱动小牛
  • 注册日期2006-09-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分35分
  • 威望278点
  • 贡献值1点
  • 好评度150点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-01-02 17:07
呵,谢谢.不过,我没有加密路径,我只是把这些改写过的内容显示出来而已...

想不明白为什么..在显示中,如果说我不创建目录(在其它盘创建一个同名的目录),就不会出错了.

怪呀..麻烦你帮我看一下,是不是我创建目录的代码有错.
游客

返回顶部