slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
阅读:4237回复:13

总结:关于文件夹地隐藏。

楼主#
更多 发布于:2004-02-07 22:22
1、返回的列表中只有一项并且这一项就是需要隐藏的项同时ReturnSingleEntry又为TRUE时怎么办?

  1)、Coolice采用重新调用ZwQueryDirectoryFile()的方法,不过这种方法需要考虑重入问题。
  2)、VCMFC通过对根目录进行特别处理来实现隐藏,不过他没有给出代码,具体方法我也不清楚。

  还有另外一种的方法,那就是重新构造IRP查询。Coolice也提到了这种方法,不过他也没有代码。OK,下面就是这种方法的代码:

  //
  // 执行隐藏操作
  //
  bool bNeedReQuery;
  bool bReturnSingleEntry;

  bReturnSingleEntry = ((IrpStack->Flags & SL_RETURN_SINGLE_ENTRY)
              == SL_RETURN_SINGLE_ENTRY
              );

  while(true)
  {  
    //
    // 在SfHideFile()中判断是否符合上述条件,如果符合则设置bNeedReQuery为TRUE然后直接返回。
    //
    Status = SfHideFile(
          &FullDirName,
          Irp->UserBuffer,
          IrpStack->Parameters.QueryFile.Length,
          bReturnSingleEntry,
          &bNeedReQuery
          );
    if(!bNeedReQuery)
    {
      break;
    }

    //
    // 如果欲隐藏的文件恰好是第一项,这时候只能通过重新查询来实现隐藏。
    //
    Status = SfReissueIrp(Irp,DeviceObject->StackSize + 2,DevExt);
    if(Status != STATUS_SUCCESS)
    {
      break;
    }
  }


  //---------------------------------------------------------------------------
  //
  // 构造新的IRP来继续查询
  //
  NTSTATUS
  SfReissueIrp(
    IN PIRP Irp,
    IN int StackSize,
    IN PSFILTER_DEVICE_EXTENSION DevExt
    )
  {
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpStack;
    PIRP NewIrp;
    PIO_STACK_LOCATION NextIrpStack;

    NewIrp = IoAllocateIrp(StackSize,false);
    if(NewIrp != NULL)
    {
      //
      // 设置同步事件
      //
      KEVENT WaitEvent;

      KeInitializeEvent(&WaitEvent,SynchronizationEvent,false);
  
      //
      // 设置IRP
      //
      NewIrp->UserEvent = NULL;
  
      NewIrp->AssociatedIrp.SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
      NewIrp->UserBuffer = Irp->UserBuffer;

      NewIrp->Tail.Overlay.Thread = PsGetCurrentThread();
      NewIrp->RequestorMode = Irp->RequestorMode;
      NewIrp->Flags = Irp->Flags & (~IRP_ASSOCIATED_IRP);
  
      //
      // 设置IO堆栈
      //
      IrpStack = IoGetCurrentIrpStackLocation(Irp);
      NextIrpStack = IoGetNextIrpStackLocation(NewIrp);
  
      *NextIrpStack = *IrpStack;
  
      NextIrpStack->CompletionRoutine = SfDirectoryControlCompletion;
      NextIrpStack->Context = &WaitEvent;
  
      //
      // 发送新的IRP到下层FSD
      //
      Status = IoCallDriver(DevExt->AttachedToDeviceObject,NewIrp);
      if(Status == STATUS_PENDING)
      {
        KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL);
  
        Status = NewIrp->IoStatus.Status;
      }

      //
      // 释放IRP
      //
      IoFreeIrp(NewIrp);
    }
    else
    {
      Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return Status;
  }


2、那就是要隐藏的文件在返回缓冲中不是第一项时怎么隐藏?

  我使用“隐藏”来搜索了本分论坛的贴子,在有关隐藏文件夹地讨论中,发现几乎99.9999%的FSFD Writer都使用与VCMFC相同的方法,那就是不停的Move Memory …:),实际上除了第一项需要Move以外,后面所有项地隐藏都是不需要Move的,直接更改一个ULONG值就可以了,一律Move只会对系统性能产生影响。虽然现在CPU已经是2、3、4G了(Sorry,具体是多少不清楚),不过追求最好的性能应该是一个程序员最基本的追求吧?

  //
  // 1、第一项匹配
  //
  if(...)
  {
  }

  //
  // 2:最后一项匹配
  //
  else if(pDirInfo->NextEntryOffset == 0)
  {
    pPrevDirInfo->NextEntryOffset = 0;
  }

  //
  // 3:中间项匹配
  //
  else
  {
    //
    // 隐藏中间项目时不需要调整pPrevDirInfo的值
    //
    bMustAdjustPrevDirInfo = false;

    pPrevDirInfo->NextEntryOffset += pDirInfo->NextEntryOffset;
  }

  //
  // ........ // Do something here
  //

  //
  // 是否需要调整pPrevDirInfo的值?(隐藏中间项目时不需要)
  //
  if(bMustAdjustPrevDirInfo)
  {
    pPrevDirInfo = pDirInfo;
  }

  pDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)pDirInfo + pDirInfo->NextEntryOffset);


3、最最重要的一点,那就是我上面的贴出的代码是不能直接Copy & Paste & Compile的,其中道理我想你自己应该明白。


2004-1-30开始学习文件系统驱动开发,直接着手的第一个问题就是把以前通过Hook ZwQueryDirectoryFile()来实现文件夹隐藏的驱动重新使用FSFD来实现。说来惭愧,使用了8天时间才彻底搞定。

题外话:SFilter在2K上面也是可以动态加载的,使用一些Trick就可以了。如果老是只听MS的那些工程师的话,那玩驱动编程岂不是少了许多乐趣?

最后,如果你认为我的总结对你还有一个点帮助,就请up一个这个贴子



[编辑 -  2/7/04 by  slwqw]

[编辑 -  2/7/04 by  slwqw]

最新喜欢:

gongliyugongli... cyliucyliu
freducn2002
驱动小牛
驱动小牛
  • 注册日期2002-06-26
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分11分
  • 威望29点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2004-02-08 10:39
ding
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
板凳#
发布于:2004-02-09 09:20
不错,希望老兄能多一些这样的总结经验。。。。。。
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-02-09 09:29
不需要重新构造一个irp,只需要把原来的irp往下传就可以了
nustzhua
驱动中牛
驱动中牛
  • 注册日期2002-06-19
  • 最后登录2015-09-27
  • 粉丝0
  • 关注0
  • 积分18分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-02-09 09:37
第2点比较好。
up,up,up.
不限容量的免费邮箱 www.k65.net
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-02-09 10:03
不需要重新构造一个irp,只需要把原来的irp往下传就可以了


我试过了这种方法,结果产生了MULTIPLE_REQUEST_COMPLETION BugCheck,也就是说IRP被完成了两次。如果要解决这个问题那还得做别地处理。不如重新构造一个IRP方便,不用考虑那么多。
vcmfc
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-01-28
  • 粉丝0
  • 关注0
  • 积分528分
  • 威望53点
  • 贡献值0点
  • 好评度52点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-02-11 12:49
我以前是用move.


你的方法是不是参考rootkit的hide process ?,它也是修改其Offset,是个好方法。
vcmfc
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-01-28
  • 粉丝0
  • 关注0
  • 积分528分
  • 威望53点
  • 贡献值0点
  • 好评度52点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-02-11 12:50
其实最大的损耗不在这里,在匹配规则表的时间,那将是最大的地方。
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-02-11 18:06
其实最大的损耗不在这里,在匹配规则表的时间,那将是最大的地方。


同意!

假设一个目录下面存在50项,需要隐藏其中的4项,最坏情况下需要匹配“49 + 48 + 47 + 46”次,实在受不了 :( :( :(

如果待隐藏的目录或者文件中“不包含通配符”,则使用多模式字符串匹配算法,可以避免这个问题,最多只比较50次即可。

只是不使用通配符又不太现实,烦啊...
super9
驱动牛犊
驱动牛犊
  • 注册日期2008-08-06
  • 最后登录2009-04-29
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望99点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2008-08-25 19:47
感觉很抽象,略懂
dreamsity
驱动小牛
驱动小牛
  • 注册日期2006-09-01
  • 最后登录2013-07-04
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望821点
  • 贡献值1点
  • 好评度68点
  • 原创分1分
  • 专家分0分
10楼#
发布于:2008-08-28 20:06
MULTIPLE_REQUEST_COMPLETION
这个是完成例程的返回值没有处理正确引起的。
一切都是时间问题!
alwaysrun
驱动小牛
驱动小牛
  • 注册日期2006-06-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1059分
  • 威望752点
  • 贡献值1点
  • 好评度98点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2008-09-02 09:48
学习了
一颗平常的心!
yuanyuan
驱动大牛
驱动大牛
  • 注册日期2003-01-15
  • 最后登录2010-08-04
  • 粉丝0
  • 关注0
  • 积分1025分
  • 威望300点
  • 贡献值0点
  • 好评度232点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2008-09-03 13:54
过几天我把我的代码贴出来,今天出差
generalos
驱动牛犊
驱动牛犊
  • 注册日期2008-10-23
  • 最后登录2011-04-20
  • 粉丝0
  • 关注0
  • 积分63分
  • 威望477点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2009-01-21 22:29
如果一个跟目录下所有文件都要隐藏,楼主的方法不行。
实际上最简单的办法就是不用建立IRP,直接把当前的IRP做个循环多CALL几次就可以了。
驱网无线,快乐无限
游客

返回顶部