![Windows内核编程](https://wfqqreader-1252317822.image.myqcloud.com/cover/592/39130592/b_39130592.jpg)
2.4 部署驱动程序
现在,我们有了一个能够成功编译的Sample.sys驱动程序文件,让我们把它安装到系统里并加载。通常我们希望用一个虚拟机来安装和载入驱动程序,以避免主机崩溃的风险。否则的话,需要为这个最小的驱动程序稍稍承担点风险。
安装软件驱动程序与安装用户模式服务一样,要么用合适的参数调用CreateService
API,要么使用现成的工具。有一个用来做这件事的众所周知的工具叫作Sc.exe。这是一个用来对服务进行操作的Windows内置工具,我们会用它来安装和加载驱动程序。请注意,安装和加载驱动程序是特权操作,一般只有管理员才能这么做。
打开一个提升了权限的命令窗口,键入如下内容(最后部分必须是系统里SYS文件所在的路径):
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/027-2.jpg?sign=1739267296-jcYbE0YWteTo6aZXsIqNWwXRZVwroFfj-0-cfd62d4b9e6b9501b5f0973d2dabaa2d)
注意在type和等号之间没有空格,而等号和kernel之间有空格,后面那个也一样。
如果一切顺利,你会看到操作成功的输出信息。为了测试安装是否成功,可以打开注册表编辑器(regedit.exe),在HKLM\System\CurrentControlSet\Services\Sample下寻找这个驱动程序。图2-3显示了完成前一命令之后注册表编辑器的屏幕截图。
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/028-1.jpg?sign=1739267296-ZImCNiBZXFGsekQM4PwYVpb5kQbqobT3-0-bf9b849ce3887b468dd2524b65a8370f)
图2-3 已安装的驱动程序的注册表项
可以再次使用Sc.exe来加载驱动程序。这次用的是start选项,这个选项使用StartService
API来加载驱动程序(同一个API也用来加载服务)。不过,在64位系统中,驱动程序必须经过签名才能被加载,因此这个命令通常会失败:
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/027-3.jpg?sign=1739267296-bDLDhUADUxycmbuNDuGeDHN9R6XNfCrJ-0-2af719973d924e80fa0a8226e8eb35bc)
由于在开发时对驱动程序进行签名并不方便(甚至可能因为没有合适的证书无法签名),有个更好的选择是把系统设置成测试签名模式。在此模式下,未签名的驱动程序能够顺利加载。
可以在一个提升了权限的命令窗口里,用如下方式打开测试签名模式:
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/028-2.jpg?sign=1739267296-cA5fF2ceRRvUmeQeIGC0NqfH0Z8GbYHh-0-970a01803e0d5aabdca6cbe56c9462f0)
不幸的是,这个命令需要重启系统才能生效。重启之后,前面的start命令应该就能成功执行了。
如果在打开了安全启动的Windows 10上进行测试,上面修改测试签名模式的命令将会失败。这个设置是受安全启动保护的(另一项受保护的设置是本地内核调试)。如果由于IT策略或者别的原因,导致无法从BIOS设置中关闭安全启动的话,最好的办法还是用虚拟机进行测试。
如果希望在Windows 10之前的版本上进行测试,那还有一个地方需要设置。你需要在项目属性的对话框里设置目标操作系统的版本,如图2-4所示。注意图中选择了所有配置和所有平台,这样在切换配置(调试/发布)或者平台(x86/x64/ARM/ARM64)时,设置的值可以保持不变。
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/029-1.jpg?sign=1739267296-9eoA0aK4wX4VVJjcBoHFY4AYMPotjiia-0-9442cb125fca9b3d856b5921f1d9c9e2)
图2-4 在项目属性中设置目标操作系统的版本
在打开了测试签名模式并且成功加载了驱动程序之后,将会看到如下输出:
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/028-3.jpg?sign=1739267296-PBgRi4tqoXDWNXRLoLdL0GVzIS7GmxY3-0-797324b4831f23077911106b8a596491)
这表示一切正常,驱动程序已经加载。为了证实这一点,可以打开Process Explorer寻找Sample.sys驱动的映像文件。图2-5显示了加载到系统空间中的Sample驱动程序映像文件的细节。
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/029-2.jpg?sign=1739267296-TCOQCJXJbogI5tRIcgaojnjYbR1B55cx-0-8d0d03ddff0ddc63549c6af909936c36)
图2-5 加载到系统空间中的Sample驱动程序映像文件
此时我们可以用下面这个命令卸载驱动程序:
![000](https://epubservercos.yuewen.com/B7706C/20516006501584606/epubprivate/OEBPS/Images/029-3.jpg?sign=1739267296-o4iZvo6wJBOyXhPRaFXaTkCKUMea7ZBP-0-1b88916af24934788cc354f4a5e8dd42)
在其内部,Sc.exe使用SERVICE_CONTROL_STOP
的值调用了ControlService
这个API。卸载驱动程序导致其Unload例程被调用,目前Unload例程还没做什么。你可以通过再次观察Process Explorer验证驱动程序的确已经被卸载了。