驱动的入口点函数为DriverEntry() 函数,函数在调用时会默认传入两个参数,分别是驱动对象指针(PDRIVER_OBJECT)和驱动注册路径(PUNICODE_STRING),驱动对象指针顾名思义是指代指向驱动对象的指针对象,而驱动注册路径是指驱动在注册表中注册的具体路径。
驱动对象成员DriverUnload 指向驱动卸载回调函数,当驱动停止并卸载时该函数会启动。
为驱动创建设备使用到的函数未IoCreateDevice(), 函数定义如下:
创建驱动设备对象源码:
驱动设备对象创建使用IoCreateDevice 函数,创建好的驱动设备对象可以由驱动对象指针指出,指出的该对象与函数创建时返回的对象为同一个对象。IoCreateDevice 函数返回为STATUS_SUCCESS 是表示创建驱动设备对象成功。驱动设备对象名称格式为"\DEVICE\YOUR_DEVICE_NAME",其中,DEVICE 可小写。驱动在卸载的时候需要调用IoDeleteDevice 函数删除驱动设备对象。驱动设备对象是供内核层(R0)调用时使用的,在用户层(R3)调用驱动使用的是驱动符号链接。
驱动设备对象无法在用户层得到调用,要实现在用户层实现对驱动的控制,需要为驱动绑定符号链接。通过使用IoCreateSysbolicLink 函数为驱动绑定符号链接。函数原型如下:
通常在调用IoCreateDevice 创建设备对象的时候回传入设备名称,这个设备名称只能在内核层使用,只能被内核层的函数识别。如果IoCreateDevice 中没有指定设备名称,那么I/O管理器会自动分配一个数字作为设备的名称。例如"\Device\00000001"。
如果想要在用户层的应用程序中访问(比如调用CreateFile 函数打开),就需要创建符号链接,相当于为设备对象创建一个别名,供应用程序访问。应用层是无法直接通过设备名字来打开对象的,必须建立一个暴露给应用程序的符号链接。
比如:C盘的符号链接名称是"C:",对应的设备名称是"\Device\HarddiskVolume1"。
驱动创建符号链接代码:
在用户层对驱动符号链接进行操作时,会产生相应的IRP 事件,在驱动内对IRP 进行操作,实现用户层对驱动的操作。
实现对IRP 事件的处理需要使用到派遣函数:
在驱动内对特定的事件绑定派遣回调函数:
具体实现代码:
在代码中,派遣函数定义了一个,并且在派遣函数内部通过IoGetCurrentIrpStackLocation 函数获取了具体的IRP 事件进行不同的执行。在驱动入口函数内,使用:
指定了对应事件[IRP_TYPE] 所需要执行的派遣函数FUNC。派遣函数不唯一,不同的IRP 事件也可以指向不同的IRP 函数。
上面说到了驱动层处理用户层调用时产生的IRP 事件的方式--派遣函数。在用户层通过对之前为驱动绑定的符号链接进行操作实现对驱动的操作。所使用到的函数为CreateFile():
使用CreateFile 函数对驱动设备打开并执行后续操作。使用CloseHandle 函数关闭对驱动的使用:
具体代码:
// 驱动层代码即上一次编写的代码
// 用户层代码
实现驱动层(R0)和用户层(R3)通信,是实现用户层对驱动层控制的重要方式,实现驱动层与用户层通信可以使用以下API 函数:
驱动在调用过程中使用的InsDrv.exe 工具实现安装驱动、开启驱动、停止驱动和卸载驱动,但是在正常的执行过程中,上述步骤是放在代码中来实现的。
SSDT 的全称是System Services Descriptor Table, 系统服务描述表。这个表就是一个吧Ring3 的Win32 API 和Ring0 内核API 联系起来。
SSDT 并不仅仅只包含一个庞大的地址索引表,它还包含一些其他应用的信息,如:地址索引的基址、服务函数个数等。
通过修改此表的函数地址可以对常用的Windows 函数及API 进行HOOK,从而实现对一些关心的系统动作进行过滤、监控的目的。一些HIPS(主机入侵防御系统)、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。
SSDT 即系统服务描述表,它的结构如下:
内核中有两个系统服务描述符表,一个是KeServiceDescriptorTable(由ntoskrnl.exe导出),一个是KeServieDescriptorTableShadow(没有导出)。
两者的区别是,KeServiceDescriptorTable仅有ntoskrnel一项,KeServieDescriptorTableShadow包含了ntoskrnel以及win32k。一般的Native API(原生API)的服务地址由KeServiceDescriptorTable分派,gdi.dll/user.dll的内核API调用服务地址由KeServieDescriptorTableShadow分派。还有要清楚一点的是win32k.sys只有在GUI线程中才加载,一般情况下是不加载的,所以要Hook KeServieDescriptorTableShadow的话,一般是用一个GUI程序通过IoControlCode来触发(想当初不明白这点,蓝屏死机了N次都想不明白是怎么回事)。(此段摘抄自网络)
内核HOOK 分类:
首先是关于内核函数地址是怎么计算的。这里以NtOpenProcess 为例:
首先是要IDA 加载ntdll.dll, 查找NtOpenProcess 查看函数对应的SystemId,这个值可以理解为地址表内的一个下标。
查看KeServiceDescriptorTable(服务描述表):
是要WinDbg 调试本地内核或者双调试,执行命令
所得到的0x83EBDD9C 值就指向函数表首地址的指针,如下:
利用函数表首地址和SystemId(下标)计算出目标函数 (NtOpenProcess)函数对应的地址。
上述就是计算NtOpenProcess 函数地址的方式。那么样实现HOOK 该函数,就是将最后得出的地址0x840529DC 替换成自己的函数地址。
https://bbs.pediy.com/thread-40832.htm
实现对SSDT 表的修改,首先要确保这个表示可写的。可以通过以下3种方法实现对SSDT 的内存保护机制的修改。
修改方式:
修改注册表
改变CR0 寄存器的第一位
Windows对内存的分配,是采用的分页管理。其中有个CR0寄存器,如下图:
其中第一位叫做保护属性位,控制着页的读写属性。如果为1,则页面可进行读写和执行,如果为0,则只能进行读和执行操作。SSDT, IDT 的页属性默认情况下是只读可执行的。
//设置为不可写
void DisableWrite()
{
__try
{
}
__except(1)
{
}
}
// 设置为可写
void EnableWrite()
{
__try
{
}
__except(1)
{
}
}
SSDT HOOK 代码框架
编写驱动前环境设置(仅为不使用框架时使用)
1.
属性
-
> C
/
C
+
+
-
> 警告等级 : 等级
3
/
W3
2.
属性
-
> C
/
C
+
+
-
> 将警告视为错误 : 否
3.
属性
-
> Inf2Cat
-
> Run Inf2Cat : 否
4.
属性
-
> Driver Settings
-
> Target Os Version : 设置对应的系统版本
5.
属性
-
> Driver Settings
-
> Target PlaForm : Desktop
6.
属性
-
> StampInf
-
> Enable ArchiteCture : 否
编写驱动前环境设置(仅为不使用框架时使用)
1.
属性
-
> C
/
C
+
+
-
> 警告等级 : 等级
3
/
W3
2.
属性
-
> C
/
C
+
+
-
> 将警告视为错误 : 否
3.
属性
-
> Inf2Cat
-
> Run Inf2Cat : 否
4.
属性
-
> Driver Settings
-
> Target Os Version : 设置对应的系统版本
5.
属性
-
> Driver Settings
-
> Target PlaForm : Desktop
6.
属性
-
> StampInf
-
> Enable ArchiteCture : 否
/
/
驱动头文件
void DriverUnload(PDRIVER_OBJECT obj)
{
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
return
status;
}
/
/
驱动头文件
void DriverUnload(PDRIVER_OBJECT obj)
{
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
return
status;
}
NTSTATUS IoCreateDevice
(
IN PDRIVER_OBJECT DriverObject,
/
/
驱动对象
IN ULONG DeviceExtensionSize,
/
/
指定驱动程序为设备扩展对象而
/
/
定义的结构体的大小.
IN PUNICODE_STRING DeviceName OPTIONAL,
/
/
设备名称,只能在内
/
/
核层使用
IN DEVICE_TYPE DeviceType,
/
/
设备类型
IN ULONG DeviceCharacteristics,
/
/
大多数驱动程序为此参数指定
/
/
FILE_DEVICE_SECURE_OPEN。,指定一个或多个系统定义的常量,连
/
/
接在一起,提供有关驱动程序的设备其他信息.对于可能的设备特征信
/
/
息
IN BOOLEAN Exclusive,
/
/
如果指定设备是独占的,大部分驱动程序设
/
/
置这个值为FALSE,如果是独占的话设置为TRUE,非独占设置为FALSE.
OUT PDEVICE_OBJECT
*
DeviceObject
/
/
一个指向DEVICE_OBJECT结构
/
/
体指针的指针,这是一个指针的指针,指向的指针用来接收
/
/
DEVICE_OBJECT结构体的指针,返回创建的设备对象,在卸载驱动的时
/
/
候,需要对这个设备对象进行删除:IoDeleteDevice()
);
独占就是在用户层(R3)使用CreateFile 获取驱动句柄只能进行
一次,再次获取需要对之前的句柄进行释放。而非独占可以多次获取
该驱动的句柄
其中,设备驱动类型可以取如下的值:
NTSTATUS IoCreateDevice
(
IN PDRIVER_OBJECT DriverObject,
/
/
驱动对象
IN ULONG DeviceExtensionSize,
/
/
指定驱动程序为设备扩展对象而
/
/
定义的结构体的大小.
IN PUNICODE_STRING DeviceName OPTIONAL,
/
/
设备名称,只能在内
/
/
核层使用
IN DEVICE_TYPE DeviceType,
/
/
设备类型
IN ULONG DeviceCharacteristics,
/
/
大多数驱动程序为此参数指定
/
/
FILE_DEVICE_SECURE_OPEN。,指定一个或多个系统定义的常量,连
/
/
接在一起,提供有关驱动程序的设备其他信息.对于可能的设备特征信
/
/
息
IN BOOLEAN Exclusive,
/
/
如果指定设备是独占的,大部分驱动程序设
/
/
置这个值为FALSE,如果是独占的话设置为TRUE,非独占设置为FALSE.
OUT PDEVICE_OBJECT
*
DeviceObject
/
/
一个指向DEVICE_OBJECT结构
/
/
体指针的指针,这是一个指针的指针,指向的指针用来接收
/
/
DEVICE_OBJECT结构体的指针,返回创建的设备对象,在卸载驱动的时
/
/
候,需要对这个设备对象进行删除:IoDeleteDevice()
);
独占就是在用户层(R3)使用CreateFile 获取驱动句柄只能进行
一次,再次获取需要对之前的句柄进行释放。而非独占可以多次获取
该驱动的句柄
其中,设备驱动类型可以取如下的值:
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
}
return
status;
}
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
}
return
status;
}
NTSTATUS IoCreateSymbolicLink(
PUNICODE_STRING SymbolicLinkName,
/
/
符号链接名称,
unicode
字符串
PUNICODE_STRING DeviceName
/
/
设备名称
);
NTSTATUS IoCreateSymbolicLink(
PUNICODE_STRING SymbolicLinkName,
/
/
符号链接名称,
unicode
字符串
PUNICODE_STRING DeviceName
/
/
设备名称
);
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
NTSTATUS DriverIRPCtl(PDEVICE_OBJECT obj, PIRP pIrp)
{
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
KdPrint((
"进入派遣函数"
));
/
/
获取用户层调用时产生的具体的IRP 事件
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断不同的IRP 事件
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
/
/
用户层开启了驱动
{
KdPrint((
"用户层调用了CreateFile()"
));
};
break
;
case IRP_MJ_CLOSE:
/
/
用户层关闭了驱动
{
KdPrint((
"用户层调用了CloseHandle()"
));
}
default:
break
;
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
/
/
返回给DeviceIoControl 中的倒数第二个参数lpBytesReturned
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint((
"退出派遣函数"
));
return
STATUS_SUCCESS;
}
NTSTATUS DriverIRPCtl(PDEVICE_OBJECT obj, PIRP pIrp)
{
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
KdPrint((
"进入派遣函数"
));
/
/
获取用户层调用时产生的具体的IRP 事件
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断不同的IRP 事件
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
/
/
用户层开启了驱动
{
KdPrint((
"用户层调用了CreateFile()"
));
};
break
;
case IRP_MJ_CLOSE:
/
/
用户层关闭了驱动
{
KdPrint((
"用户层调用了CloseHandle()"
));
}
default:
break
;
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
/
/
返回给DeviceIoControl 中的倒数第二个参数lpBytesReturned
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint((
"退出派遣函数"
));
return
STATUS_SUCCESS;
}
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtl;
/
/
指定驱动打开的派遣函数
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtl;
/
/
指定驱动关闭的派遣函数
/
/
派遣函数可以为多个,也可以指定应该。不同的是当指定应该函数时,需要
/
/
对传入的IRP 事件进行判断
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtl;
/
/
指定驱动打开的派遣函数
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtl;
/
/
指定驱动关闭的派遣函数
/
/
派遣函数可以为多个,也可以指定应该。不同的是当指定应该函数时,需要
/
/
对传入的IRP 事件进行判断
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
};
break
;
default:
break
;
}
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
/
/
为IRP 事件指定派遣函数,指定的派遣函数可以为不同的事件不同的函数
/
/
当用户层调用CreateFile 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtrl;
/
/
当用户层调用CloseHandle 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtrl;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
};
break
;
default:
break
;
}
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
/
/
为IRP 事件指定派遣函数,指定的派遣函数可以为不同的事件不同的函数
/
/
当用户层调用CreateFile 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtrl;
/
/
当用户层调用CloseHandle 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtrl;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
obj
-
>MajorFunction[IRP_TYPE]
=
FUNC;
obj
-
>MajorFunction[IRP_TYPE]
=
FUNC;
HANDLE CreateFile(
LPCTSTR lpFileName,
/
/
文件名称,这里指符号链接名称
DWORD dwDesiredAccess,
/
/
读取权限
DWORD dwShareMode,
/
/
共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
/
/
安全属性
DWORD dwCreationDisposition,
/
/
创建方式
DWORD dwFlagsAndAttributes,
/
/
文件属性
HANDLE hTemplateFile
/
/
复制文件所使用的句柄
);
HANDLE CreateFile(
LPCTSTR lpFileName,
/
/
文件名称,这里指符号链接名称
DWORD dwDesiredAccess,
/
/
读取权限
DWORD dwShareMode,
/
/
共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
/
/
安全属性
DWORD dwCreationDisposition,
/
/
创建方式
DWORD dwFlagsAndAttributes,
/
/
文件属性
HANDLE hTemplateFile
/
/
复制文件所使用的句柄
);
BOOL
CloseHandle(
HANDLE hObject
/
/
对象句柄
);
BOOL
CloseHandle(
HANDLE hObject
/
/
对象句柄
);
/
/
驱动对象句柄
HANDLE hDriver
=
(HANDLE)
0xFFFFFFFF
;
/
/
驱动对象句柄
HANDLE hDriver
=
(HANDLE)
0xFFFFFFFF
;
/
/
开始驱动调用
void CR3AppForMyDriverDlg::OnBnClickedBtnCreate()
{
/
/
TODO: 创建驱动的调用
hDriver
=
CreateFile(
DRIVER_SYMBOLLINK_NAME,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
TRACE(
"JJR:R3 获取驱动句柄成功:0x%08X"
, hDriver);
}
}
/
/
结束驱动调用
void CR3AppForMyDriverDlg::OnBnClickedBtnClose()
{
/
/
TODO: 结束驱动的调用
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
CloseHandle(hDriver);
TRACE(
"JJR:R3 结束对驱动调用成功"
);
hDriver
=
(HANDLE)
0xFFFFFFFF
;
}
}
/
/
开始驱动调用
void CR3AppForMyDriverDlg::OnBnClickedBtnCreate()
{
/
/
TODO: 创建驱动的调用
hDriver
=
CreateFile(
DRIVER_SYMBOLLINK_NAME,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
TRACE(
"JJR:R3 获取驱动句柄成功:0x%08X"
, hDriver);
}
}
/
/
结束驱动调用
void CR3AppForMyDriverDlg::OnBnClickedBtnClose()
{
/
/
TODO: 结束驱动的调用
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
CloseHandle(hDriver);
TRACE(
"JJR:R3 结束对驱动调用成功"
);
hDriver
=
(HANDLE)
0xFFFFFFFF
;
}
}
BOOL
WriteFile(
HANDLE hFile,
/
/
句柄
LPCVOID lpBuffer,
/
/
缓冲区
DWORD nNumberOfBytesToWrite,
/
/
缓冲区大小
LPDWORD lpNumberOfBytesWritten,
/
/
实际写入的字节数
LPOVERLAPPED lpOverlapped
/
/
OVERLAPPED 结构指针
);
BOOL
ReadFile(
HANDLE hFile,
/
/
句柄
LPVOID lpBuffer,
/
/
缓冲区
DWORD nNumberOfBytesToRead,
/
/
缓冲区大小
LPDWORD lpNumberOfBytesRead,
/
/
实际读取的字节数
LPOVERLAPPED lpOverlapped
/
/
OVERAPPED 结构指针
);
BOOL
WINAPI DeviceIoControl(
__in HANDLE hDevice,
/
/
需要执行操作的句柄
__in DWORD dwIoControlCode,
/
/
操作的控制代码。
/
/
该值标识要执行的特定操作以及要在其上执行的设备的类型
__in_opt LPVOID lpInBuffer,
/
/
指向包含执行操作所需
/
/
的数据的输入缓冲区的指针
__in DWORD nInBufferSize,
/
/
输入缓冲区的大小,
/
/
以字节为单位。
__out_opt LPVOID lpOutBuffer,
/
/
指向要接收操作返回的
/
/
数据的输出缓冲区的指针
__in DWORD nOutBufferSize,
/
/
输出缓冲区的大小,
/
/
以字节为单位。
__out_opt LPDWORD lpBytesReturned,
/
/
指向变量的指针,
/
/
该变量接收以字节为单位的输出缓冲区中存储的数据大小.
__inout_opt LPOVERLAPPED lpOverlapped
/
/
指向OVERLAPPED
/
/
结构的指针。
);
BOOL
WriteFile(
HANDLE hFile,
/
/
句柄
LPCVOID lpBuffer,
/
/
缓冲区
DWORD nNumberOfBytesToWrite,
/
/
缓冲区大小
LPDWORD lpNumberOfBytesWritten,
/
/
实际写入的字节数
LPOVERLAPPED lpOverlapped
/
/
OVERLAPPED 结构指针
);
BOOL
ReadFile(
HANDLE hFile,
/
/
句柄
LPVOID lpBuffer,
/
/
缓冲区
DWORD nNumberOfBytesToRead,
/
/
缓冲区大小
LPDWORD lpNumberOfBytesRead,
/
/
实际读取的字节数
LPOVERLAPPED lpOverlapped
/
/
OVERAPPED 结构指针
);
BOOL
WINAPI DeviceIoControl(
__in HANDLE hDevice,
/
/
需要执行操作的句柄
__in DWORD dwIoControlCode,
/
/
操作的控制代码。
/
/
该值标识要执行的特定操作以及要在其上执行的设备的类型
__in_opt LPVOID lpInBuffer,
/
/
指向包含执行操作所需
/
/
的数据的输入缓冲区的指针
__in DWORD nInBufferSize,
/
/
输入缓冲区的大小,
/
/
以字节为单位。
__out_opt LPVOID lpOutBuffer,
/
/
指向要接收操作返回的
/
/
数据的输出缓冲区的指针
__in DWORD nOutBufferSize,
/
/
输出缓冲区的大小,
/
/
以字节为单位。
__out_opt LPDWORD lpBytesReturned,
/
/
指向变量的指针,
/
/
该变量接收以字节为单位的输出缓冲区中存储的数据大小.
__inout_opt LPOVERLAPPED lpOverlapped
/
/
指向OVERLAPPED
/
/
结构的指针。
);
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
驱动层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_DEVICE_CONTROL:
{
/
/
获取控制码
ULONG funcCode
=
pIoStackLocation
-
>Parameters.DeviceIoControl.IoControlCode;
if
(funcCode
=
=
IO_TEST_CODE)
{
KdPrint((
"JJR:用户层调用了DeviceIoControl 函数"
));
/
/
取出传入的缓冲区数据和大小
char
*
inBuffer
=
(char
*
)pIrp
-
>AssociatedIrp.SystemBuffer;
KdPrint((
"JJR:用户层传入数据:%s"
, inBuffer));
/
/
inBuffer 既是传入数据的缓冲区,也是传出数据的缓冲区
strcpy(inBuffer,
"驱动层传出数据"
);
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
/
/
实际传出缓冲区的大小
pIrp
-
>IoStatus.Information
=
pIoStackLocation
-
>Parameters.DeviceIoControl.InputBufferLength;
};
break
;
default:
break
;
}
KdPrint((
"JJR:退出派遣函数"
));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
/
/
为IRP 事件指定派遣函数,指定的派遣函数可以为不同的事件不同的函数
/
/
当用户层调用CreateFile 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtrl;
/
/
当用户层调用CloseHandle 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtrl;
obj
-
>MajorFunction[IRP_MJ_DEVICE_CONTROL]
=
DriverIRPCtrl;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
用户层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
定义的控制码
void CR3AppForMyDriverDlg::OnBnClickedBtnMsgDevicecontrol()
{
/
/
TODO: 使用Devicecontrol 实现驱动层和用户层通信
UpdateData(TRUE);
TRACE(
"JJR:%s"
, CStringToPChar(m_R0Text));
TRACE(
"JJR:%s"
, CStringToPChar(m_R3Text));
char szpTest[
256
]
=
{
0
};
strcpy_s(szpTest, sizeof(szpTest), CStringToPChar(m_R3Text));
char szpResult[
256
]
=
{
0
};
DWORD nSize
=
0
;
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
if
(DeviceIoControl(
hDriver,
IO_TEST_CODE,
szpTest,
sizeof(szpTest),
szpResult,
sizeof(szpResult),
&nSize,
NULL
))
{
m_R0Text
=
PCharToCString(szpResult);
UpdateData(FALSE);
}
}
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
驱动层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_DEVICE_CONTROL:
{
/
/
获取控制码
ULONG funcCode
=
pIoStackLocation
-
>Parameters.DeviceIoControl.IoControlCode;
if
(funcCode
=
=
IO_TEST_CODE)
{
KdPrint((
"JJR:用户层调用了DeviceIoControl 函数"
));
/
/
取出传入的缓冲区数据和大小
char
*
inBuffer
=
(char
*
)pIrp
-
>AssociatedIrp.SystemBuffer;
KdPrint((
"JJR:用户层传入数据:%s"
, inBuffer));
/
/
inBuffer 既是传入数据的缓冲区,也是传出数据的缓冲区
strcpy(inBuffer,
"驱动层传出数据"
);
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
/
/
实际传出缓冲区的大小
pIrp
-
>IoStatus.Information
=
pIoStackLocation
-
>Parameters.DeviceIoControl.InputBufferLength;
};
break
;
default:
break
;
}
KdPrint((
"JJR:退出派遣函数"
));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
/
/
为IRP 事件指定派遣函数,指定的派遣函数可以为不同的事件不同的函数
/
/
当用户层调用CreateFile 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtrl;
/
/
当用户层调用CloseHandle 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtrl;
obj
-
>MajorFunction[IRP_MJ_DEVICE_CONTROL]
=
DriverIRPCtrl;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
用户层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
定义的控制码
void CR3AppForMyDriverDlg::OnBnClickedBtnMsgDevicecontrol()
{
/
/
TODO: 使用Devicecontrol 实现驱动层和用户层通信
UpdateData(TRUE);
TRACE(
"JJR:%s"
, CStringToPChar(m_R0Text));
TRACE(
"JJR:%s"
, CStringToPChar(m_R3Text));
char szpTest[
256
]
=
{
0
};
strcpy_s(szpTest, sizeof(szpTest), CStringToPChar(m_R3Text));
char szpResult[
256
]
=
{
0
};
DWORD nSize
=
0
;
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
if
(DeviceIoControl(
hDriver,
IO_TEST_CODE,
szpTest,
sizeof(szpTest),
szpResult,
sizeof(szpResult),
&nSize,
NULL
))
{
m_R0Text
=
PCharToCString(szpResult);
UpdateData(FALSE);
}
}
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
驱动层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_DEVICE_CONTROL:
{
/
/
获取控制码
ULONG funcCode
=
pIoStackLocation
-
>Parameters.DeviceIoControl.IoControlCode;
if
(funcCode
=
=
IO_TEST_CODE)
{
KdPrint((
"JJR:用户层调用了DeviceIoControl 函数"
));
/
/
取出传入的缓冲区数据和大小
char
*
inBuffer
=
(char
*
)pIrp
-
>AssociatedIrp.SystemBuffer;
KdPrint((
"JJR:用户层传入数据:%s"
, inBuffer));
/
/
inBuffer 既是传入数据的缓冲区,也是传出数据的缓冲区
strcpy(inBuffer,
"驱动层传出数据"
);
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
/
/
实际传出缓冲区的大小
pIrp
-
>IoStatus.Information
=
pIoStackLocation
-
>Parameters.DeviceIoControl.InputBufferLength;
};
break
;
case IRP_MJ_WRITE:
{
KdPrint((
"JJR:用户层调用了WriteFile 函数"
));
char
*
inBuffer
=
(char
*
)pIrp
-
>UserBuffer;
KdPrint((
"JJR:传递的数据>> %s"
, inBuffer));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_READ:
{
KdPrint((
"JJR:用户层调用了ReadFile 函数"
));
char
*
inBuffer
=
(char
*
)pIrp
-
>UserBuffer;
KdPrint((
"JJR:传递的数据>> %s"
, inBuffer));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
}
default:
break
;
}
KdPrint((
"JJR:退出派遣函数"
));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
}
/
/
为驱动创建设备对象
NTSTATUS createDevice(PDRIVER_OBJECT obj)
{
/
/
定义驱动对象名称
UNICODE_STRING deviceName;
NTSTATUS status
=
STATUS_SUCCESS;
/
/
初始化驱动设备名称
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
/
/
驱动对象
DEVICE_OBJECT deviceObj;
status
=
IoCreateDevice(
obj,
0x4
,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObj
);
return
status;
}
/
/
为驱动绑定符号链接
NTSTATUS createSymbolLink()
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
/
/
驱动设备名称
UNICODE_STRING deviceName;
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
status
=
IoCreateSymbolicLink(&SymbolLinkName, &deviceName);
return
status;
}
/
/
驱动入口点
NTSTATUS DriverEntry(
/
*
驱动对象
*
/
PDRIVER_OBJECT obj,
/
*
驱动注册路径
*
/
PUNICODE_STRING registePath)
{
NTSTATUS status
=
STATUS_SUCCESS;
KdPrint((
"JJR:驱动安装函数启动"
));
/
/
指定卸载函数
obj
-
>DriverUnload
=
DriverUnload;
/
/
为IRP 事件指定派遣函数,指定的派遣函数可以为不同的事件不同的函数
/
/
当用户层调用CreateFile 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CREATE]
=
DriverIRPCtrl;
/
/
当用户层调用CloseHandle 函数时产生的IRP 事件
obj
-
>MajorFunction[IRP_MJ_CLOSE]
=
DriverIRPCtrl;
obj
-
>MajorFunction[IRP_MJ_DEVICE_CONTROL]
=
DriverIRPCtrl;
obj
-
>MajorFunction[IRP_MJ_WRITE]
=
DriverIRPCtrl;
obj
-
>MajorFunction[IRP_MJ_READ]
=
DriverIRPCtrl;
if
(createDevice(obj)
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动设备创建成功"
));
if
(createSymbolLink()
=
=
STATUS_SUCCESS)
{
KdPrint((
"JJR:驱动符号链接创建成功"
));
}
}
return
status;
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
用户层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
void CR3AppForMyDriverDlg::OnBnClickedBtnMsgWritefile()
{
/
/
TODO: 使用WriteFile 向驱动层通信
UpdateData(TRUE);
char szpTest[
256
]
=
{
0
};
strcpy_s(szpTest, sizeof(szpTest), CStringToPChar(m_R3Text));
char szpResult[
256
]
=
{
0
};
DWORD nSize
=
0
;
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
if
(WriteFile(
hDriver,
szpTest,
strlen(szpTest),
&nSize,
NULL
))
{
TRACE(
"JJR:执行成功"
);
}
}
}
void CR3AppForMyDriverDlg::OnBnClickedBtnMsgReadfile()
{
/
/
TODO: 使用WriteFile 向驱动层通信
UpdateData(TRUE);
char szpTest[
256
]
=
{
0
};
strcpy_s(szpTest, sizeof(szpTest), CStringToPChar(m_R3Text));
char szpResult[
256
]
=
{
0
};
DWORD nSize
=
0
;
if
((DWORD)hDriver !
=
0xFFFFFFFF
)
{
if
(ReadFile(
hDriver,
szpTest,
strlen(szpTest),
&nSize,
NULL
))
{
TRACE(
"JJR:执行成功"
);
}
}
}
/
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
驱动层代码
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
/
/
驱动头文件
/
/
驱动名称格式\\DEVICE\\YOUR_DEVICE_NAME
/
/
驱动链接名称,格式为\\??\\YOUR_SYMBOLLINK_NAME
/
/
驱动派遣回调函数
NTSTATUS DriverIRPCtrl(PDEVICE_OBJECT obj, PIRP pIrp)
{
NTSTATUS status
=
STATUS_SUCCESS;
/
/
当前IO 栈,用于存放用户层调用时产生的IRP 事件
PIO_STACK_LOCATION pIoStackLocation
=
NULL;
/
/
获取用户层调用时产生的IRP 函数
pIoStackLocation
=
IoGetCurrentIrpStackLocation(pIrp);
/
/
判断IRP 事件类型
switch (pIoStackLocation
-
>MajorFunction)
{
case IRP_MJ_CREATE:
{
/
/
用户层使用CreateFile 调用驱动
KdPrint((
"JJR:用户层调用CreateFile 开启对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_CLOSE:
{
/
/
用户层使用CloseHandle 结束驱动调用
KdPrint((
"JJR:用户层调用CLoseHandle 结束对驱动的调用"
));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_DEVICE_CONTROL:
{
/
/
获取控制码
ULONG funcCode
=
pIoStackLocation
-
>Parameters.DeviceIoControl.IoControlCode;
if
(funcCode
=
=
IO_TEST_CODE)
{
KdPrint((
"JJR:用户层调用了DeviceIoControl 函数"
));
/
/
取出传入的缓冲区数据和大小
char
*
inBuffer
=
(char
*
)pIrp
-
>AssociatedIrp.SystemBuffer;
KdPrint((
"JJR:用户层传入数据:%s"
, inBuffer));
/
/
inBuffer 既是传入数据的缓冲区,也是传出数据的缓冲区
strcpy(inBuffer,
"驱动层传出数据"
);
}
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
/
/
实际传出缓冲区的大小
pIrp
-
>IoStatus.Information
=
pIoStackLocation
-
>Parameters.DeviceIoControl.InputBufferLength;
};
break
;
case IRP_MJ_WRITE:
{
KdPrint((
"JJR:用户层调用了WriteFile 函数"
));
char
*
inBuffer
=
(char
*
)pIrp
-
>UserBuffer;
KdPrint((
"JJR:传递的数据>> %s"
, inBuffer));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
};
break
;
case IRP_MJ_READ:
{
KdPrint((
"JJR:用户层调用了ReadFile 函数"
));
char
*
inBuffer
=
(char
*
)pIrp
-
>UserBuffer;
KdPrint((
"JJR:传递的数据>> %s"
, inBuffer));
pIrp
-
>IoStatus.Status
=
STATUS_SUCCESS;
pIrp
-
>IoStatus.Information
=
4
;
}
default:
break
;
}
KdPrint((
"JJR:退出派遣函数"
));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return
status;
}
void DriverUnload(PDRIVER_OBJECT obj)
{
/
/
删除符号链接
/
/
符号链接名称
UNICODE_STRING SymbolLinkName;
RtlInitUnicodeString(&SymbolLinkName, DRIVER_SYMBOLLINK_NAME);
IoDeleteSymbolicLink(&SymbolLinkName);
/
/
删除驱动设备
/
/
这里驱动对象所包含的设备对象与我们创建的设备对象是同一个对象
IoDeleteDevice(obj
-
>DeviceObject);
KdPrint((
"JJR:驱动卸载函数启动"
));
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!