免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:4.Windows驱动-DbgPringtEx详解(驱动名、驱动卸载、驱动注册表)
首先创建一个MFC的项目,如下图右击选择新建项目

选择MFC应用,然后点击下一步

然后点击创建

根据下图选择完直接点击完成

然后添加一个按钮

然后双击下图红框的按钮

双击完写的代码

代码说明:
// ###########################################################################
// 宏定义:用户态访问内核驱动的符号链接路径(与内核驱动中的"三环符号"完全一致)
// 核心映射关系(必须重点理解):
// 内核态定义:L"\\??\\myhellWord" → 用户态实际访问路径:L"\\\\.\\myhellWord"
// 系统自动将用户态的 L"\\??\\" 映射为 L"\\\\.\\",因此两种写法等价
// 作用:用户态程序通过该路径找到内核中对应的设备对象(\\Device\\myhellWord)
// 注意:该宏必须与内核驱动中的"三环符号"完全一致,否则无法找到驱动设备
// ###########################################################################
#define 三环符号 L"\\??\\myhellWord"
// ###########################################################################
// MFC按钮点击事件处理函数:用户点击按钮时触发,核心功能是"用户态访问内核驱动"
// 作用:通过 CreateFile API 打开内核驱动创建的设备,建立用户态与内核态的通信通道
// 这是用户态程序与内核驱动交互的第一步(打开设备)
// ###########################################################################
void CMFCApplication1Dlg::OnBnClickedButton1()
{
// #######################################################################
// CreateFile:Windows核心API,用于打开/创建文件、设备、管道等对象
// 此处用于打开内核驱动创建的设备对象(用户态与内核态通信的核心入口)
// 参数详细说明(结合内核驱动场景):
// #######################################################################
HANDLE nDeviveHandle = CreateFile(
三环符号, // 参数1:设备路径(用户态符号链接,与内核驱动一致)
// 可取值:必须是内核驱动中 IoCreateSymbolicLink 创建的符号链接
// 等价写法:L"\\\\.\\myhellWord"(用户态更直观的写法,与三环符号等价)
GENERIC_READ | GENERIC_WRITE, // 参数2:访问权限(请求读+写权限)
// 可取值:
// GENERIC_READ → 读权限(对应内核 IRP_MJ_READ)
// GENERIC_WRITE → 写权限(对应内核 IRP_MJ_WRITE)
// 0 → 仅打开设备,无读写权限
// 注意:权限需与内核驱动的安全设置匹配,否则会返回权限不足(错误码5)
FILE_SHARE_READ, // 参数3:共享模式(允许其他进程同时读该设备)
// 可取值:
// FILE_SHARE_READ → 共享读
// FILE_SHARE_WRITE → 共享写
// FILE_SHARE_DELETE → 共享删除
// 0 → 独占访问(不允许其他进程打开)
NULL, // 参数4:安全属性(NULL=使用默认安全描述符)
// 内核驱动创建设备时若设置了安全属性,需在此匹配
OPEN_EXISTING, // 参数5:打开方式(必须设为"打开已存在的设备")
// 可取值:仅 OPEN_EXISTING 有效(设备是内核驱动创建的,已存在)
// 若设为 CREATE_NEW/CREATE_ALWAYS 会失败(错误码80:文件已存在)
FILE_ATTRIBUTE_NORMAL, // 参数6:文件/设备属性(普通属性,无特殊要求)
// 可取值:FILE_ATTRIBUTE_NORMAL(默认)、FILE_FLAG_OVERLAPPED(异步I/O)等
NULL // 参数7:模板文件句柄(设备访问无需模板,设为NULL)
);
// #######################################################################
// 格式化输出结果:显示设备句柄和错误码(排查打开失败的关键)
// 关键说明:
// - 若 nDeviveHandle == INVALID_HANDLE_VALUE(值为-1)→ 打开设备失败
// - GetLastError() → 获取失败原因(错误码对应具体问题,见下方注释)
// #######################################################################
char a[256];
sprintf_s(a, "am:nDeviveHandle = %d GetLastError = %d",
nDeviveHandle, // 设备句柄:非-1表示打开成功,后续可通过该句柄与驱动通信
GetLastError()); // 错误码:打开失败时的具体原因
// 弹窗显示结果(用户态直观查看是否打开成功)
MessageBoxA(0, a, 0, 0);
}
// ###########################################################################
// 关键补充注释(用户态与内核驱动通信的核心注意事项)
// ###########################################################################
// 1. 常见错误码及排查方向(结合之前的内核驱动):
// - 错误码 2(系统找不到指定文件):
// → 内核驱动未加载(未执行 sc create + sc start)
// → 内核驱动中 IoCreateSymbolicLink 调用失败(符号链接未创建)
// → 宏定义"三环符号"与内核驱动中的"三环符号"不一致(路径写错)
// - 错误码 5(拒绝访问):
// → CreateFile 的访问权限(如GENERIC_WRITE)内核驱动不允许
// → 内核驱动创建设备时设置了严格的安全属性(需在IoCreateDevice时指定FILE_ALL_ACCESS)
// → 程序未以管理员身份运行(用户态访问内核设备需管理员权限)
// - 错误码 1275(此驱动程序被阻止加载):
// → 内核驱动未签名,测试模式未开启(需执行 bcdedit /set testsigning on + 重启)
// → 安全引导未关闭(VMware需在虚拟机设置中禁用Secure Boot)
// - 错误码 32(另一个程序正在使用此文件):
// → 其他进程已独占打开该设备(CreateFile 共享模式设为0)
//
// 2. 成功条件(必须同时满足):
// - 内核驱动已加载(sc start 启动成功)
// - 内核驱动成功创建设备对象(IoCreateDevice 返回 STATUS_SUCCESS)
// - 内核驱动成功创建符号链接(IoCreateSymbolicLink 返回 STATUS_SUCCESS)
// - 测试模式已开启 + 驱动已自签名(或关闭驱动完整性校验)
// - MFC程序以管理员身份运行(右键→以管理员身份启动)
//
// 3. 后续通信:
// - 打开成功后,可通过 ReadFile(读驱动)、WriteFile(写驱动)、DeviceIoControl(控制驱动)与内核交互
// - 需内核驱动实现对应的 IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_DEVICE_CONTROL 处理函数
// ###########################################################################
驱动的代码

代码说明:
// 包含Windows内核驱动开发核心头文件
// 来源:Windows Driver Kit (WDK),提供内核API、数据结构(如NTSTATUS、PDRIVER_OBJECT)、宏定义
// 作用:驱动开发必备,所有内核函数/类型均依赖此头文件声明
#include "ntifs.h"
// ###########################################################################
// 驱动卸载函数:系统卸载驱动(sc stop 或关机)时自动调用
// 作用:释放驱动创建的资源(原代码未实现资源释放,需注意)
// 参数说明:
// _In_ struct _DRIVER_OBJECT* DriverObject:驱动对象指针
// - 来源:系统传入,指向当前被卸载的驱动对象
// - 作用:通过该对象可访问驱动创建的设备对象、符号链接等资源
// _In_ 标注:WDK定义的注解,表示该参数为"输入型"(仅读取,不修改)
// 注意:原代码未释放符号链接和设备对象,会导致资源泄漏(系统重启才能释放)
// ###########################################################################
VOID
MyUnload(
_In_ struct _DRIVER_OBJECT* DriverObject
) {
// DbgPrintEx:增强版内核调试打印(支持组件ID+调试级别过滤)
// 参数1:DPFLTR_IHVDRIVER_ID → 第三方驱动组件ID(预定义,来源dpfilter.h)
// 参数2:0 → 调试级别(0-31,数值越小优先级越高)
// 参数3:格式化字符串,%wZ → 专门打印UNICODE_STRING类型(驱动名称)
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "DbgPrintEx hello am 卸载 = %wZ\n", DriverObject->DriverName);
}
// ###########################################################################
// IRP_MJ_CREATE 处理函数:用户态程序调用 CreateFile 打开驱动设备时触发
// 作用:处理设备的"打开"请求(如权限校验、初始化等)
// 参数说明:
// _In_ struct _DEVICE_OBJECT* DeviceObject:被打开的设备对象指针
// - 来源:系统传入,指向用户态要打开的内核设备对象
// _Inout_ struct _IRP* Irp:I/O请求包(用户态请求的核心载体)
// - 来源:系统创建并传入,包含请求类型、参数、结果存储位置
// - _Inout_ 标注:输入输出型参数(读取请求信息,写入处理结果)
// 关键风险:原代码未设置 Irp->IoStatus 且未调用 IoCompleteRequest
// → 系统会一直等待该请求完成,导致用户态程序卡死、甚至系统蓝屏!
// ###########################################################################
NTSTATUS
MyCreate(
_In_ struct _DEVICE_OBJECT* DeviceObject,
_Inout_ struct _IRP* Irp
) {
// 打印设备创建(打开)日志,无其他处理逻辑
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "创建\n");
}
// ###########################################################################
// 宏定义:设备路径与用户态符号链接(内核态与用户态通信的关键标识)
// 1. 驱动符号(内核态设备路径):
// - 格式规范:\\Device\\[设备名](固定格式,设备名自定义)
// - 作用:内核态唯一标识设备,仅内核程序可见
// - 可取值:自定义设备名(需唯一,避免与系统设备冲突,如L"\\Device\\MyDriver")
// 2. 三环符号(用户态符号链接):
// - 格式规范:\\??\\[符号名](固定格式,符号名需与驱动设备名对应)
// - 作用:映射内核设备路径到用户态,用户态通过 \\.\myhellWord 访问该设备
// - 可取值:必须与驱动符号的设备名一致,仅前缀固定为\\??\\
// ###########################################################################
#define 驱动符号 L"\\Device\\myhellWord" // 内核态设备路径(唯一标识内核设备)
#define 三环符号 L"\\??\\myhellWord" // 用户态符号链接(用户态访问入口)
// ###########################################################################
// 驱动入口函数:系统加载驱动时优先调用(内核驱动的"main函数")
// 作用:初始化驱动核心配置(绑定卸载函数、IRP处理函数、创建设备/符号链接)
// 参数说明:
// PDRIVER_OBJECT DriverObject:驱动对象指针
// - 来源:系统创建并传入,代表当前加载的驱动本身
// - 核心作用:存储驱动配置(卸载函数、IRP处理函数数组、设备对象链表等)
// PUNICODE_STRING RegistryPath:驱动注册表路径
// - 来源:系统传入,对应驱动服务在注册表中的键路径(如L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\[驱动名]")
// - 作用:读取驱动的注册表配置(如启动参数、服务设置)
// 返回值:NTSTATUS → 驱动加载状态(STATUS_SUCCESS 表示加载成功)
// ###########################################################################
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
// 打印驱动名称(DriverObject->DriverName 是系统分配的驱动名)和注册表路径
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "DbgPrintEx hello am 驱动名字 = %wZ\n", DriverObject->DriverName);
KdPrintEx((DPFLTR_IHVDRIVER_ID, 0, "KdPrintEx hello am 注册表2222 = %wZ\n", RegistryPath));
// 绑定驱动卸载函数:告知系统驱动卸载时要执行的函数(必须设置,否则无法正常卸载)
DriverObject->DriverUnload = MyUnload;
// 绑定 IRP_MJ_CREATE 处理函数:
// MajorFunction 是IRP处理函数数组,下标为IRP请求类型,值为对应处理函数地址
// 下标 IRP_MJ_CREATE → 对应"打开设备"请求,触发 MyCreate 函数
// 常见IRP类型可取值(WDK预定义):
// IRP_MJ_CREATE → 打开设备(本示例用)
// IRP_MJ_CLOSE → 关闭设备
// IRP_MJ_READ → 读取设备数据
// IRP_MJ_WRITE → 写入设备数据
// IRP_MJ_DEVICE_CONTROL → 设备控制(用户态DeviceIoControl调用)
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreate;
UNICODE_STRING uString; // 存储内核态设备路径的UNICODE字符串(需初始化后使用)
DEVICE_OBJECT uDevice_Object; // 设备对象(原代码此处定义为局部变量,存在严重错误!)
// 初始化UNICODE字符串:绑定到"驱动符号"(内核态设备路径)
// RtlInitUnicodeString:WDK提供的内核API,用于初始化UNICODE_STRING类型
RtlInitUnicodeString(&uString, 驱动符号);
// 创建设备对象:内核态与用户态通信的核心载体
// IoCreateDevice:WDK提供的内核API,用于创建内核设备对象
// 参数说明:
// 参数1:DriverObject → 设备所属的驱动对象
// 参数2:sizeof(DriverObject->DriverExtension) → 设备扩展大小(原代码错误!应为自定义设备扩展大小,无需则设为0)
// 正确用法:设备扩展是用户自定义的附加数据结构大小,与DriverExtension(驱动扩展)无关
// 参数3:&uString → 设备路径(内核态可见)
// 参数4:FILE_DEVICE_UNKNOWN → 设备类型(预定义可取值见下方)
// 参数5:FILE_DEVICE_SECURE_OPEN → 设备特性标志(表示设备需要安全访问校验)
// 参数6:FALSE → 是否独占设备(FALSE=允许多进程同时打开,TRUE=仅单进程打开)
// 参数7:&uDevice_Object → 输出参数,接收创建的设备对象指针(原代码错误!应为PDEVICE_OBJECT类型指针)
// 设备类型(参数4)预定义可取值(WDK提供):
// FILE_DEVICE_UNKNOWN → 未知设备(通用设备,本示例用)
// FILE_DEVICE_DISK → 磁盘设备
// FILE_DEVICE_KEYBOARD → 键盘设备
// FILE_DEVICE_MOUSE → 鼠标设备
// FILE_DEVICE_NETWORK → 网络设备
NTSTATUS uStatus = IoCreateDevice(DriverObject, sizeof(DriverObject->DriverExtension),&uString, FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&uDevice_Object);
if (uStatus == STATUS_SUCCESS) { // 检查设备对象创建是否成功
UNICODE_STRING uThreeString; // 存储用户态符号链接路径的UNICODE字符串
RtlInitUnicodeString(&uThreeString, 三环符号); // 初始化符号链接路径
// 创建用户态符号链接:映射内核设备路径到用户态,让用户态程序可访问
// IoCreateSymbolicLink:WDK提供的内核API,用于创建符号链接
// 参数1:&uThreeString → 用户态符号链接路径(三环符号)
// 参数2:&uString → 对应的内核态设备路径(驱动符号)
uStatus = IoCreateSymbolicLink(&uThreeString, &uString);
if (uStatus == STATUS_SUCCESS) { // 检查符号链接创建是否成功
// DbgPrintEx 参数1设为77(自定义组件ID,未注册,调试器需特殊配置才能显示)
DbgPrintEx(77, 0, "IoCreateSymbolicLink 成功\n");
}
else {
DbgPrintEx(77, 0, "IoCreateSymbolicLink 失败\n");
}
}
else {
DbgPrintEx(77, 0, "IoCreateDevice 失败\n");
}
// 返回驱动加载状态:STATUS_SUCCESS 表示驱动加载成功(系统会认为驱动初始化完成)
return STATUS_SUCCESS;
}
// ###########################################################################
// 原代码关键风险标注(仅提醒,不修改代码)
// ###########################################################################
// 1. 设备对象定义错误:DEVICE_OBJECT uDevice_Object 是局部变量,IoCreateDevice 要求传入 PDEVICE_OBJECT(指针)
// → 会导致编译错误或运行时蓝屏(系统无法写入创建的设备对象)
// 2. IoCreateDevice 设备扩展大小错误:sizeof(DriverObject->DriverExtension) 是驱动扩展大小,而非设备扩展
// → 设备扩展内存分配错误,可能导致后续访问非法内存
// 3. MyCreate 函数未处理IRP:未设置 Irp->IoStatus.Status 和 Irp->IoStatus.Information,未调用 IoCompleteRequest
// → 用户态调用 CreateFile 后卡死,系统等待IRP完成超时蓝屏
// 4. 卸载函数未释放资源:未调用 IoDeleteSymbolicLink 和 IoDeleteDevice
// → 驱动卸载后设备对象和符号链接残留,资源泄漏(需重启系统释放)
// 5. DbgPrintEx 组件ID为77(未注册):调试器默认无法过滤显示该组件日志,需手动注册或改用预定义ID
// ###########################################################################
效果图:未点击下图蓝框的按钮时打印的内容,也就是三环还未访问驱动

点击按钮之后,成功从三环访问到了零环,注意当前的代码没有清理逻辑,所以只能通过重启的方式清理


25

被折叠的 条评论
为什么被折叠?



