本章内容主要就是带着写了第一个驱动程序,书上当前章节没有介绍如何配置双机调试环境,也没介绍如何禁用驱动强制签名,本文来介绍一下这些东西。
Win7 10 双机调试配置
开发机环境准备
Windows 10 + VS 2019
在 Visual Studio Installer 里安装 SDK,官网下载安装 WDK
遇到的问题解决方案:
https://blog.csdn.net/wangzhichunnihao/article/details/108584295
虚拟机设置
安装好虚拟机,关机,设置虚拟机:
- 移除打印机
- 添加串行端口,设置如图:
Windbg 启动参数
-y srv*D:\Symbols\Windows7sp17601\Symbols -b -k com:port=\\.\pipe\com_1,baud=115200,pipe
注意:
Windows 7 x86 使用 windbg(x86) 版本
Windows 7 x64 使用 windbg(x64) 版本
开启调试模式
开启虚拟机,以管理员运行 cmd,执行如下命令:
bcdedit /dbgsettings serial baudrate:115200 debugport:1
bcdedit /copy {current} /d DebugEntry
bcdedit /displayorder {current} {ID}
bcdedit /debug {ID} ON
顺利的话,到此,调试模式启动成功
驱动加载测试
Win7x86 可直接加载驱动服务安装启动
Win7x64 版本新增了强制签名机制,需要禁用强制签名才能直接加载驱动安装启动(或者安装签名)禁用方法有 2 个(Windows10 也适用):
-
开机的时候按 F8 进入安全模式,选择禁用驱动程序签名强制(该方法单次有效,重启后失效)
-
以管理员运行 cmd,输入如下命令:(不一定成功,可能因为一些林域问题失败)
bcdedit -set loadoptions DDISABLE_INTEGRITY_CHECKS bcdedit -set TESTSIGNING ON
如果要设置回来,输入如下命令:
bcdedit -set loadoptions ENABLE_INTEGRITY_CHECKS bcdedit -set TESTSIGNING OFF
SXS 输出一大堆信息怎么处理
windbg:
ed nt!kd_fusion_mask 0
驱动中的 Hello world
开发环境:Windows 10 + VS2019
当前开发学习的是 NT 式驱动,使用 WDM 驱动开发就行了(WDM 和 NT 驱动混合了)
创建项目
创建项目 WDM
项目文件中有个 inf 文件,写其他驱动的时候可能会有用,但是写 NT 式驱动会出现错误,这里要删掉
源文件,新建项,添加 c 文件
用.cpp 写需要将入口函数使用
extern "c"
进行修饰,使用C的方式进行导出
项目设置
配置设置:所有配置、所有平台
C/C++:常规,将警告视为错误,关掉
Driver Settings:General,Target OS Version,安装到什么系统上就选什么
到这里就设置完了,可以开始写程序了
第一个程序
#include <ntddk.h>
//包含wdm.h,ntifs.h差不多,类似R3开发的Windows.h
//卸载需要单独提供一个卸载函数,不然不能卸载
//卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver) {
//处理未引用的形参,微软提供了个宏
UNREFERENCED_PARAMETER(pDriver);
DbgPrint("Bye World!\n");
}
//主函数:以前是Main,WinMain,现在是DriverEntry
//参数以前可以不带,驱动程序必须带:
//参数1:驱动对象指针
//参数2:内核字符串指针,内核字符串和R3不一样,不使用0作为结尾,而是用结构体表示,这里是注册表路径
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath){
UNREFERENCED_PARAMETER(pRegPath);
//卸载函数需要指定一下
pDriverObject->DriverUnload = DriverUnload;
//Ring3打印:printf
DbgPrint("Hello World!\n");
return STATUS_SUCCESS;//状态成功,实际上就是0(内核中0代表成功),状态码实际上就是数字,但一定要返回STATUS_SUCCESS,这代表成功
}
头文件 #include<ntddk.h>
相当于 R3 开发的时候用的 <windows.h>
,每次写代码都要包含的;
从主函数 DriverEntry
开始看,首先驱动程序的主程序必须带参数,参数是固定的,分别是驱动对象指针和内核字符串指针,参数后面会介绍;
驱动程序里不允许出现未引用的变量,需要通过微软提供的宏 UNREFERENCED_PARAMETER(var)
进行处理;
卸载驱动程序的卸载函数需要在驱动对象指针中指定;
DbgPrint()
是驱动中的 print 函数;
STATUS
是类型是驱动程序中用的类型,需要用宏来表示;
编译项目
右键项目名称,重新生成:
生成了三个东西
- cer 测试证书,毛用没有
- pdb 符号文件,调试的时候会用
- sys 驱动程序
加载测试
拖入虚拟机,打开 dbgview,用 INSTDRV 安装驱动,启动、关闭、卸载:
驱动一般是以服务形式来加载的
首先,驱动作为一个服务来进行安装,启动,停止是对服务的,卸载也是,实际上是一套服务的一套流程
程序参数里的注册表路径就是作为服务的注册表路径
不要问为啥,就是微软规定的
调试测试
这里以 x64 为例,调试方法:
- 在代码里使用内联汇编
int 3
进行中断 - 使用微软提供的中断方式:
DbgBreakPoint()
函数(函数功能就是下个断点让程序停在这里)
在代码中加个断点
#include <ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT pDriver) {
UNREFERENCED_PARAMETER(pDriver);
DbgPrint("Bye World!\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath){
UNREFERENCED_PARAMETER(pRegPath);
pDriverObject->DriverUnload = DriverUnload;
// 断点
DbgBreakPoint();
DbgPrint("Hello World!\n");
return STATUS_SUCCESS;
}