news 2026/5/1 6:01:40

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/5/1 4:07:01

Miniconda-Python3.9运行强化学习PPO算法

Miniconda-Python3.9 运行强化学习 PPO 算法:构建高效、可复现的实验环境 在深度强化学习的研究与工程实践中,一个常见的痛点是:“代码没问题,但为什么在我机器上跑不通?”——这往往不是模型的问题,而是环…

作者头像 李华
网站建设 2026/5/1 4:05:02

六肽-3 (Hexapeptide-3)纤连蛋白的功能性仿生肽

六肽-3 (Hexapeptide-3) 综合介绍一、核心概述 六肽-3是纤连蛋白的功能性仿生肽。纤连蛋白是人体细胞外基质中至关重要的黏附糖蛋白,是细胞迁移、黏附、增殖及组织再生修复的核心蛋白。六肽-3的序列源于纤连蛋白的核心活性功能区域,精准保留了其生物活性…

作者头像 李华
网站建设 2026/5/1 4:08:26

珍藏必看:小白也能学会:个人电脑搭建专属AI大模型与知识库教程

文章详细介绍了如何在个人电脑上搭建本地AI大模型和知识库的完整过程。使用Ollama管理qwen3-vl模型,Cherry构建知识库,nomic-embed-text进行向量化处理,创建无需联网、保护隐私的专属AI助手,将个人资料转化为领域专用工具。AI大模…

作者头像 李华
网站建设 2026/5/1 5:06:50

9D影院设备厂家为球幕影院带来沉浸式观影新体验

随着科技的进步,9D影院设备厂家在提升观影体验方面发挥了重要作用。这些厂家致力于通过高效能视觉效果和互动功能,创造出更具沉浸感的观影环境。例如,采用球幕技术的设备使得观众可以在360度的视觉空间中感受影片情节,大幅增强了视…

作者头像 李华
网站建设 2026/5/1 8:30:30

Miniconda-Python3.9运行OCR识别模型实战

Miniconda-Python3.9 运行 OCR 识别模型实战 在智能文档处理日益普及的今天,从发票、合同到身份证件,海量纸质材料正通过 OCR(光学字符识别)技术被快速转化为结构化数据。然而,许多开发者都曾经历过这样的窘境&#xf…

作者头像 李华
网站建设 2026/5/1 6:03:12

基于STM32F1038T6单片机的汽车疲劳驾驶报警系统

基于STM32F1038T6单片机的汽车疲劳驾驶报警系统设计 一、系统总体设计 基于STM32F1038T6单片机的汽车疲劳驾驶报警系统以“实时监测、精准识别、主动预警”为核心目标,针对长途驾驶、夜间行车等易疲劳场景,通过监测驾驶员生理特征与驾驶行为,…

作者头像 李华