Windows 10 驱动开发 及 驱动签名

article/2025/10/13 1:38:12

记录下在公司开发驱动的一些注意事项, 驱动当前仅针对win10x64.

常识:

        最早的驱动开发sdk是    ntddk, 类似于用户层的win32 api,    后面为了增加对pnp(Plug-and-Play, 即插即用)的支持,  迭代为 wdm.    后面因为wdm开发过于繁琐,   微软发布了 WDF 框架,  类似于 用户层的 MFC. 

       ddk和后面2种驱动的最大区别是 : ddk 创建设备是主动的,  而wdm和wdf之后, 创建设备是被动的, 通过设置一个回调函数来创建设备.  所以通常一些安全软件(非驱动类), 通常会选择ddk模板来开发, 而一些硬件或者模拟类的软件会选择wdm和wdf来开发.

        ddk开发的驱动, 其实可以简单想象为一个服务, 只是这个服务不是运行在用户层, 而在内核层, 所以通常通过scmanager创建服务即可, 只是服务类型改为驱动.

        而wdm和wdf是当设备状态发生变化(系统检测到设备插入, 或模拟强制创建)时, 系统才会回调驱动的create device函数. 并且驱动的安装是需要通过inf文件的, 而inf是比较繁琐的. so....

        其实驱动开发并不是什么异常复杂和高深的知识,  只是使用人数少,  并且系统版本的迭代导致要注意的事项比较多. 导致入手比较烦. 

        sys文件其实跟dll是没什么区别的, 都是pe文件,  都是一个个section段. dll编译的代码和数据段的地址空间都是基于ring3的, 而驱动的地址空间是基于ring0. 内存申请不能使用常见的malloc或者virtualalloc等用户态, 必须用内核态而已. 内核函数运行在哪个进程通常是不能确定的,  理解为HTTP的基于会话方式就行了.

开发环境:

        visual studio 2019 + wdk,   vs2019 安装常规的C++开发环境即可, WDK安装 [适用于 Windows 10 版本 2004 的 WDK]

工程创建步骤:

新项目类型, 若是kmdf, 建议选下面这个模板

        若是wdm, 建议选:

INF文件:

        inf文件比较繁琐, 这里就没有粘贴inf文件了, 但是inf的示例注释我已提交到GitHub上 https://github.com/ChinaCCF/devcon,  可自行下载查看.

        这里有个要主要的事项是, inf文件中不要保存非ascii编码的字符, 否则安装会失败.

测试环境:

        编译好的驱动是不能安装的, 因为没有签名(32驱动不用签名, 随便折腾). 要安装没有签名的驱动也是可以的, 就是配置测试环境, 有2种方式:

                一: 强制禁用系统检测 

                        1)Windows设置
                        2)更新和安全
                        3)恢复
                        4)高级启动->立即重新启动
                        5)疑难解答
                        6)高级选项
                        7)启动设置->重启

                        重启中选择 7 禁用驱动签名

                二: 测试模式

                        管理员权限cmd,  运行命令   :   bcdedit /set testsigning on

         项目生成的目录  x64\release中, 会包含***.sys, 然后也包含一个工程名的文件夹, 里面也包含一个***.sys,  其区别是, 工程名文件夹里面的***.sys是经过测试签名的, 可以在测试模式下加载, 而 x64\release中的是没有测试签名, 只能在禁用测试环境下加载.       

        驱动开发的调试比较麻烦, 因为是基于内核的, 不能像普通用户层那样中断,  因为一旦中断, 整个系统都会中断的, 所以需要2台机器来调试,  通常一台是本机, 一台是VMware. 

        而更为简单的开发方式是通过dbgview查看log. 这软件是微软的.

dbgview 的capture 选择  capture kernel 和 enable verbose kernel output 和 capture events

当显示的日志过多时候, 可以使用filter.

 在exclude中输入你要过滤的信息即可. 或者反之也行.

至于双机调试以后有时间补充.

驱动安装:

       ntddk的驱动, 自己搜索scmanager 来安装, 或者使用 DriverMonitor.exe 软件来安装

        wdm及之后的驱动安装用devcon这个工具, 这工具可以自己编译,  在微软的

        Windows-driver-samples\setup\devcon     目录中

        注意编译后, 要区分系统是否是64位, 64位系统只能用64位编译的devcon来安装, 否则会报错的

        安装命令为 devcon install  xyz.inf  root\xyz

        重复安装的话, 需要先卸载之前安装的实例, 否则会出现很多驱动实例的

        卸载命令为  devcon remove  root\xyz

        但是 devcon 的卸载有个bug, 可能会出现无法卸载驱动的情况, 我自己重写了devcon的卸载, 下载地址 GitHub - ChinaCCF/devcon: 重写了devcon的卸载部分代码

其实到了这一步, 个人开发者参考一些例子和开源代码基本可以随便折腾了.

驱动签名:

          把生成好的.cat和.sys文件 用 ev证书 (abc.pfx)  签名. 例如 驱动文件为 xyz.sys

          signtool sign /f abc.pfx /p 密码 xyz.sys

        signtool 是开发环境附带的, 更详细的使用说明, 可以网上搜索或者参考help.

         HXXX公司的签名流程可以查看 公司文档 <<手动签名指引>>. 

        把签名好的cat和sys和inf文件通过makecab这个工具打包, 这个工具也是开发环境附带的.

makecab所需的ddf文件例子如下:

.OPTION EXPLICIT   
.Set CabinetFileCountThreshold=0
.Set FolderFileCountThreshold=0
.Set FolderSizeThreshold=0
.Set MaxCabinetSize=0
.Set MaxDiskFileCount=0
.Set MaxDiskSize=0
.Set CompressionType=MSZIP
.Set Cabinet=on
.Set Compress=on 
.Set CabinetNameTemplate=ScpVBus.cab 
.Set DestinationDir=abc_dir
C:\learn_driver\build\xyz.inf
C:\learn_driver\build\xyz.sys
C:\learn_driver\build\xyz.cat

####################################################

执行命令:

MakeCab /f "C:\learn_driver\1.ddf"

就会生成一个xxx.cab包.  然后继续用signtool 工具对这个包签名

 HXXX公司签名网页是无法对xxx.cab包签名的, 修改后缀名, 把xxx.cab改为xxx.sys, 再签名

到这个时候, 提交到微软的合作伙伴网页, 硬件签名就可以了

避坑注意,  最好不要附带 协注册器的dll, (WdfCoinstaller01009.dll) inf中去掉与这个dll相关的项, 例如 [xxx.NT.CoInstallers], 否则微软的检测时间长不说, 而且在一些Windows10的机器上会安装驱动失败.

附带 一篇知乎上 驱动签名 文章

避坑 | Windows驱动签名经验贴 - 知乎

我都如此慷慨大方把教程和坑点写出来了, 各位大哥来点赞赏吧, 这可是节约了你们大量时间啊.

也让我有动力继续分享好文章


http://chatgpt.dhexx.cn/article/qjf2OhmO.shtml

相关文章

Linux——驱动开发

一、驱动开发概述 1.1 驱动形式 驱动代码的形式一般可分为build-in和module两种形式&#xff0c;build-in是在编译linux同时将pcie的驱动代码编译到内核中&#xff0c;启动的时候就载入该驱动代码&#xff1b;module是在linux启动完成后通过终端输入命令insmod/remod进行载入…

Windows 驱动开发 新手入门(一)

Windows 驱动开发 新手入门&#xff08;一&#xff09; 引言驱动介绍Win10 WDK 建立一个驱动项目建立MyDriver.cpp理论知识驱动入口派遣函数 MajorFunctionDevice和SymbolicLinkDeviceExtensionIRP 引言 首先祝朋友们新年快乐&#xff0c;然后呢&#xff0c;因为无聊&#xff…

驱动开发学习

驱动 1、驱动开发环境 完成系统移植的三步&#xff1a;u-boot启动引导程序、内核镜像、文件系统&#xff0c;u-boot启动引导程序最好固化到开发板上&#xff0c;内核镜像通过tftp服务从ubuntu下载&#xff0c;文件系统通过nfs服务从ubuntu共享到开发板&#xff0c;开发板启动…

Linux设备驱动开发详解

Linux设备驱动开发详解 Linux设备驱动开发详解Linux设备驱动开发Linux设备驱动开发详解1. linux设备驱动概述及开发环境搭建2. 驱动设计的硬件基础3. linux内核及内核编程4. linux内核模块5. linux文件系统与设备文件6. 字符设备驱动7. linux设备驱动中的并发控制8. linux设备驱…

QT部件基类——QWidget与QDialog

一、默认基类 QT提供的默认部件基类包括QMainWindow、QWidget、和QDialog这三种&#xff0c;这三个部件基类也是用的最多的。 QWidget类是所有部件对象的基类&#xff0c;被称为基础窗口部件&#xff0c;继承关系详看QWidget类关系图。QWidget提供自我绘制和处理用户输入等基本…

qt 中 qwidget 嵌入 qml

以上是效果图&#xff0c; 整个窗口是 qml 窗口 核心代码 #ifndef WIDGETANCHOR_H #define WIDGETANCHOR_H#include <QObject> #include <QQuickItem> #include <QWidget> #include <QQmlApplicationEngine> #include <QQmlContext>class WgtAn…

QWidget尺寸限定

1、控件只能在最小和最大之间进行调整&#xff0c;不能超过范围。 ①直接宽高同时设置 window.setMinimumSize(200, 200)&#xff1b; window.setMaximumSize(500, 500) app QApplication(sys.argv)window QWidget()window.setWindowTitle("最小最大窗口")windo…

QWidget居中显示

须知 以下函数只要继承QWidget都可以使用.例如 QDialog, QPushButton( -v- 一个居中的”引爆按钮”)关于坐标问题: qt窗口坐标原点是在”左上角”的. 如图, (x2, y2)是我窗口的分辨率的一半无论目前我的窗口在什么位置,我只要把窗口原点设置为(x1, y1)就行了.所以目前我要获得…

QWidget事件消息

1、用户操作界面时会产生特定的事件消息。 API&#xff1a;显示和关闭事件、移动事件、调整大小、鼠标事件、键盘事件、焦点事件、拖拽事件、绘制事件、改变事件、右键菜单、输入法。 应用场景&#xff1a;当一个控件被触发了一个特定的行为时&#xff0c;就会调用特定的方法…

QWidget的isHidden和isVisible

文章目录 问题的出现QWidget的show()函数QWidget的isVisible和isHidden源码追溯 QWidget的isHidden和isVisible 问题的出现 最近在写代码的时候&#xff0c;出现了一个问题&#xff0c;我新建了两个类&#xff0c;分别是Chapter2和ConsecutiveCurtain // ConsecutiveCurta…

QWidget鼠标操作

1、设置鼠标形状&#xff1a;鼠标放置在不同控件上&#xff08;有不同功能时&#xff09;鼠标的形状是不一样的。 鼠标跟踪&#xff1a;鼠标在某一个控件上移动&#xff0c;则会向对应的控件对象发送一个消息&#xff0c;去调用具体的某一个方法&#xff0c;可以在方法里面监听…

QWidget旋转方法

参考链接&#xff1a;https://stackoverflow.com/questions/43388464/rotate-whole-qwidget-by-angle 说明&#xff1a; 本文实现方法本质是使用QGraphics三件套&#xff0c;即View、Scene、Item&#xff0c;将QWidget控件作为Item显示&#xff0c;从而实现角度控制的目的&…

QWidget设置背景图及圆角

在Qt开发过程中&#xff0c;QWidget是经常作为主窗体的父窗口&#xff0c;有时我们需要对主窗口设置背景&#xff0c;设置圆角以达到美观的效果&#xff0c;通常的有以下三种方法&#xff1a;qss, QPalette设置以及paintEvent绘制。下面介绍这三种方法。 背景设置介绍 方法一&a…

QWidget之adjustSize

from PyQt5.Qt import * import sys# 创建一个应用程序对象 app QApplication(sys.argv)window QWidget()label QLabel(window) label.setText(学无止境) label.move(100, 100) label.setStyleSheet(background-color:gray)def changeCao():tmp label.text()学无止境label.…

初识QWidget

初识QWidget 在Qt中QWidget是一个非常关键和重要的类&#xff0c;推荐初学Qt的同学们第一个学习此类 在Qt的帮助手册中我们搜索QWidget&#xff0c;可以看到下图的描述 通过帮助手册我们了解到如果想使用QWidget这个类&#xff0c;需要包含QWidget这个头文件&#xff0c;Qt特…

QWidget继承

查看QWidget的继承于哪个类 方法一 随便写一个类继承自己QWidget 按住Ctrl鼠标单击QWidget即可 方法二 print(QWidget.__base__)方法三 print(QWidget.mro()) 链条式的继承展示 enjoy

QWidget(长文)

一、描述 1、QWidget 是用户界面的原子&#xff1a;它从窗口系统接收鼠标、键盘和其他事件&#xff0c;并在屏幕上绘制自己的表示。每个小部件都是矩形的&#xff0c;它们按Z顺序排序。小部件由其父部件和它前面的小部件剪裁。 2、未嵌入父窗口小部件的 QWidget 称为窗口。通…

QWidget的使用

一、QWidget介绍 QWidget是用户操作的原子接口&#xff0c;它从窗口系统中接收鼠标&#xff0c;键盘以及其他事件&#xff0c;并绘制图形界面。QT提供的默认窗口基类只有QMainWindow、QWidget、和QDialog这三种&#xff0c;QMainWindow是带有菜单栏和工具栏的主窗口类&#xf…

QWidget

QWidget QWidget是容器组件&#xff0c;继承自QObject类和QPaintDevice类。能够绘制自己和处理用户输入&#xff0c;是QT中所有窗口组件类的父类&#xff0c;是所有窗口组件的抽象&#xff0c;每个窗口组件都是一个QWidget&#xff0c;QWidget类对象常用作父组件或顶级组件使用…

QT学习总结之QWidget详解

1、说明 QWidget类是所有用户界面对象的基类。 QWidget是用户界面的原子类。它接收鼠标、键盘和来自系统的其他事件&#xff0c;并在屏幕上将它们绘制出来。每个Widget都是矩形的&#xff0c;并按照Z-order&#xff08;Z轴&#xff09;进行排序。一个Widget夹在它的Parent和它…