文件系统驱动(IFS DDK)学习笔记 (转)

linux设备驱动程序--sysfs用户接口的使用 在上述的示例中,我们依旧引入了一个指示灯,值得注意的是,在示例中,博主并没有将led_attrs传入给kobject本身,而是使用sysfs_create_group()接口创建了一个目录,目录下的文件有led和led_status.Linux设备模型的核心是使用Bus、Class、Device、Driver四个核心数据结构,将大量的、不同功能的硬件设备(以及驱动该硬件设备的方法),以树状结构的形式,进行归纳、抽象,从而方便Kernel的统一管理。这就是Kobject诞生的背景。 阅读详情
文件系统驱动是windows系统中最复杂的驱动种类之一。它的全称 IFS DDK 是指可安装文件系统 设备驱动程序开发工具。这方面的资料非常少,我从网上找到的资料大都是文档,都是一些在学习文件系统驱动的人自己写的,几乎没有这方面的专门书籍,更不用说中文资料了。而且ifs ddk中的帮助文档没多大意义,文件系统相关的ddk帮助极其简略,很多重要的部分仅仅轻描淡写的带过。

下图是我们的IFS DDK在堆栈中的位置

I/O管理器

文件驱动

中间驱动层

设备驱动

硬件抽象层

可以看出IFS DDK是在我们的硬件和操作系统之间工作的。

那么如何学好IFS DDK呢?

首先,要把 Windows 的底层基础学扎实。

其次,就是要把英文阅读能力练好。所有资料几乎全是英文的,DDK开发工具也全是英文,而且你别指望会有中文开发工具面市,至少短期内是不会有的,我费了老大劲才从Microsoft偷出了WDK工具包,现在的文件系统驱动是要收费的,就是博士说的4000$。这种东西一般是不会有人共享的。

再次,还有附加的一个条件就是要有足够的耐心,驱动程序设计将要花费的时间是你无法想象到的,没有耐性建议趁早转行。

最后,也是最重要的一点就是一定要亲自动手做!看再多的资料不动手,那只是停留在理论上,实践永远是空白。

看了上面是不是已经做好了心理准备了?准备好了我们就继续往下看。

开发文件系统驱动的目的

一是用于防病毒引擎。希望在系统读写文件的时候,捕获读写的数据内容,然后检测其中是否含有病毒代码。

二是用于加密文件系统,希望在文件写过程中对数据进行加密,在读的过程中进行解密。

三是设计透明的文件系统加速。读写磁盘的时候,合适的cache算法是可以大大提高磁盘的工作效率。windows本身的cache算法未必适合一些特殊的读写磁盘操作(如流媒体服务器上读流媒体文件)。

知道了开发目的,我们就来了解一下DDK里面的具体东西

例程(Routine):简单说例程就是函数。

接口(Api):编程开发接口,一个提供给你调用的函数。

流(Stream):实际上就是FileObject(文件对象),是一个文件中的物理数据流。

文件(File):一个文件可能有多个FileObject,因为可能多次打开,多个FileObject可能对应一个文件。

域(Field):数据结构中的一个数据成员。数据库中称为字段。面向对象中称为数据成员。

回调(Callback)函数:一个由系统调用而不能自己调用的函数。

入口函数(DriverEntry)和win32编程一样,驱动也有一个入口函数 (相当于main  WinMain),这里注意他们之间的运行方式是不同的,win32入口函数后是进入消息循环,驱动DriverEntry的主要功能是注册一些IRP的相当于回调处理方式的函数,也就是派遣函数。入口函数主要是创建设备对象及符号连接,以及其它初使化操作,如分配池内存等。

出口函数(DriverUnload):删除符号连接与设备对象,并释放已经分配的各种资源。

IRP(I/O请求包),驱动编程里十分重要的概念,说白了它就是一个数据结构,里面有对应操作需要的数据,比如我们在应用层调用了CreateFile函数,在驱动层就需要构建一个IRP(IRP_MJ_CREATE),通过这个IRP的处理完成对应操作,如果我们对用户打开,创建文件等操作有兴趣,就可以通过挂接的方式让系统将这个IRP发送到我们指定的函数(DriverEntry里面指定的)。

DriverObject->MajorFunction[IRP_MJ_CREATE]=FileDiskCreateClose

DriverObject->MajorFunction[IRP_MJ_CLOSE]=FileDiskCreateClose;响应建立关闭DriverObject->MajorFunction[IRP_MJ_READ]=FileDiskReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE]=FileDiskReadWrite;响应一般读写DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl; 设置IRP控制函数

DriverObject->DriverUnload = FileDiskUnload; 设置卸载规则

CDO(control Device Object),控制设备对象,这个对象代表这个驱动,它是供我们应用层的程序使用的,在DriverEntry里面创建它,它是没有设备扩展的。我们一般见到说的DO(device object)是用来绑定到文件系统驱动的FDO上的,和CDO不同。他们都使用IoCreateDevice函数创建。  

Device Extension(设备扩展),其实它就是一块保存有用数据的内存,这里一般就是一个结构体。它有一个好处就是它可以随DO一起传递,方便又节省资源。

访问输入输出参数:

Buffered方式:使用IoGetCurrentIrpStackLocation得到调用者堆栈区域指针IrpStack(PIO_STACK_LOCATION类型)

Irp->AssociatedIrp.SystemBuffer;输入输出缓冲

IrpStack->Parameters.DeviceIoControl.InputBufferLength;输入缓冲长度

IrpStack->Parameters.DeviceIoControl.OutputBufferLength;输出缓冲长度

IrpStack->Parameters.DeviceIoControl.IoControlCode;设备控制代码

如果需要输出参数,在填写完SystemBuffer后要设置IRP的IoStatus成员的Information指示输出数据的长度.

Direct方式:MmGetSystemAddressForMdlSafe映射IRP->MdlAddress地址到内核空间

MmGetMdlByteCount,得到MDL大小,以字节为单位.通常应该在IRQL<=DISPATCH_LEVEL的情况下使用MDL,

Neither方式:这个方式比恐怖,除非确定驱动不是分层的并且运行在PASSIVE_LEVEL级,一般不使用这种方式.比如写一个简单的Dump核心数据结构的驱动,该驱动只由我们的一个程序控制,那么可以直接把用户模式的地址传给驱动使用。

前面提到了IRP在驱动里是个非常重要的概念,那我们下面就着重看一下I/O请求包数据结构中的具体东东

 Flags(ULONG)域 包含一些对驱动程序只读的标志。

 AssociatedIrp(union)域 是一个三指针联合。其中,与WDK驱动程序相关的指针是AssociatedIrp.SystemBuffer。SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中。对于IRP_MJ_READ和IRP_MJ_WRITE操作,如果顶级设备指定DO_BUFFERED_IO标志,则I/O管理器就创建这个数据缓冲区。对于IRP_MJ_DEVICE_CONTROL操作,如果 I/O控制功能代码指出需要缓冲区,则I/O管理器就创建这个数据缓冲区。I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,并对数据进行管理,这也是创建IRP过程的一部分。这些数据可以是与WriteFile调用有关的数据,或者是DeviceIoControl调用中所谓的输入数据。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。对于指定了 METHOD_BUFFERED的I/O控制操作,驱动程序把所谓的输出数据放到这个缓冲区,然后I/O管理器再把数据复制到用户模式的输出缓冲区。

  IoStatus(IO_STATUS_BLOCK) 是一个仅包含两个域的结构,驱动程序在最终完成请求时设置这个结构。

  RequestorMode 等于一个枚举常量UserMode或KernelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。

  PendingReturned(BOOLEAN) 如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。完成例程通过参考该域来避免自己与派遣例程间的潜在竞争。

  Cancel(BOOLEAN) 如果为TRUE,则表明IoCancelIrp已被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIrp函数。

  CancelIrql(KIRQL) 是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的。当你在取消例程中释放自旋锁时应参考这个域。

  IRQL是Interrupt ReQuest Level,中断请求级别。

  CancelRoutine(PDRIVER_CANCEL),是驱动程序取消例程的地址。可以使用IoSetCancelRoutine函数设置这个域但尽量不要直接修改该域。

任何内核模式程序在创建一个IRP时,同时还创建了一个与之关联的 IO_STACK_LOCATION结构数组:数组中的每个堆栈单元都对应一个将处理该IRP的驱动程序,另外还有一个堆栈单元供IRP的创建者使用。堆栈单元中包含该IRP的类型代码和参数信息以及完成函数的地址。

MajorFunction

MinorFunction

Flags

Control

Parameters

DeviceObject

FileObject

CompletionRoutine

Context

 

上图是I/O堆栈单元数据结构的示例图,下面对图中的函数做一下解释。

  MajorFunction(UCHAR)  是IRP的主功能码。这个代码应该为类似 IRP_MJ_READ一样的值,并与驱动程序对象中MajorFunction表的某个派遣函数指针相对应。如果该代码存在于某个特殊驱动程序的I/O 堆栈单元中,它有可能一开始是,例如IRP_MJ_READ,而后被驱动程序转换成其它代码,并沿着驱动程序堆栈发送到低层驱动程序。我将在第十一章 (USB总线)中举一个这样的例子,USB驱动程序把标准的读或写请求转换成内部控制操作,以便向USB总线驱动程序提交请求。

  MinorFunction(UCHAR)  是IRP的副功能码。它进一步指出该IRP属于哪个主功能类。例如,IRP_MJ_PNP请求就有约一打的副功能码,如IRP_MN_START_DEVICE、IRP_MN_REMOVE_DEVICE,等等。

  Parameters(union)   是几个子结构的联合,每个请求类型都有自己专用的参数,而每个子结构就是一种参数。这些子结构包括Create(IRP_MJ_CREATE请求)、Read(IRP_MJ_READ请求)、StartDevice(IRP_MJ_PNP的IRP_MN_START_DEVICE子类型),等等。

  DeviceObject(PDEVICE_OBJECT)   是与堆栈单元对应的设备对象的地址。该域由IoCallDriver函数负责填写。

  FileObject(PFILE_OBJECT)  是内核文件对象的地址,IRP的目标就是这个文件对象。驱动程序通常在处理清除请求(IRP_MJ_CLEANUP)时使用FileObject指针,以区分队列中与该文件对象无关的IRP。

  CompletionRoutine(PIO_COMPLETION_ROUTINE)  是一个I/O完成例程的地址,该地址是由与这个堆栈单元对应的驱动程序的更上一层驱动程序设置的。你绝对不要直接设置这个域,应该调用IoSetCompletionRoutine函数,该函数知道如何参考下一层驱动程序的堆栈单元。设备堆栈的最低一级驱动程序并不需要完成例程,因为它们必须直接完成请求。然而,请求的发起者有时确实需要一个完成例程,但通常没有自己的堆栈单元。这就是为什么每一级驱动程序都使用下一级驱动程序的堆栈单元保存自己完成例程指针的原因。

  Context(PVOID)  是一个任意的与上下文相关的值,将作为参数传递给完成例程。你绝对不要直接设置该域;它由IoSetCompletionRoutine函数自动设置,其值来自该函数的某个参数。

 

 

过滤/挂钩IRP请求

    对于过滤/挂钩IRP请求我也不是十分理解,只是觉得比较有用,在这里拿出来与大家一起探讨,如果有知道的可以联系我。

挂钩某个IRP处理函数

1 调用IoGetDeviceObjectPointer返回的设备对象(PDEVICE_OBJECT)

2 由设备对象得到驱动对象PDEVICE_OBJECT->DriverObject(PDRIVER_OBJECT),这里应该调用ObReferenceObjectByPointer函数增加驱动对象的引用计数,以防止该驱动程序在我们的驱动程序前被卸载。

3 再由驱动对象得到中断请求派遣函数表(PDRIVER_OBJECT->MajorFunction)

4 保存PDRIVER_OBJECT->MajorFunction[IRP_MJ_XXXXXXX]值(原中断请求派遣函数地址)

5 修改PDRIVER_OBJECT->MajorFunction[IRP_MJ_XXXXXXX]值(让它指向我们自定义的函数),使用锁总线前缀lock的xchg指令进行赋值操作(让代码多线程和多处理器安全)

6 结束处理同System Service Hook

过滤某个设备的IRP请求:

1 初使化IRP请求派遣函数表MajorFunction,将它们全都指向一个派遣函数DispatchAny

2 再为MajorFunction指定几个我们感兴趣的IRP请求派遣函数

3 得到设备对象指针:IoGetDeviceObjectPointer

4 将设备加到设备堆栈上:IoAttachDeviceToDeviceStack,并保存下层设备对象,以供IoCallDriver时使用.

5 在DispatchAny中将IRP传给下层驱动IoSkipCurrentIrpStackLocation,IoCallDriver.

6 在指定的几个请求派遣函数中对IRP进行处理.

说了这么多是不是有点迷糊了,下面我们来看一个驱动框架的创建过程

 

 

NTSTATUS DriverEntry(  

          IN   PDRIVER_OBJECT   DriverObject,  

          IN   PUNICODE_STRING   RegistryPath  )

{

  NTSTATUS status;

  DriverObject->DriverUnload   =   DriverUnload;    

  Device_object  *  ourCDO   =   NULL;   //控制设备对象,这里默认为空

  UNICODE_STRING           Name_2k

  RtlInitUnicodeString(&Name_2k,L"//FileSystem//OurFilter_Cdo");

  status = IoCreateDevice(DriverObject, 0,  &Name_orc);

  if(!NT_SUCCESS(status)) 

    return   status;  如果创建控制设备对象失败,返回status

  UNICODE_STRING    Link_orc;   创建一个Win32可见的符号连接

  RtlInitUnicodeString(&Link_orc,L"//DosDevices//OurFilter");  

  status = IoCreateSymbolicLink(&Link_orc   ,&Name_orc);  

  if(!NT_SUCCESS(status))  

    return   status;

}

void   DriverUnload(IN   PDRIVER_OBJECT   pDriverObject)  

{    

   UNICODE_STRING   uniNameString;  

   RtlInitUnicodeString(&Name_orc,   L"//FileSystem//OurFilter_Cdo");  

   IoDeleteSymbolicLink(&Name_orc);//删除win32可见的连接 

   IoDeleteDevice(pDriverObject->DeviceObject);//删除设备  

   return;  

}

 

  DriverObject拥有一组函数指针,称为dispatch  functions.开发驱动的主要任务就是亲手撰写这些dispatch functions.当系统用到你的驱动时,会向你的DO发送IRP(这是windows所有驱动的共同工作方式)。你的任务是在dispatch  function中处理这些请求。你可以让irp失败,也可以成功返回,也可以修改这些irp,甚至可以自己发出irp。

  这样一个最基本的驱动框架就出来了,再加入DbgPrint()调试信息,编译并调试后就可以看到输出的调试信息。大体框架是这样,里面有很多东西我也不理解,大概也有些错误。至于调试我现在还在学习中,DDK工具中的好多东西还没有弄明白。

文件系统驱动(IFS DDK)学习笔记 文件系统驱动是windows系统中最复杂的驱动种类之一。它的全称 IFS DDK 是指可安装文件系统 设备驱动程序开发工具。这方面的资料非常少,我从网上找到的资料大都是文档,都是一些在学习文件系统驱动的人自己写的,几乎没有这方面的专门书籍,更不用说中文资料了。而且ifs ddk中的帮助文档没多大意义,文件系统相关的ddk帮助极其简略,很多重要的部分仅仅轻描淡写的带过。 下图是我们的IFS DDK... 阅读详情

相关推荐

文件系统过滤驱动_笔记

1.IFS和DDK的区别 DDK 是指设备驱动程序开发工具 IFS (Installable File System) DDK 是指可安装文件系统 设备驱动程序开发工具 还有就是MS DDK完全免费 驱动程序在堆栈中的位置: ============================= =I/O管理器= =============...

tianyu的专栏 - Linux site:blog.youkuaiyun.com/wishfly 550

Linux文件系统与设备驱动

由于字符设备和块设备都良好地体现了“一切都是文件”的设计思想,掌握Linux文件系统、设备文件系统的知识就显得相当重要了。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 690

文件系统驱动开发的文档资料(IFS+DDK)

文件系统驱动开发的文档资料(IFS+DDK) 文件系统驱动开发的文档资料(IFS+DDK)

IFS和DDK的区别

DDK 是指设备驱动程序开发工具IFS DDK 是指可安装文件系统 设备驱动程序开发工具还有就是MS DDK完全免费驱动程序在堆栈中的位置:==============================           I/O管理器             ==     ==========================   =****************=   =*   文件驱动    

jiabinzx的专栏 2609

IFSDDK+FOR+XP可以下载地址包

积存了我在网上找的IFSDDK FOR XP的下载地址,本想把自己下载的传上来,无奈太大有138M,如果传上来得分几次几个名字传,所以直接把自己下载的地址传上来,用迅雷下载,速度很快,我共用了10多分钟下下来,速度总在400KB/S,希望对大家有用,如果下不下来的可以留言,给个邮箱地址,本人免费发送给你们。另本人有IFSDDK FOX XP,IFSDDK 2003和WDFv10(ifsddk for2000)

文件系统驱动开发的文档资料(IFS DDK).rar

文件系统驱动开发的文档资料(IFS DDK)

【转帖】文件系统驱动(IFS DDK)学习笔记

 文件系统驱动是windows系统中最复杂的驱动种类之一。它的全称 IFS DDK 是指可安装文件系统 设备驱动程序开发工具。这方面的资料非常少,我从网上找到的资料大都是文档,都是一些在学习文件系统驱动的人自己写的,几乎没有这方面的专门书籍,更不用说中文资料了。而且ifs ddk中的帮助文档没多大意义,文件系统相关的ddk帮助极其简略,很多重要的部分仅仅轻描淡写的带过。下图是我们的IFS DD

floweronwarmbed的专栏 935

文件系统驱动开发的文档资料IFSDDK

文件系统驱动开发的文档资料IFSDDK 文件系统驱动开发的文档资料IFSDDK

WDK与DDK的区别

虽然都说WDK是DDK的升级版本,我下面的说话是最详细的。 WDK采用WDF驱动模型,意为Windows Driver Foudation,是Vista及以后版本OS所采用的驱动模型, 以前的DDK,是WDM驱动模型,意为Windows Driver Model WDK包含了以前的DDK和IFS,和驱动验证等等…… XP下也可以使用WDK,它能编译Win2000

木易云清 3080

文件系统驱动和设备驱动的区别

文件系统驱动和设备驱动是容易混淆的概念,本PDF将对文件系统过滤驱动和设备驱动的异同点做简要总结和分析,详细剖析两者的异同点,超高清PDF

利用Ghidra与SVD插件实现STM32固件深度逆向分析

本文详细介绍了如何利用Ghidra逆向工程框架结合SVD插件,实现对STM32固件(.bin文件)的深度逆向分析。通过加载描述芯片外设寄存器的SVD文件,Ghidra能将晦涩的硬件地址操作转换为可读的寄存器符号,极大提升了对嵌入式固件中通信协议、安全校验等关键逻辑的分析效率。文章涵盖了从Java环境搭建、工具配置到实战逆向解析的完整流程。

peach的博客 942

关于windows驱动开发的几个专有名词的解释(DDK,WDM,IFS,VXD)

文件系统驱动是windows系统中最复杂的驱动种类之一。它的全称 IFS DDK 是指可安装文件系统 设备驱动程序开发工具。这方面的资料非常少 DDK 是指设备驱动程序开发工具 WDM(Win32 Driver Model),即Win32驱动程序模型 旨在通过提供一种灵活的方式来简化驱动程序的开发。在实现对新硬件的支持上,减少并降低了所必须开发的驱动程序的数量和复杂性。除了通用的平

786

C#.NET斗地主服务端核心架构与高性能实现

斗地主作为典型的实时对战棋牌逻辑,本质是状态驱动的分布式协同问题。其技术内核涵盖有限状态机建模、低延迟网络同步、无GC内存操作与轻量级AI决策等关键能力。在.NET平台下,借助Span<T>、ImmutableArray、命令/事件总线与内存池等特性,可构建出高吞吐(200+ QPS)、低延迟(<150ms)、强一致的可落地服务端。本文聚焦C#.NET生态中斗地主核心模块的设计取舍与压测验证,深入解析状态机驱动、CardSet结构体优化、Kestrel中间件锁、规则+概率混合AI等实战方案,为实时对战类业务

weixin_29726381的博客 345

Windows文件系统过滤驱动开发教程-楚狂人

第一部分:概述,钻研目的和准备 我经常在网上碰到同行请求开发文件系统驱动。Windows的PC机上以过滤驱动居多。其目的不外乎有以下几种:     1、用于防病毒引擎。希望在文件读写的时候,捕获读写的数据内容,然后检测其中是否含有病毒代码。     2、用于加密文件系统,希望在文件写过程中对数据进行加密,在读的过程中进行解密。     3、设计透明的文件系统加速。读写磁盘的

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 2343

告别AT串口线!用STM32F407的USB FS口直连EC800M进行物联网通信

本文介绍了一种创新的物联网通信方案,利用STM32F407的USB FS接口直连EC800M模块,替代传统的AT串口线连接。通过详细的硬件对比、STM32CubeMX配置和USB驱动调试步骤,展示了如何实现更高效的AT指令通信,同时降低硬件复杂度和功耗。

weixin_29189987的博客 706

别再被手机厂商忽悠了!一文看懂光学变焦、数字变焦和混合变焦到底有啥区别

本文深入解析手机摄影中的光学变焦、数字变焦和混合变焦技术,揭示它们的工作原理和实际效果差异。光学变焦保持无损画质,数字变焦依赖算法放大,而混合变焦结合两者优势。帮助消费者识破厂商宣传,根据实际需求选择最适合的变焦方式,提升拍摄质量。

weixin_28717969的博客 409

Windows文件系统过滤驱动开发教程

0.       作者,楚狂人自述我长期网上为各位项目经理充当“技术实现者”的角色。我感觉Windows文件系统驱动的开发能找到的资料比较少。为了让技术经验不至于遗忘和引起大家交流的兴趣我以我的工作经验撰写本教程。我的理解未必正确,有错误的地方望多多指教。有问题欢迎与我联系。我们也乐于接受各种驱动项目的开发。邮箱为MFC_Tan_Wen@163.com,QQ为16191935。对于这本教程,您可以

温研的专栏 (探索OS内核的奥秘) 3709

【人工智能】向量数据库全生命周期数据安全防护体系:破解向量化与检索双环节泄露风险

大模型时代,向量数据库已成为RAG(检索增强生成)架构、语义检索、多模态应用的核心基础设施,解决了大模型幻觉、长上下文窗口限制、私有知识落地等核心痛点。但行业普遍存在认知误区:将Embedding向量等同于“无害的语义压缩乱码”,忽视了向量数据原生的泄露风险。

奶爸的编程之路,也就一周冷个三天 156
上一篇: 文件系统过滤基础知识
下一篇: MDL(内存描述符表) 详解
vbsourcecode
博客等级 码龄17年 19粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值