Windows驱动wdf驱动开发系列(二)

   1.  前言

Windows的驱动开发模型

[序言]
很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概也就3~4年时间.大多数人都认为会驱动开发的都是牛人,高手之类的.其实高手,牛人不是这样定义的.我们在学习驱动开发之前,一定要明白一个道理:术业有专攻,不要盲目跟风.

 

之前没有做过驱动开发,一切从〇开始。陆陆续续看了些书,windows设备驱动程序wdf开发等。但是总是云里雾里的。所以想一点一点的积累下在驱动方面的知识。

因工作上项目的需要,笔者需要做驱动相关的开发,之前并没有接触过相关的知识,折腾一段时间下来,功能如需实现了,也积累了一些经验和看法,所以在此做番总结。

 

[贡献者]
1> defddr   看雪学院
2> StudyRush看雪学院

1. Framework Object Model

威尼斯网址开户网站 1

首先我将记录下如何搭建调试环境?前提是wmware已装完毕,已有两台guest os.
(xp 和win7)。下面针对两类系统的调试进行说明。

对于驱动开发的开发指引,微软官方文档网站已经提供了很详细的教程文档,并且在Github上提供了一系列典型的例程源码用于开发人员参考。开发人员在具备一定的驱动概念知识后,通过参考官方例程可以很容易实现拥有特定功能的驱动应用程序。

   
在Windows的不同版本上开发的驱动程序“模型”(模型这个词语应该来源于单词“Mode”。在Windows
NT上,驱动程序被称为Kernel Driver
Mode驱动程序。笔者认为这个Mode是指一种驱动程序的结构和运作的规范),有过不同的名称。比如在Windows
9x上的驱动程序,都叫做VXD,而在Windows
NT上的驱动程序被称为KDM驱动程序,Windows
98~2000这个时期出现的新模型叫做WDM。
   
Windows的驱动模型概念,本来是就驱动程序的行为而言的。比如WDM驱动,必须要满足提供n种被要求的特性(如电源管理、即插即用)才被称为WDM驱动。如果不提供这些功能,那么统一称为NT式驱动。同样的,WDF驱动也有它的一系列规范。
    但是本书采用简单的区分方法。将一切在Windows 2000~Windows
Vista下能正常运作且未调用WDF相关的内核API函数的驱动都称为传统型驱动(包括NT式和WDM)。如果调用了WDF相关的内核API则称为WDF驱动。
请注意:WDF驱动是可以调用传统型驱动所调用的内核API的,WDF可以视为传统型的升级版。
   
模型的发展并不是和操作系统版本的升级齐步走的,而是有一个逐渐替代的过程。比如Windows
98已经支持部分的WDM驱动程序,但是又支持一部分的VXD驱动。而到了Windows
2000,则VXD这种驱动程序完全被淘汰了。KDM则是WDM的前身。WDM是在KDM的基础上增加了一些新的特性,制定了一些新的规范而造就的。绝大部分函数调用都是通用的。当然,Windows
9x系列的内核完全不同,所以VXD与之相比,就没有一个内核API函数是一样的。
    故而随着Windows 9x的失宠,VXD难逃彻底被淘汰的命运。Windows
NT则发展成了后来的Windows版本,KDM也变成了WDM而存在下来。当然,微软不会闲着,现在又推出了新的WDF。读者又不得不担心:本书是用WDM写的还是用WDF写的呢?会不会刚刚学完又被淘汰呢?
   
和VXD不同,从KDM到WDM再到WDF是一脉相承的,基本上KDM程序员在学习WDM时已经占尽了便宜。到WDF也不例外,WDF与其说是新的驱动开发模型,还不如说是在已有的内核API和数据结构的基础上,又封装出一套让使用者觉得更简单、更易用的以Wdf-开头的一组API。因此,读者大可不必担心WDF的发展会让前面学习传统型驱动的努力付之东流。一个典型的例子是:大约在1991年到1992年间发布首个版本的硬盘上层过滤diskperf的代码,18年过去了,今天依然可以编译并正常在最新版本的Vista上运行。
   
本书对于大部分无法找到WDF实例的章节,都采用了传统型驱动进行说明。比如磁盘过滤、文件系统过滤和网络中间层驱动。此外为了从简单入手,对于入门级的两个例子(串口和键盘)也使用了传统型驱动。但是虚拟磁盘和虚拟网卡(第5章和第11章),使用了WDF版本的例子,请读者注意识别。

[本内容适用环境及工具]
1> Windows系统下
2> VS2003版本以上
3> Windows驱动开发包(DDK(老版本) WDK(新版本))
4> 有能力着可以安装VMWare

2. KMDF程序结构

KMDF属于即插即用驱动程序的驱动模型:

1.一个DriverEntry例程。

2.一个EvtDriverDeviceAdd例程,类似于WDM的AddDevice例程。

3.一个或多个IO队列。

4.一个活多个IO事件回调例程,类似于WDM的DispatchXxx。

5.支持的即插即用和电源管理回调例程。

6.支持的WMI回调例程,用于管理计算机系统

7.其他回调例程,如对象的清除例程、中断处理例程、DMA例程。

 

  • 针对xp驱动调试的设置(参考:)

Windows驱动程序入门:

[本内容适用群体]
1> 具有C/C++语言基础的人
2> 具有80×86汇编基础的人
3> 具备高中以上文化水平的逻辑思维

驱动开发最好使用vmware虚拟机,好处不多说了。首先针对vmware虚拟机的设置(保证虚拟机是关机状态)

Github:

[具备Windows系统理论书籍]
1> Windows核心编程
2> Win32多线程程序设计
3> 深入解析Windows操作系统
4> Windows操作系统原理

1.
设置VM与Windbg通信的串口

 

FAQ1:为什么需要[具备Windows系统理论书籍]这4本书?
答:驱动是Windows系统的一个重要的组成部分,深入Windows系统核心的一个体系,就因为驱动跟系统内核联系得十分紧密,所以涉及了不少系统的基础理论以及原理.因此在学习驱动开发之前必须先明白Windows系统的基础开发理论,Windows系统的运作原理,Windows系统的架构体系.那么我提供的上面4本书是目前市面上我认为最经典最全面的书籍了.

打开目标系统的**Virtual
Machine Setting选项,在Hardware中添加新硬件:1)选择Serial
Port;2)serial
Port Type 选择“Output
to named pipe”;3)Specify
Socket的选项如图1吧;4)最终的配置结果如图2所示。然后启动VM的目标系统吧。**

   2.  驱动类型

[具备Windows驱动开发书籍]
1> Windows驱动开发技术详解
2> Windows设备驱动程序WDF开发

威尼斯网址开户网站 ,注意事项:一般情况下是串口2:Serial Port
2,原因是默认VM安装虚拟打印机占用Serial Port
1.

 驱动分为如下几种类型:

FAQ2:为什么需要[具备Windows驱动开发书籍]这2本书?
答:假设你对Windows系统的基础理论扎实了,也看完了所说的[Windows系统理论书籍]这4本书,而且你还从事开发过Windows程序或者大程序的经验者.那么你进入Windows驱动开发的时候,需要一本经典的驱动入门开发书籍即可正确入门.现在我提供了[Windows驱动开发书籍]这2本书完完全全针对Windows驱动开发入门而编写的书籍.当然我首要推荐<Windows驱动开发详解>这本书.本书的内容在目前来说,针对驱动开发的讲解时非常到位了.包含了驱动开发理论
配置 驱动体系
等等……是一本不可多得的好书.那么第2本,其实有点滥竽充数,但是他里面有少少涉及到WDF这个最新的驱动开发理论的讲解,大家也就凑合着吧.

威尼斯网址开户网站 2 

> > 图1

威尼斯网址开户网站 3

> > 图2

  • 设备函数驱动程序
  • 设备筛选器驱动程序
  • 软件驱动程序
  • 文件系统筛选器驱动程序
  • 文件系统驱动程序

[具备Windows调试基础理论书籍]
1> 软件调试
2> Windows用户态程序高效排错

2. 设置Guest
OS的启动项

驱动程序不是一定需要与硬件通讯,如果需要访问操作系统核心数据,往往应用程序没有足够的权限,这种情况则需要在内核模式下进行访问。就上面5种驱动类型,笔者参考着微软的驱动例子开发过
鼠标键盘设备过滤驱动
网络过滤软件驱动程序,所以对驱动开发的理解仍在浅水区,如在阅读过程中发现有误的地方,还请不吝指出。

FAQ3:为什么需要[具备Windows调试基础理论书籍]这2本书?
答:在开发驱动的情况下,你少不了要调试驱动程序.那么如何调试驱动程序呢?
Windows已为你考虑到这个问题了并开发了一套强有力的调试工具:Windbg
.如何学习这个工具的调试呢?那么现在市面上只有这2本书针对Windbg讲解得还比较到位,至少针对调试命令的使用,已经用中文讲解了,大家可以通过2本书先大概了解Windbg的调试命令,然后再进一步进行GOOGLE搜索并深入学习.

进入WinXP的虚拟机操作系统,打开系统盘(C:\),将文件夹查看选项全开了,那在C盘根目录下有一个叫boot.ini的启动项文件,先去掉只读属性,以文本文件的方式打开,拷贝原来的启动项,作如下修改:

采用的驱动类型关乎到代码的实现(需不需要考虑PNP和电源管理)和驱动的安装(
NT式驱动程序以 service
的形式运行,其他驱动需要采用通用的INF文件安装),微软的官方文档这样提到:

[具备汇编基础理论书籍]
1> 汇编语言 作者:王爽
2> 80×86汇编语言程序设计教程[绿皮版 或者 黑皮版]

Multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=”Microsoft
Windows XP Professional” /noexecute=optin /fastdetect /debug
/debugport=com2 /baudrate=115200

style=”font-family: ‘Microsoft YaHei’;”>有关软件驱动程序,你的两个选项为
KMDF 和内核模式 Windows NT 驱动程序模型。 使用 KMDF 和内核模式 Windows
NT 模型,你可以编写驱动程序,而无需考虑即插即用 (PnP) 和电源管理。
你可以改为专心于驱动程序的首要任务上。 使用 KMDF,你不必考虑 PnP
和电源,因为框架会为你处理 PnP 和电源。 使用内核模式 Windows NT
模型,你不必考虑 PnP 和电源,因为内核模式服务在与 PnP
和电源管理完全无关的环境中运行。

FAQ4:为什么需要[具备汇编基础理论书籍]这2本书?
答:由于在Windows环境下开发驱动,从而有个弊端,就是Windows的WDK,DDK文档少得可怜,很多说明多是模糊的.因此导致我们开发的驱动极其不稳定,这时就需要逆向Windows驱动的机制来加深理解.在一个由于驱动的不稳定性,会导致系统蓝屏,有时错误并不会直接定位到你的代码,这时就需要汇编来分析错误的缘由.就如我前面介绍的[具备Windows调试基础理论书籍]基本是用汇编语言来阐述调试技术.

注意事项:如果步骤1中的serial port选择的是serial
port 1是话,此处为com1.如果是serial port
2的话此处为com2.

   3.  开发环境

[驱动开发扩展书籍]
1> 寒江独钓-Windows内核安全编程
2> Windows内核原理与实现
3> Rootkit Windows内核安全防范
4> Windows内核情景分析

3.配置WinDbg的快捷方式

 

FAQ5:为什么需要[驱动开发扩展书籍]这4本书?
答:熟话说:学无止境,驱动开发领域是一个很庞大的体系,这归根于驱动框架多样化而决定的.驱动包含了:文件驱动,磁盘驱动,显卡驱动,网络驱动,等等不同的种类,每一种类就是一个领域,你决定你的能力需要扩展到多方面,那么你可以考虑先我这里提供的这4本书来学习,通过阅读这3本书,你会发现驱动可以做很多你意想不到的事情.本人从事开发驱动将近4年,也仅仅涉及
文件驱动,磁盘驱动以及一些小型驱动而已.这些的学习我也仅仅是根据需求来进行选择性学习.每个人都有自己的能力极限,大家要量力而行.

在winddk的安装目录(C:\WinDDK\7600.16385.0\Debuggers)找到windbg.exe执行程序。在桌面创建快捷方式,并且修改属性如下:

Visual Studio +
WDK(Windows Driver Kit)

来自为知笔记(Wiz)

“C:\WinDDK\7600.16385.0\Debuggers\windbg.exe”
-b -k com:port=\\.\pipe\com_1,baud=115200,pipe

其中WDK需要自己手动下载安装

注意事项:host os
使用对应的windbg.exe,原因是windbg.exe有32和64位之分。

笔者是在Windows平台上开发,使用的开发环境为
Visual Studio 2013 + WDK 8.1

  • 针对win7驱动调试的设置

 

1. WM和windbg的通信串口设置(同guest os为xp的设置一致)

   4.  实现方式

2. 设置guest os 启动项

 

首先,运行msconfig进入引导tab页,点击高级选项,将调试选上,并且注意调试端口要和通信串口的设置保持一致,重启guest
os.

WDM vs WDF

对于刚接触驱动开发的新手来说,笔者不建议采用WDM(Windows
驱动程序模型)进行开发。目前在网上能找到的关于驱动开发的中文书籍基本上都是围绕WDM模式进行讲述的,而关于WDF(Windows
驱动框架)开发的书籍寥寥无几,《竹林溪径——深入浅出Window驱动开发》和《Developing
Drivers with the Windows Driver
Foundation》算是两本讲述基于WDF开发驱动的书籍,两者都能在网上找到电子书资源。

 

其次, 方法一:启动guest os后,以管理员权限启动dbgview.exe。

基于WDF的驱动开发

WDF的开发需要遵循一定的规则,开发实现时需要考虑较多的细节,由于篇幅有限,笔者凭着自己的经验暂且稍做列举,后续将写一篇针对WDF驱动开发的文章。

  • PNP和电源管理(WDF已经帮忙封装了大部分的接口);
  • 各种对象:驱动对象,设备对象,WDF对象,文件对象,队列对象;
  • 驱动上下文:有时称为设备扩展,用于存储特定设备对象的相关信息的数据结构;
  • 对象的释放:需要考虑不同性质对象释放的时机;
  • 中断请求级别:处理不当易导致蓝屏;
  • 分页与非分页内存;
  • 同步锁:回调同步锁、框架等待锁、自旋锁、中断锁等;
  • 日志跟踪记录:
    调试的必备,可以采用 WPP(Windows软件追踪预处理器)或简单的
    DebugPrint 输出
  • 与应用程序的通讯:控制代码、IRQ,请求队列

 

   5.  驱动安装

 

方法二:如果想调试Kdprint的话可以修改注册表

测试环境下安装驱动前

开发的驱动程序没有进行签名或者采用测试签名,则需要在设备上开启测试模式,具体操作为:打开控制台,输入:

bcdedit /set testsigning on

回车,会提示:操作成功完成。
然后重启设备,开机后会在电脑桌面右下方显示有“测试模式”字样内容的水印。

如果要关闭测试模式,则需在控制台输入:

bcdedit /set testsigning off

回车,同样会提示:操作成功完成。
重启设备后则会发现桌面右下角的水印消失。

 

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session
Manager/Debug Print Filter] DEFAULT=dword:0000000f

以服务的形式运行

NT式的驱动程序允许以 service
的形式运行, 服务安装的例程可以参考 WDF Sample 中的 Eventdrv
工程,或者参考我写的关于进程网络监控的驱动例程的开源代码

 

3. 配置windbg的快捷方式(同guest os为xp的设置一致)**

使用INF文件安装

设备相关的驱动安装可以选择INF进行安装,INF安装文件的编写建议从
WDF Sample
中找到合适的INF文件进行修改,如果你想了解INF的语法,可以参考这里

  • 通过设备管理器手工安装

打开控制台,输入 devmgmt
回车,这是打开设备管理器的其中一种方式,其他方式比如右键系统菜单栏图标均可以打开任务管理器,只是使用命令行的方式比较少见,这里特意记录一下。找到感兴趣的
设备节点,右键 属性(或更新驱动程序软件),切换到
驱动程序,可以进行感兴趣的操作。这里所看到所提供的选项,后续等你熟悉了驱动安装的接口后,你会发现都有对应的接口对应每个功能选项。

  • 通过程序实现自动安装

可以参考 WDF Sample
中的Driver Install Frameworks API (DIFxAPI) Sample
Device Console (DevCon) Tool
两个工程,分别提供了不同调用接口的驱动安装方式,Device Console (DevCon) Tool
生成的devcon.exe
是一个功能强大的工具,不仅可用于驱动(包)的安装和卸载,还可以获取设备的硬件ID,描述符以及设备所安装的驱动列表等信息,开发人员可以从中一窥究竟。

在驱动的安装过程中,系统会自动记录安装的日志,在INF目录(路径一般在 C:\Windows\inf下)下可以找到两个日志文件
setupapi.app.logSetupapi.dev.log
,查看这两个日志文件有利于理解驱动安装的执行过程,同时也有利于排查驱动安装过程中出现的异常。

驱动的安装涉及到驱动文件的校验(保证驱动文件的完整性和合法性),驱动的优先级计算(选择最优的驱动去匹配当前识别到的新的设备),驱动的放置目录(Driver
Store)等内容。开发人员熟悉驱动安装逻辑有利于驱动的开发,感兴趣可以通过此处进行了解。

 

   6.  驱动签名

 

  •  单步调试

测试环境

通过VS集成开发环境创建 Driver
解决方案后会生成两个项目,右键属性打开 XXX Package,左侧选中
Driver Signing ,在右侧栏 Sign Mode 选择 Test Sign,在
Test Certificate选择
<Create test certificate...>,则在编译时会自动生成测试签名证书。

 

  1.  加载符号文件

生产环境

从Win10开始,驱动文件包不仅需要进行扩展验证
(EV)
代码签名,还需要提交到硬件开发中心仪表盘,具体操作指南可以参考此处,你可以在该文档上找到驱动签名所需的任何内容。

 

在windbg上键入:.reload

键入:ld charsample

键入:lm l 

2.  设置断点

点击菜单“File”-> ”OpenSource File…”,
选择驱动程序目录下的源文件queue.cpp并打开。将光标移动到某指令位置,使用F9设置断点,则该处代码显示为红色,就表示断点已经设置了。

3. 使用F11可进行单步调试

相关文章