news 2026/4/16 14:27:39

BYOVD再探—编写简单的驱动与Loade

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BYOVD再探—编写简单的驱动与Loade

前言

之前已经说过如何通过驱动进入内核了,今天我们来编写一个简单的驱动以及驱动加载器,虽然上一篇也有介绍了,但是还是再记录一下。

驱动编写

如何创建驱动项目就不说了,上一篇说过了,直接进入正题。

老规矩,先在驱动的头文件定义好设备名称和IOCTL控制码,这是必须要的,不然用户态和内核态都找不到你的驱动设备,没有IOCTL码就无法在用户态调用驱动的功。

CTL_CODE不是函数,而是一个宏,用于生成I/O Control Code(IOCTL)

现在我们来编写主函数,也就是DriverEntry。

其实 DriverEntry 的基础功能也非常简单,注意我说的是基础功能,正规厂商发布的驱动肯定是复杂得多,我们只是学习,所以编写的 DriverEntry 只包含基本的功能即可。

第一句代码只是为了去除编译器的警告,可有可无,第二句代码就是定义一个驱动设备对象的指针,后面要用到。

下面代码是Windows 驱动开发中最核心、最基础的“注册回调函数”操作。

举个现实中的例子,如果把 Windows 操作系统比作一个“大公司的前台”,把你的驱动程序比作新入职的“员工”,那么这几行代码就是在填写员工职能表

你需要告诉操作系统(前台):“如果有这些事情发生,请去找那个函数处理。”

DriverObject 是操作系统在加载你的驱动时,发给你的一个表格(结构体)。这个表格里有很多空白的格子(函数指针),你需要往里面填入你写的函数的名字。

比如下面的代码,在内核注册了一个卸载驱动的函数,那么就是告诉Windows,如果有人要卸载这个驱动,请去加载 DriverUnload 函数,注意,这些注册的回调函数要我们自己在驱动里面写好才行。

DriverObject->DriverUnload = DriverUnload;

再比如下面的代码,在内核注册一个功能回调函数,这个函数的功能就是告诉系统有人“找”你时咋办。当应用层的软件(比如你写的一个 exe)调用 CreateFile 打开你的设备时,内核就会调用你注册的 CreateClose 函数,负责把门打开。

DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateClose;

注册完回调函数之后,我们就创建一个设备对象,相当于告诉内核,我要创建一个驱动啦。

API 原型如下。

最后就是创建符号链接,这里调用 IoCreateSymbolicLink API去把用户态和内核态的驱动名称链接起来。

API 原型如下。

总结一下 DriverEntry 函数的基础功能,无非就是三大件,注册回调函数 —> 创建设备对象 —> 创建符号链接。

接下来就是一些卸载驱动函数之类的编写了,这个直接复制粘贴就行。

剩下一个最重要的 DeviceControl 函数,这个函数是用来控制驱动要干什么的,简单来说你传对应的 IOCTL 码,这个函数就根据你传入的码去调用对应的功能函数。

首先获取用户态传过来的 I/O请求包的位置。

API 原型如下。

下面就是驱动的判断逻辑,解释一下代码。

  • stack:代表当前的IO 堆栈位置。也就是应用层发来的这次请求中,属于你这个驱动的那部分数据区域(上面我们通过IoGetCurrentIrpStackLocation获取到了)

  • Parameters.DeviceIoControl:这是一个联合体(Union)的一部分。意思是“我看的是 DeviceIoControl 这一类请求带来的参数”。

  • IoControlCode最关键的部分。这是IO 控制码

  • switch:C 语言的开关语句,用来根据这个码的不同,跳到不同的代码段执行。

当传过来的控制码等于我们定义的 My_IOCTL_Code 时就会调用我们定义好的 check_bug 函数。

这里补充一下check_bug 函数,就是往目标内存地址写入数据。

在调用 check_bug 函数前,还运行了下面的两行代码,这里也解释一下。

当应用层(EXE)通过 DeviceIoControl 发送指令给驱动时,它不仅会发送一个“功能号”(你是去干什么),还会附带一个“包裹”(具体要操作的数据)。Irp->AssociatedIrp.SystemBuffer指向一块地址,里面存放着刚才操作系统帮我们要来的数据。但是这个数据是一个混乱状态的,我们需要在前面加上 (PREQUEST) 把数据转为我们定义好的结构体。简单来说这句代码就相当于拆包裹,把拆出来的数据变成我们需要的格式。

PREQUEST request = (PREQUEST)Irp->AssociatedIrp.SystemBuffer;

这个结构体我们在驱动头文件进行定义,后续用户态传输数据也是通过这个结构体来的。

下面的这句代码是获取传过来的数据的大小,这里后续没有用到,可有可无。

  • stack:你之前的 IO 堆栈位置(你的任务单)。

  • InputBufferLength:代表应用层这次发过来了多少字节的数据

  • inputBufferSize:把这个长度存起来,供后面使用。

ULONG inputBufferSize = stack->Parameters.DeviceIoControl.InputBufferLength;

这三行代码是驱动处理请求的最后一步,通常被称为“完成 IRP 请求”。

第一行代码是填写任务状态,驱动需要告诉应用层(EXE),这次任务到底是做完了,还是出错了。

第二行代码是填写实际返回数据的字节数,这告诉操作系统:请从我的系统缓冲区里,把前 bytesReturned 个字节的数据,拷贝回应用层变量里去。如果不需要返回什么,直接返回 0 即可。

第三行代码是通知系统任务结束,把 IRP(请求包)交还给 I/O 管理器,调用这个函数后,这个 Irp 就不再属于你了,你不能再碰它里面的任何数据。

Loade编写

现在我们驱动编写完了,开始编写Loade去加载驱动。

Loade 的头文件直接导入驱动的头文件即可。

剩余的代码也是非常简单了,打开驱动文件,构造一个结构体,通过 DeviceIoControl 构造 I/O 请求包,向设备驱动发送 IOCTL 控制码,实现用户态对内核驱动的功能调用与数据交换。

DeviceIoControl API原型。

总结

驱动的构成不算复杂,主要是生成控制码,注册回调函数,创建设备对象,创建符号链接,按需编写功能函数,Loade 就更加简单了。

最后,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 12:42:42

Miniconda-Python3.9配置HTTPS反向代理保护Jupyter

Miniconda-Python3.9 配置 HTTPS 反向代理保护 Jupyter 在数据科学和 AI 开发日益普及的今天,越来越多团队选择将 Jupyter Notebook 部署为远程协作平台。然而,一个常见的误区是:只要服务器能连上,开发效率就提升了——却忽视了默…

作者头像 李华
网站建设 2026/4/16 14:27:06

如何更好地学习 Java(适合初学者)

Java 是一门强大且广泛使用的编程语言,适合初学者入门。掌握 Java 不仅能帮助理解编程基础,还能为后续学习更高级的技术打下扎实的基础。以下是几个关键的学习建议:打好基础语法学习任何编程语言,基础语法都是第一步。Java 的基础…

作者头像 李华
网站建设 2026/4/16 14:23:15

【git】git-transfer一行搞定仓库迁移

文章目录介绍使用场景可用命令单个迁移示例批量迁移自动创建gitea组织和仓库执行步骤新增特性支持的地址格式获取介绍 这是一个go语言编写的命令行git迁移工具:git-transfer。 特点: 快速迁移,保留完整branch和commits记录本地到远程批量迁…

作者头像 李华
网站建设 2026/4/15 15:26:49

python基于Vue框架的敦煌文化旅游管理系统的设计与实现_524q8_django Flask pycharm项目

目录已开发项目效果实现截图关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!已开发项目效果实现截图 同行可拿货,招校园代理 ,本人源头供货商 python基于Vue框架的敦煌文化旅游管理…

作者头像 李华
网站建设 2026/4/15 20:11:27

基于STM32的手势识别电机调速系统

基于STM32的手势识别电机调速系统 第一章 系统设计背景与需求分析 传统电机调速多依赖物理按键、旋钮或遥控器,存在操作接触限制、环境适应性弱等问题,在工业流水线、智能家居等场景中,频繁接触操作易导致效率降低或卫生隐患。手势识别技术凭…

作者头像 李华
网站建设 2026/4/16 10:17:15

WeGame下载安装教程 | 详细步骤与常见问题解决方案

前言 在 Windows 平台上,WeGame 是国内广泛使用的数字游戏分发与管理平台之一,为用户提供游戏下载、更新、存档同步以及社区互动等综合功能。对于刚开始接触 PC 游戏的用户,正确的下载安装步骤和环境配置往往决定了使用体验的流畅度。本文将…

作者头像 李华