挂钩FSD实现文件隐藏

【文章标题】: 挂钩FSD实现文件隐藏
【文章作者】: index09
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  最近看Fastfat驱动想到的方法。查了一下又是被别人玩过了,还是简单说一下吧。
  当explorer进程查看文件夹信息时,会像卷对应的文件系统发送一个IRP
  MajorFunction == IRP_MJ_DIRECTORY_CONTROL
  MinorFunction == IRP_MN_QUERY_DIRECTORY
  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation
  当文件系统驱动完成这个请求时
  会在Irp->UserBuffer中返回FILE_BOTH_DIR_INFORMATION组成的数组。
  数组中有当前文件夹下的所有文件信息,我们只要把要隐藏的文件从这里面抹去就可以达到文件隐藏的目的了。
  
  挂载后我们的IRP_MJ_DIRECOTRY_CONTROL路径如下
  NTSTATUS
  DirectoryCtrlRoutineKernel(
                             IN PDEVICE_OBJECT DeviceObject,
                             IN PIRP Irp,
                             PDRIVER_DISPATCH DispRoutine
                             )
  {
      PIO_STACK_LOCATION IrpSp;
      PFILE_BOTH_DIR_INFORMATION fileInfos;
      WCHAR buffer[256];
      UNICODE_STRING uniDirName;
      BOOLEAN bGetDirName;
      PFILE_NAME_INFORMATION pFileNameInfo;
      NTSTATUS status;
      ULONG length, currentOffset;
  
      IrpSp = IoGetCurrentIrpStackLocation(Irp);
  
      ASSERT(IrpSp->MajorFunction == IRP_MJ_DIRECTORY_CONTROL);
  
      //只过滤用户态、FileBothDirectoryInformation请求
      if( Irp->RequestorMode == KernelMode ||
          IrpSp->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
          IrpSp->Parameters.QueryDirectory.FileInformationClass != FileBothDirectoryInformation)
          return DispRoutine(DeviceObject,
                             Irp);
  
      //获得目录名
      pFileNameInfo = (PFILE_NAME_INFORMATION)buffer;
      status = IrpGetFilePath(DeviceObject,
                              IrpSp->FileObject,
                              pFileNameInfo,
                              sizeof(buffer));
  
      //不能获得目录名不处理
      if(!NT_SUCCESS(status))
          return DispRoutine(DeviceObject,
                             Irp);
      uniDirName.Buffer = pFileNameInfo->FileName;
      uniDirName.Length = uniDirName.MaximumLength = pFileNameInfo->FileNameLength;
  
      //发送给下层驱动获得目录信息、若请求没完成不处理
      status = DispRoutine(DeviceObject, 
                           Irp);
      if(!NT_SUCCESS(status) ||
          status ==  STATUS_PENDING)
          return status;
  
      fileInfos = (PFILE_BOTH_DIR_INFORMATION)Irp->UserBuffer;
      DoFileNameFilter(DeviceObject,
                       &uniDirName,
                       fileInfos,
                       &Irp->IoStatus);
  
      status = Irp->IoStatus.Status;
      return status;
  }
  
  这里有一个问题——如何在这个函数中获得文件的全路径。这里只有目录中的文件名信息。
  但是如果我们想隐藏指定目录下的某个文件,我们还必须的到目录的路径。
  在这个函数中Irp->FileObject是当前目录的文件对象,可以利用这个对象一个IRP_MJ_QUERY_INFORMATION请求下发到Fsd来获得文件夹的路径。
  比较麻烦,不知还有没有其他简单的方法,请教各位大侠 :)
  代码如下:
  NTSTATUS
  IrpGetFilePath(
                 IN PDEVICE_OBJECT DeviceObject,
                 IN PFILE_OBJECT FileObject,
                 IN OUT PFILE_NAME_INFORMATION FileNameInfo,
                 IN ULONG Length
                 )
  {
      NTSTATUS status;
      PIRP irp;
      PIO_STACK_LOCATION irpSp;
      KEVENT event;
  
      if(DeviceObject == NULL ||
         FileObject == NULL ||
         FileNameInfo == NULL ||
         Length == 0)
         return STATUS_INVALID_PARAMETER;
  
      //申请一个IRP
      irp = IoAllocateIrp(DeviceObject->StackSize,
                          FALSE);
      if(irp == NULL)
      {
          KdPrint(("allocate irp fail.\n"));
          return STATUS_INSUFFICIENT_RESOURCES;
      }
  
      //填写IRP
      irpSp = IoGetNextIrpStackLocation(irp);
  
      irp->RequestorMode = KernelMode;
      irp->AssociatedIrp.SystemBuffer = FileNameInfo;
      irp->UserBuffer = NULL;
      irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
      irpSp->Parameters.QueryFile.FileInformationClass = FileNameInformation;
      irpSp->Parameters.QueryFile.Length = Length;
      irpSp->FileObject = FileObject;
  
      //使用完成回调实现同步IO
      KeInitializeEvent(&event,
                        NotificationEvent,
                        FALSE);
      IoSetCompletionRoutine(irp,
                             IrpCompleteRoutine,
                             &event,
                             TRUE,
                             TRUE,
                             TRUE);
  
      //下发请求并完成回调
      status = IoCallDriver(DeviceObject,
                            irp);
      if(status == STATUS_PENDING)
      {
          KeWaitForSingleObject(&event,
                                Executive,
                                KernelMode,
                                FALSE,
                                NULL);
      }
      status = irp->IoStatus.Status;
  
      //请求完毕
      IoFreeIrp(irp);
  
      return status;
  }
  
  然后就是一些简单的处理了,就不说了。
  有兴趣可以看看代码 :)
  代码可以隐藏根目录下的hahaha.txt文件(只是看不到,依然可以打开)
最后,这段代码只是过滤了FileBothDirectoryInformation消息,还有很多其它消息也可以获得文件名信息,如果想全面隐藏请一一过滤。
具体消息参考DDK 中的IRP_MJ_DIRECTORY_CONTROL :)
code: http://e.ys168.com/?index09 -> Code

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值